Пример #1
0
// deeper reports whether block x is lexically deeper than y.
func deeper(x, y *types.Scope) bool {
	if x == y || x == nil {
		return false
	} else if y == nil {
		return true
	} else {
		return deeper(x.Parent(), y.Parent())
	}
}
Пример #2
0
// 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
}
Пример #3
0
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
}
Пример #4
0
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)
	}
}
Пример #5
0
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
}
Пример #6
0
// 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
}
Пример #7
0
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()
	}
}