func containsMethod(m *st.FunctionSymbol, sym st.ITypeSymbol) (bool, *errors.GoRefactorError) { candidate, ok := sym.Methods().LookUp(m.Name(), "") if !ok { return false, nil } cand, ok := candidate.(*st.FunctionSymbol) if !ok { panic("non-method symbol " + candidate.Name() + " in type " + sym.Name() + " methods()") } if !st.EqualsMethods(cand, m) { return true, &errors.GoRefactorError{ErrorType: "implement interface error", Message: "type has a method, named " + cand.Name() + "but it has signature, different from the necessary one"} } return true, nil }
func (mv *methodsVisitor) Visit(node ast.Node) (w ast.Visitor) { w = mv switch f := node.(type) { case *ast.FuncDecl: fft, cyc := st.GetBaseType(mv.Parser.parseTypeSymbol(f.Type)) if cyc { panic("unexpected cycle") } ft := fft.(*st.FunctionTypeSymbol) locals := st.NewSymbolTable(mv.Parser.Package) locals.AddOpenedScope(ft.Parameters) locals.AddOpenedScope(ft.Results) locals.AddOpenedScope(ft.Reciever) var basertype, rtype st.ITypeSymbol if f.Recv != nil { e_count := 0 for _, field := range f.Recv.List { basertype = mv.Parser.parseTypeSymbol(field.Type) if prtype, ok := basertype.(*st.PointerTypeSymbol); ok { rtype = prtype.BaseType } else { rtype = basertype } if mv.Parser.Package.AstPackage.Name == "os" { // fmt.Printf("###@@@### (%s) %s\n", rtype.Name(), f.Name.Name) } if rtype.Methods() == nil { panic("ok, this is a test panic") rtype.SetMethods(st.NewSymbolTable(mv.Parser.Package)) } if len(field.Names) == 0 { toAdd := st.MakeVariable("$unnamed receiver"+strconv.Itoa(e_count), ft.Reciever, basertype) ft.Reciever.AddSymbol(toAdd) e_count += 1 } for _, name := range field.Names { toAdd := st.MakeVariable(name.Name, ft.Reciever, basertype) mv.Parser.registerIdent(toAdd, name) ft.Reciever.AddSymbol(toAdd) } } } toAdd := st.MakeFunction(f.Name.Name, nil, ft) // Scope is set 5 lines down toAdd.Locals = locals mv.Parser.registerIdent(toAdd, f.Name) if f.Recv != nil { rtype.AddMethod(toAdd) toAdd.Scope_ = rtype.Methods() } else { mv.Parser.RootSymbolTable.AddSymbol(toAdd) toAdd.Scope_ = mv.Parser.RootSymbolTable } } return }