func (c *converter) convertScope(dst *types.Scope, src *gotypes.Scope) { for _, name := range src.Names() { obj := src.Lookup(name) dst.Insert(c.convertObject(obj)) } for i := 0; i < src.NumChildren(); i++ { child := src.Child(i) newScope := types.NewScope(dst, token.Pos(child.Pos()), token.Pos(child.End()), "") c.convertScope(newScope, child) } }
// getTypeStruct will take a type and the package scope, and return the // (innermost) struct if the type is considered a RR type (currently defined as // those structs beginning with a RR_Header, could be redefined as implementing // the RR interface). The bool return value indicates if embedded structs were // resolved. func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) { st, ok := t.Underlying().(*types.Struct) if !ok { return nil, false } if st.Field(0).Type() == scope.Lookup("RR_Header").Type() { return st, false } if st.Field(0).Anonymous() { st, _ := getTypeStruct(st.Field(0).Type(), scope) return st, true } return nil, false }
func analyzeCode(scope *types.Scope, docs *doc.Package, variable string) (imports.Importer, []fn, error) { pkg := docs.Name v, ok := scope.Lookup(variable).(*types.Var) if v == nil { return nil, nil, fmt.Errorf("impossible to find variable %s", variable) } if !ok { return nil, nil, fmt.Errorf("%s must be a variable", variable) } var vType interface { NumMethods() int Method(int) *types.Func } switch t := v.Type().(type) { case *types.Interface: vType = t case *types.Pointer: vType = t.Elem().(*types.Named) case *types.Named: vType = t if t, ok := t.Underlying().(*types.Interface); ok { vType = t } default: return nil, nil, fmt.Errorf("variable is of an invalid type: %T", v.Type().Underlying()) } importer := imports.New(pkg) var funcs []fn for i := 0; i < vType.NumMethods(); i++ { f := vType.Method(i) if !f.Exported() { continue } sig := f.Type().(*types.Signature) funcs = append(funcs, fn{ WrappedVar: variable, Name: f.Name(), CurrentPkg: pkg, TypeInfo: f, }) importer.AddImportsFrom(sig.Params()) importer.AddImportsFrom(sig.Results()) } return importer, funcs, nil }
func (c *Suggester) scopeCandidates(scope *types.Scope, pos token.Pos, b *candidateCollector) { seen := make(map[string]bool) for scope != nil { isPkgScope := scope.Parent() == types.Universe for _, name := range scope.Names() { if seen[name] { continue } obj := scope.Lookup(name) if !isPkgScope && obj.Pos() > pos { continue } seen[name] = true b.appendObject(obj) } scope = scope.Parent() } }
func extractTestFunctions(scope *types.Scope) []string { var tests []string for _, name := range scope.Names() { if !strings.HasPrefix(name, "Test") { continue } if f, ok := scope.Lookup(name).(*types.Func); ok { sig := f.Type().(*types.Signature) // basic signature checks if sig.Recv() != nil { log.Printf("Skipping %q - test function should not be a method", f.String()) continue } if sig.Variadic() { log.Printf("Skipping %q - test function should not be variadic", f.String()) continue } if sig.Results() != nil { log.Printf("Skipping %q - test function should not return result", f.String()) continue } // check params params := sig.Params() if params != nil || params.Len() == 1 { if named, ok := params.At(0).Type().(*types.Named); ok { if named.Obj().Name() == "TestingT" { tests = append(tests, f.Name()) continue } } } log.Printf("Skipping %q - test function should have one parameter of type gophers.TestingT", f.String()) } } return tests }
// analyzeCode takes the types scope and the docs and returns the import // information and information about all the assertion functions. func analyzeCode(scope *types.Scope, docs *doc.Package) (imports.Importer, []testFunc, error) { testingT := scope.Lookup("TestingT").Type().Underlying().(*types.Interface) importer := imports.New(*outputPkg) var funcs []testFunc // Go through all the top level functions for _, fdocs := range docs.Funcs { // Find the function obj := scope.Lookup(fdocs.Name) fn, ok := obj.(*types.Func) if !ok { continue } // Check function signatuer has at least two arguments sig := fn.Type().(*types.Signature) if sig.Params().Len() < 2 { continue } // Check first argument is of type testingT first, ok := sig.Params().At(0).Type().(*types.Named) if !ok { continue } firstType, ok := first.Underlying().(*types.Interface) if !ok { continue } if !types.Implements(firstType, testingT) { continue } funcs = append(funcs, testFunc{*outputPkg, fdocs, fn}) importer.AddImportsFrom(sig.Params()) } return importer, funcs, nil }