示例#1
0
文件: reflect.go 项目: tsandall/opa
func initReflect(i *interpreter) {
	i.reflectPackage = &ssa.Package{
		Prog:    i.prog,
		Pkg:     reflectTypesPackage,
		Members: make(map[string]ssa.Member),
	}

	// Clobber the type-checker's notion of reflect.Value's
	// underlying type so that it more closely matches the fake one
	// (at least in the number of fields---we lie about the type of
	// the rtype field).
	//
	// We must ensure that calls to (ssa.Value).Type() return the
	// fake type so that correct "shape" is used when allocating
	// variables, making zero values, loading, and storing.
	//
	// TODO(adonovan): obviously this is a hack.  We need a cleaner
	// way to fake the reflect package (almost---DeepEqual is fine).
	// One approach would be not to even load its source code, but
	// provide fake source files.  This would guarantee that no bad
	// information leaks into other packages.
	if r := i.prog.ImportedPackage("reflect"); r != nil {
		rV := r.Pkg.Scope().Lookup("Value").Type().(*types.Named)

		// delete bodies of the old methods
		mset := i.prog.MethodSets.MethodSet(rV)
		for j := 0; j < mset.Len(); j++ {
			i.prog.MethodValue(mset.At(j)).Blocks = nil
		}

		tEface := types.NewInterface(nil, nil).Complete()
		rV.SetUnderlying(types.NewStruct([]*types.Var{
			types.NewField(token.NoPos, r.Pkg, "t", tEface, false), // a lie
			types.NewField(token.NoPos, r.Pkg, "v", tEface, false),
		}, nil))
	}

	i.rtypeMethods = methodSet{
		"Bits":      newMethod(i.reflectPackage, rtypeType, "Bits"),
		"Elem":      newMethod(i.reflectPackage, rtypeType, "Elem"),
		"Field":     newMethod(i.reflectPackage, rtypeType, "Field"),
		"In":        newMethod(i.reflectPackage, rtypeType, "In"),
		"Kind":      newMethod(i.reflectPackage, rtypeType, "Kind"),
		"NumField":  newMethod(i.reflectPackage, rtypeType, "NumField"),
		"NumIn":     newMethod(i.reflectPackage, rtypeType, "NumIn"),
		"NumMethod": newMethod(i.reflectPackage, rtypeType, "NumMethod"),
		"NumOut":    newMethod(i.reflectPackage, rtypeType, "NumOut"),
		"Out":       newMethod(i.reflectPackage, rtypeType, "Out"),
		"Size":      newMethod(i.reflectPackage, rtypeType, "Size"),
		"String":    newMethod(i.reflectPackage, rtypeType, "String"),
	}
	i.errorMethods = methodSet{
		"Error": newMethod(i.reflectPackage, errorType, "Error"),
	}
}
示例#2
0
文件: gcimporter.go 项目: vmware/vic
// Field = Name Type [ string_lit ] .
//
func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
	pkg, name := p.parseName(parent, true)
	typ := p.parseType(parent)
	anonymous := false
	if name == "" {
		// anonymous field - typ must be T or *T and T must be a type name
		switch typ := deref(typ).(type) {
		case *types.Basic: // basic types are named types
			pkg = nil // objects defined in Universe scope have no package
			name = typ.Name()
		case *types.Named:
			name = typ.Obj().Name()
		default:
			p.errorf("anonymous field expected")
		}
		anonymous = true
	}
	tag := ""
	if p.tok == scanner.String {
		s := p.expect(scanner.String)
		var err error
		tag, err = strconv.Unquote(s)
		if err != nil {
			p.errorf("invalid struct tag %s: %s", s, err)
		}
	}
	return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag
}
示例#3
0
func (p *importer) field() *types.Var {
	pkg, name := p.qualifiedName()
	typ := p.typ()

	anonymous := false
	if name == "" {
		// anonymous field - typ must be T or *T and T must be a type name
		switch typ := deref(typ).(type) {
		case *types.Basic: // basic types are named types
			pkg = nil
			name = typ.Name()
		case *types.Named:
			obj := typ.Obj()
			name = obj.Name()
			// correct the field package for anonymous fields
			if exported(name) {
				pkg = p.pkgList[0]
			}
		default:
			panic("anonymous field expected")
		}
		anonymous = true
	}

	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
}
示例#4
0
// Field = Name Type [ string_lit ] .
//
func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
	pkg, name := p.parseName(parent, true)

	if name == "_" {
		// Blank fields should be package-qualified because they
		// are unexported identifiers, but gc does not qualify them.
		// Assuming that the ident belongs to the current package
		// causes types to change during re-exporting, leading
		// to spurious "can't assign A to B" errors from go/types.
		// As a workaround, pretend all blank fields belong
		// to the same unique dummy package.
		const blankpkg = "<_>"
		pkg = p.getPkg(blankpkg, blankpkg)
	}

	typ := p.parseType(parent)
	anonymous := false
	if name == "" {
		// anonymous field - typ must be T or *T and T must be a type name
		switch typ := deref(typ).(type) {
		case *types.Basic: // basic types are named types
			pkg = nil // objects defined in Universe scope have no package
			name = typ.Name()
		case *types.Named:
			name = typ.Obj().Name()
		default:
			p.errorf("anonymous field expected")
		}
		anonymous = true
	}
	tag := ""
	if p.tok == scanner.String {
		s := p.expect(scanner.String)
		var err error
		tag, err = strconv.Unquote(s)
		if err != nil {
			p.errorf("invalid struct tag %s: %s", s, err)
		}
	}
	return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag
}
func (p *importer) field(parent *types.Package) *types.Var {
	pkg, name := p.fieldName(parent)
	typ := p.typ(parent)

	anonymous := false
	if name == "" {
		// anonymous field - typ must be T or *T and T must be a type name
		switch typ := deref(typ).(type) {
		case *types.Basic: // basic types are named types
			pkg = nil // // objects defined in Universe scope have no package
			name = typ.Name()
		case *types.Named:
			name = typ.Obj().Name()
		default:
			panic("anonymous field expected")
		}
		anonymous = true
	}

	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
}
示例#6
0
// Field = Name Type [string] .
func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) {
	name := p.parseName()
	typ := p.parseType(pkg)
	anon := false
	if name == "" {
		anon = true
		switch typ := deref(typ).(type) {
		case *types.Basic:
			name = typ.Name()
		case *types.Named:
			name = typ.Obj().Name()
		default:
			p.error("anonymous field expected")
		}
	}
	field = types.NewField(token.NoPos, pkg, name, typ, anon)
	if p.tok == scanner.String {
		tag = p.parseString()
	}
	return
}
示例#7
0
文件: bimport.go 项目: jacobsa/go
func (p *importer) field() *types.Var {
	pkg, name := p.fieldName()
	typ := p.typ()

	anonymous := false
	if name == "" {
		// anonymous field - typ must be T or *T and T must be a type name
		switch typ := deref(typ).(type) {
		case *types.Basic: // basic types are named types
			name = typ.Name()
		case *types.Named:
			pkg = p.pkgList[0]
			name = typ.Obj().Name()
		default:
			panic("anonymous field expected")
		}
		anonymous = true
	}

	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
}
示例#8
0
文件: gokit-gen.go 项目: sasha-s/kit
// t is a tuple for representing parameters or return values of  function.
func (g *generator) parse(name string, t *types.Tuple) *args {
	ps := toList(t)
	var fields []*types.Var
	var tags []string
	imports := map[types.Object]*ast.SelectorExpr{}
	un := uniqueNames{}
	m := &args{}
	for _, p := range ps {
		n := p.Name()
		if n == "" {
			n = p.Type().String()
			if !validIdentifier(n) {
				n = "p"
			}
		}
		n = un.get(capitalize(n))
		t := types.NewField(0, g.pkg, n, p.Type(), false)
		// Filter out context and error.
		switch p.Type().String() {
		case "golang.org/x/net/context.Context":
			ctxName := un.get("ctx")
			m.Args = append(m.Args, func(string) string { return ctxName })
			m.CtxName = ctxName
			m.HasCtx = true
			m.Args2 = append(m.Args2, struct{ Name, Type string }{ctxName, types.TypeString(t.Type(), relativeTo(g.pkg))})
			continue
		case "error":
			errName := un.get("err")
			m.Args = append(m.Args, func(string) string { return errName })
			m.ErrName = errName
			m.HasErr = true
			m.Args2 = append(m.Args2, struct{ Name, Type string }{errName, types.TypeString(t.Type(), relativeTo(g.pkg))})
			continue
		}
		m.Args2 = append(m.Args2, struct{ Name, Type string }{uncapitalize(n), types.TypeString(t.Type(), relativeTo(g.pkg))})
		updateDeps(g.rev[p.Type()], g.info, imports)
		// Make sure all the names are unique.
		m.Args = append(m.Args, func(s string) string { return fmt.Sprintf("%s.%s", s, n) })
		fields = append(fields, t)
		tags = append(tags, fmt.Sprintf(`json:"%s"`, toSnake(n)))
	}
	if !m.HasCtx {
		m.CtxName = un.get("ctx")
	}
	if !m.HasErr {
		m.ErrName = un.get("err")
	}
	imps := cleanImports(imports)
	m.StructDef = structDef{
		Pkg:     g.pkg.Name(),
		Imports: imps,
		Name:    name,
	}
	for i, v := range fields {
		m.StructDef.Fields = append(m.StructDef.Fields, struct {
			Name string
			Tag  string
			Type string
		}{
			Name: v.Name(),
			Type: types.TypeString(v.Type(), relativeTo(g.pkg)),
			Tag:  tags[i],
		})
	}
	return m
}