//Fixes Type and its' subtypes recursively func (pp *packageParser) fixType(sym st.Symbol) { if sym == nil { panic("error: fixing nil symbol") } if st.IsPredeclaredIdentifier(sym.Name()) { return } if sym.PackageFrom() != pp.Package { return } // fmt.Printf("%s fixing %v %T %p\n", pp.Package.AstPackage.Name, sym.Name(), sym, sym) if pp.checkIsVisited(sym) { return } //fmt.Printf("%s fixing %v %T %p\n", pp.Package.AstPackage.Name, sym.Name(), sym,sym) switch t := sym.(type) { case *st.AliasTypeSymbol: pp.fixAliasTypeSymbol(t) case *st.PointerTypeSymbol: pp.fixPointerTypeSymbol(t) case *st.ArrayTypeSymbol: pp.fixArrayTypeSymbol(t) case *st.StructTypeSymbol: pp.fixStructTypeSymbol(t) case *st.InterfaceTypeSymbol: pp.fixInterfaceTypeSymbol(t) case *st.MapTypeSymbol: pp.fixMapTypeSymbol(t) case *st.ChanTypeSymbol: pp.fixChanTypeSymbol(t) case *st.FunctionTypeSymbol: pp.fixFunctionTypeSymbol(t) case *st.VariableSymbol: pp.fixVariableSymbol(t) case *st.FunctionSymbol: pp.fixFunctionSymbol(t) } }
func (pp *packageParser) openMethodsAndFields(sym st.Symbol) { if pp.checkIsVisited(sym) { return } // fmt.Printf("opening %s %T from %s\n", sym.Name(), sym, func(p *st.Package) string { // if p == nil { // return "nil" // } // return p.AstPackage.Name // }(sym.PackageFrom())) if st.IsPredeclaredIdentifier(sym.Name()) { return } switch t := sym.(type) { case *st.ArrayTypeSymbol: pp.openMethodsAndFields(t.ElemType) case *st.ChanTypeSymbol: pp.openMethodsAndFields(t.ValueType) case *st.FunctionTypeSymbol: if t.Parameters != nil { t.Parameters.ForEachNoLock(func(sym st.Symbol) { v := sym.(*st.VariableSymbol) pp.openMethodsAndFields(v.VariableType) }) } if t.Results != nil { t.Results.ForEachNoLock(func(sym st.Symbol) { v := sym.(*st.VariableSymbol) pp.openMethodsAndFields(v.VariableType) }) } case *st.InterfaceTypeSymbol: if t.Meths != nil { t.Meths.ForEachNoLock(func(sym st.Symbol) { if _, ok := sym.(*st.FunctionSymbol); !ok { //EmbeddedInterface pp.openMethodsAndFields(sym) ts := sym.(*st.InterfaceTypeSymbol) t.Meths.AddOpenedScope(ts.Meths) //Delete functionSymbol which is now useles from interface t.Meths.RemoveSymbol(sym.Name()) } }) } case *st.MapTypeSymbol: pp.openMethodsAndFields(t.KeyType) pp.openMethodsAndFields(t.ValueType) case *st.StructTypeSymbol: // if t.Name() == "Package" { // fmt.Printf("YEAHHH YEAHHH %p\n", t) // } t.Fields.ForEachNoLock(func(variable st.Symbol) { if _, ok := variable.(*st.VariableSymbol); !ok { ts := variable.(st.ITypeSymbol) pp.openMethodsAndFields(ts) //Methods if ts.Methods() != nil { t.Methods().AddOpenedScope(ts.Methods()) } //Fields switch ttt := ts.(type) { case *st.StructTypeSymbol: t.Fields.AddOpenedScope(ttt.Fields) case *st.PointerTypeSymbol: t.Fields.AddOpenedScope(ttt.Fields) } //No longer need in type thumb, replace with var typeVar := st.MakeVariable(ts.Name(), t.Fields, ts) typeVar.Idents = ts.Identifiers() typeVar.Posits = ts.Positions() t.Fields.ReplaceSymbol(ts.Name(), typeVar) //replaces old one } }) case *st.PointerTypeSymbol: //fmt.Printf("%v %T \n", t.BaseType.Name(), t.BaseType) pp.openMethodsAndFields(t.BaseType) switch str := t.BaseType.(type) { case *st.StructTypeSymbol: t.Fields = str.Fields case *st.PointerTypeSymbol: t.Fields = str.Fields } if _, cyc := st.GetBaseType(t); cyc { // fmt.Printf("%s from %s\n", t.Name(), t.PackageFrom().AstPackage.Name) panic("cycle, don't work with that") } if t.BaseType.Methods() != nil { t.Methods().AddOpenedScope(t.BaseType.Methods()) } // if t.BaseType.Name() == "Package" { // fmt.Printf("YEAHHH YEAHHH %p %p\n", t, t.BaseType) // fmt.Println(*t.Methods().String()); // } pp.openMethodsAndFields(t.BaseType) } }
func Rename(filename string, line int, column int, newName string) (ok bool, err *errors.GoRefactorError) { if ok, err = CheckRenameParameters(filename, line, column, newName); !ok { return } programTree := parseProgram(filename) var sym st.Symbol if sym, err = programTree.FindSymbolByPosition(filename, line, column); err == nil { if _, ok := sym.(*st.PointerTypeSymbol); ok { panic("find by position returned pointer type!!!") } if st.IsPredeclaredIdentifier(sym.Name()) { return false, errors.UnrenamableIdentifierError(sym.Name(), " It's a basic language symbol") } if sym.PackageFrom().IsGoPackage { return false, errors.UnrenamableIdentifierError(sym.Name(), " It's a symbol,imported from go library") } if unicode.IsUpper(int(sym.Name()[0])) && !unicode.IsUpper(int(newName[0])) || unicode.IsLower(int(sym.Name()[0])) && !unicode.IsLower(int(newName[0])) { return false, &errors.GoRefactorError{ErrorType: "Can't rename identifier", Message: "can't change access modifier. Changing first letter's case can cause errors."} } if _, ok := sym.Scope().LookUp(newName, filename); ok { return false, errors.IdentifierAlreadyExistsError(newName) } if meth, ok := sym.(*st.FunctionSymbol); ok { if meth.IsInterfaceMethod { return false, errors.UnrenamableIdentifierError(sym.Name(), " It's an interface method") } } if ps, ok := sym.(*st.PackageSymbol); ok { pack, file := programTree.FindPackageAndFileByFilename(filename) impDecl := findImportDecl(pack, file, ps) if impDecl == nil { panic("couldn't find import decl") } if impDecl.Name == nil || impDecl.Name.Name == "" { impDecl.Name = ast.NewIdent(newName) } } fnames, fsets, files, err := renameSymbol(sym, newName, programTree) if err == nil { for i, f := range fnames { programTree.SaveFileExplicit(f, fsets[i], files[i]) } } return err == nil, err } else { return false, err } panic("unreachable code") }