func (c *funcContext) typeName(ty types.Type) string { switch t := ty.(type) { case *types.Basic: return "$" + toJavaScriptType(t) case *types.Named: if t.Obj().Name() == "error" { return "$error" } return c.objectName(t.Obj()) case *types.Interface: if t.Empty() { return "$emptyInterface" } } anonType, ok := c.p.anonTypeMap.At(ty).(*types.TypeName) if !ok { c.initArgs(ty) // cause all embedded types to be registered varName := c.newVariableWithLevel(strings.ToLower(typeKind(ty)[5:])+"Type", true) anonType = types.NewTypeName(token.NoPos, c.p.Pkg, varName, ty) // fake types.TypeName c.p.anonTypes = append(c.p.anonTypes, anonType) c.p.anonTypeMap.Set(ty, anonType) } c.p.dependencies[anonType] = true return anonType.Name() }
// TestDevendorizeImportPaths checks if vendored // import paths are devendorized correctly. func TestDevendorizeImportPaths(t *testing.T) { i := imports.New("github.com/ernesto-jimenez/gogen/imports") pkg := types.NewPackage("github.com/ernesto-jimenez/gogen/vendor/github.com/stretchr/testify/mock", "mock") named := types.NewNamed(types.NewTypeName(token.Pos(0), pkg, "", &types.Array{}), &types.Array{}, nil) i.AddImportsFrom(named) require.Equal(t, map[string]string{"github.com/stretchr/testify/mock": "mock"}, i.Imports()) }
func declTypeName(pkg *types.Package, name string) *types.TypeName { scope := pkg.Scope() if obj := scope.Lookup(name); obj != nil { return obj.(*types.TypeName) } obj := types.NewTypeName(token.NoPos, pkg, name, nil) // a named type may be referred to before the underlying type // is known - set it up types.NewNamed(obj, nil, nil) scope.Insert(obj) return obj }
// TypeName = ExportedName . func (p *parser) parseTypeName() *types.TypeName { pkg, name := p.parseExportedName() scope := pkg.Scope() if obj := scope.Lookup(name); obj != nil { return obj.(*types.TypeName) } obj := types.NewTypeName(token.NoPos, pkg, name, nil) // a named type may be referred to before the underlying type // is known - set it up types.NewNamed(obj, nil, nil) scope.Insert(obj) return obj }
// parent is the package which declared the type; parent == nil means // the package currently imported. The parent package is needed for // exported struct fields and interface methods which don't contain // explicit package information in the export data. func (p *importer) typ(parent *types.Package) types.Type { // if the type was seen before, i is its index (>= 0) i := p.tagOrIndex() if i >= 0 { return p.typList[i] } // otherwise, i is the type tag (< 0) switch i { case namedTag: // read type object name := p.string() parent = p.pkg() scope := parent.Scope() obj := scope.Lookup(name) // if the object doesn't exist yet, create and insert it if obj == nil { obj = types.NewTypeName(token.NoPos, parent, name, nil) scope.Insert(obj) } if _, ok := obj.(*types.TypeName); !ok { panic(fmt.Sprintf("pkg = %s, name = %s => %s", parent, name, obj)) } // associate new named type with obj if it doesn't exist yet t0 := types.NewNamed(obj.(*types.TypeName), nil, nil) // but record the existing type, if any t := obj.Type().(*types.Named) p.record(t) // read underlying type t0.SetUnderlying(p.typ(parent)) // interfaces don't have associated methods if _, ok := t0.Underlying().(*types.Interface); ok { return t } // read associated methods for i := p.int(); i > 0; i-- { name := p.string() recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver? params, isddd := p.paramList() result, _ := p.paramList() p.int() // read and discard index of inlined function body sig := types.NewSignature(recv.At(0), params, result, isddd) t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig)) } return t case arrayTag: t := new(types.Array) p.record(t) n := p.int64() *t = *types.NewArray(p.typ(parent), n) return t case sliceTag: t := new(types.Slice) p.record(t) *t = *types.NewSlice(p.typ(parent)) return t case dddTag: t := new(dddSlice) p.record(t) t.elem = p.typ(parent) return t case structTag: t := new(types.Struct) p.record(t) n := p.int() fields := make([]*types.Var, n) tags := make([]string, n) for i := range fields { fields[i] = p.field(parent) tags[i] = p.string() } *t = *types.NewStruct(fields, tags) return t case pointerTag: t := new(types.Pointer) p.record(t) *t = *types.NewPointer(p.typ(parent)) return t case signatureTag: t := new(types.Signature) p.record(t) params, isddd := p.paramList() result, _ := p.paramList() *t = *types.NewSignature(nil, params, result, isddd) return t case interfaceTag: // Create a dummy entry in the type list. This is safe because we // cannot expect the interface type to appear in a cycle, as any // such cycle must contain a named type which would have been // first defined earlier. n := len(p.typList) p.record(nil) // no embedded interfaces with gc compiler if p.int() != 0 { panic("unexpected embedded interface") } // read methods methods := make([]*types.Func, p.int()) for i := range methods { pkg, name := p.fieldName(parent) params, isddd := p.paramList() result, _ := p.paramList() sig := types.NewSignature(nil, params, result, isddd) methods[i] = types.NewFunc(token.NoPos, pkg, name, sig) } t := types.NewInterface(methods, nil) p.typList[n] = t return t case mapTag: t := new(types.Map) p.record(t) key := p.typ(parent) val := p.typ(parent) *t = *types.NewMap(key, val) return t case chanTag: t := new(types.Chan) p.record(t) var dir types.ChanDir // tag values must match the constants in cmd/compile/internal/gc/go.go switch d := p.int(); d { case 1 /* Crecv */ : dir = types.RecvOnly case 2 /* Csend */ : dir = types.SendOnly case 3 /* Cboth */ : dir = types.SendRecv default: panic(fmt.Sprintf("unexpected channel dir %d", d)) } val := p.typ(parent) *t = *types.NewChan(dir, val) return t default: panic(fmt.Sprintf("unexpected type tag %d", i)) } }
// parent is the package which declared the type; parent == nil means // the package currently imported. The parent package is needed for // exported struct fields and interface methods which don't contain // explicit package information in the export data. func (p *importer) typ(parent *types.Package) types.Type { // if the type was seen before, i is its index (>= 0) i := p.tagOrIndex() if i >= 0 { return p.typList[i] } // otherwise, i is the type tag (< 0) switch i { case namedTag: // read type object pos := p.pos() parent, name := p.qualifiedName() scope := parent.Scope() obj := scope.Lookup(name) // if the object doesn't exist yet, create and insert it if obj == nil { obj = types.NewTypeName(pos, parent, name, nil) scope.Insert(obj) } if _, ok := obj.(*types.TypeName); !ok { errorf("pkg = %s, name = %s => %s", parent, name, obj) } // associate new named type with obj if it doesn't exist yet t0 := types.NewNamed(obj.(*types.TypeName), nil, nil) // but record the existing type, if any t := obj.Type().(*types.Named) p.record(t) // read underlying type t0.SetUnderlying(p.typ(parent)) // interfaces don't have associated methods if types.IsInterface(t0) { return t } // read associated methods for i := p.int(); i > 0; i-- { // TODO(gri) replace this with something closer to fieldName pos := p.pos() name := p.string() if !exported(name) { p.pkg() } recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver? params, isddd := p.paramList() result, _ := p.paramList() p.int() // go:nointerface pragma - discarded sig := types.NewSignature(recv.At(0), params, result, isddd) t0.AddMethod(types.NewFunc(pos, parent, name, sig)) } return t case arrayTag: t := new(types.Array) if p.trackAllTypes { p.record(t) } n := p.int64() *t = *types.NewArray(p.typ(parent), n) return t case sliceTag: t := new(types.Slice) if p.trackAllTypes { p.record(t) } *t = *types.NewSlice(p.typ(parent)) return t case dddTag: t := new(dddSlice) if p.trackAllTypes { p.record(t) } t.elem = p.typ(parent) return t case structTag: t := new(types.Struct) if p.trackAllTypes { p.record(t) } *t = *types.NewStruct(p.fieldList(parent)) return t case pointerTag: t := new(types.Pointer) if p.trackAllTypes { p.record(t) } *t = *types.NewPointer(p.typ(parent)) return t case signatureTag: t := new(types.Signature) if p.trackAllTypes { p.record(t) } params, isddd := p.paramList() result, _ := p.paramList() *t = *types.NewSignature(nil, params, result, isddd) return t case interfaceTag: // Create a dummy entry in the type list. This is safe because we // cannot expect the interface type to appear in a cycle, as any // such cycle must contain a named type which would have been // first defined earlier. n := len(p.typList) if p.trackAllTypes { p.record(nil) } // no embedded interfaces with gc compiler if p.int() != 0 { errorf("unexpected embedded interface") } t := types.NewInterface(p.methodList(parent), nil) if p.trackAllTypes { p.typList[n] = t } return t case mapTag: t := new(types.Map) if p.trackAllTypes { p.record(t) } key := p.typ(parent) val := p.typ(parent) *t = *types.NewMap(key, val) return t case chanTag: t := new(types.Chan) if p.trackAllTypes { p.record(t) } var dir types.ChanDir // tag values must match the constants in cmd/compile/internal/gc/go.go switch d := p.int(); d { case 1 /* Crecv */ : dir = types.RecvOnly case 2 /* Csend */ : dir = types.SendOnly case 3 /* Cboth */ : dir = types.SendRecv default: errorf("unexpected channel dir %d", d) } val := p.typ(parent) *t = *types.NewChan(dir, val) return t default: errorf("unexpected type tag %d", i) // panics panic("unreachable") } }
func (p *importer) typ() types.Type { // if the type was seen before, i is its index (>= 0) i := p.int() if i >= 0 { return p.typList[i] } // otherwise, i is the type tag (< 0) switch i { case arrayTag: t := new(types.Array) p.record(t) n := p.int64() *t = *types.NewArray(p.typ(), n) return t case sliceTag: t := new(types.Slice) p.record(t) *t = *types.NewSlice(p.typ()) return t case structTag: t := new(types.Struct) p.record(t) n := p.int() fields := make([]*types.Var, n) tags := make([]string, n) for i := range fields { fields[i] = p.field() tags[i] = p.string() } *t = *types.NewStruct(fields, tags) return t case pointerTag: t := new(types.Pointer) p.record(t) *t = *types.NewPointer(p.typ()) return t case signatureTag: t := new(types.Signature) p.record(t) *t = *p.signature() return t case interfaceTag: // Create a dummy entry in the type list. This is safe because we // cannot expect the interface type to appear in a cycle, as any // such cycle must contain a named type which would have been // first defined earlier. n := len(p.typList) p.record(nil) // read embedded interfaces embeddeds := make([]*types.Named, p.int()) for i := range embeddeds { embeddeds[i] = p.typ().(*types.Named) } // read methods methods := make([]*types.Func, p.int()) for i := range methods { pkg, name := p.qualifiedName() methods[i] = types.NewFunc(token.NoPos, pkg, name, p.typ().(*types.Signature)) } t := types.NewInterface(methods, embeddeds) p.typList[n] = t return t case mapTag: t := new(types.Map) p.record(t) *t = *types.NewMap(p.typ(), p.typ()) return t case chanTag: t := new(types.Chan) p.record(t) *t = *types.NewChan(types.ChanDir(p.int()), p.typ()) return t case namedTag: // read type object name := p.string() pkg := p.pkg() scope := pkg.Scope() obj := scope.Lookup(name) // if the object doesn't exist yet, create and insert it if obj == nil { obj = types.NewTypeName(token.NoPos, pkg, name, nil) scope.Insert(obj) } // associate new named type with obj if it doesn't exist yet t0 := types.NewNamed(obj.(*types.TypeName), nil, nil) // but record the existing type, if any t := obj.Type().(*types.Named) p.record(t) // read underlying type t0.SetUnderlying(p.typ()) // read associated methods for i, n := 0, p.int(); i < n; i++ { t0.AddMethod(types.NewFunc(token.NoPos, pkg, p.string(), p.typ().(*types.Signature))) } return t default: panic(fmt.Sprintf("unexpected type tag %d", i)) } }
func makeNamedType(name string, underlying types.Type) *types.Named { obj := types.NewTypeName(token.NoPos, reflectTypesPackage, name, nil) return types.NewNamed(obj, underlying, nil) }