func (c *funcContext) translateType(o *types.TypeName, toplevel bool) { typeName := c.objectName(o) lhs := typeName if toplevel { lhs += " = $pkg." + o.Name() } size := int64(0) constructor := "null" switch t := o.Type().Underlying().(type) { case *types.Struct: params := make([]string, t.NumFields()) for i := 0; i < t.NumFields(); i++ { params[i] = fieldName(t, i) + "_" } constructor = fmt.Sprintf("function(%s) {\n%sthis.$val = this;\n", strings.Join(params, ", "), strings.Repeat("\t", c.p.indentation+1)) for i := 0; i < t.NumFields(); i++ { name := fieldName(t, i) constructor += fmt.Sprintf("%sthis.%s = %s_ !== undefined ? %s_ : %s;\n", strings.Repeat("\t", c.p.indentation+1), name, name, name, c.zeroValue(t.Field(i).Type())) } constructor += strings.Repeat("\t", c.p.indentation) + "}" case *types.Basic, *types.Array, *types.Slice, *types.Chan, *types.Signature, *types.Interface, *types.Pointer, *types.Map: size = sizes32.Sizeof(t) } c.Printf(`%s = $newType(%d, "%s", "%s.%s", "%s", "%s", %s);`, lhs, size, typeKind(o.Type()), o.Pkg().Name(), o.Name(), o.Name(), o.Pkg().Path(), constructor) }
func (w *Walker) emitType(obj *types.TypeName) { name := obj.Name() typ := obj.Type() switch typ := typ.Underlying().(type) { case *types.Struct: w.emitStructType(name, typ) case *types.Interface: w.emitIfaceType(name, typ) return // methods are handled by emitIfaceType default: w.emitf("type %s %s", name, w.typeString(typ.Underlying())) } // emit methods with value receiver var methodNames map[string]bool vset := typ.MethodSet() for i, n := 0, vset.Len(); i < n; i++ { m := vset.At(i) if m.Obj().IsExported() { w.emitMethod(m) if methodNames == nil { methodNames = make(map[string]bool) } methodNames[m.Obj().Name()] = true } } // emit methods with pointer receiver; exclude // methods that we have emitted already // (the method set of *T includes the methods of T) pset := types.NewPointer(typ).MethodSet() for i, n := 0, pset.Len(); i < n; i++ { m := pset.At(i) if m.Obj().IsExported() && !methodNames[m.Obj().Name()] { w.emitMethod(m) } } }
func (a *analysis) namedType(obj *types.TypeName, implements map[*types.Named]implementsFacts) { this := obj.Pkg() T := obj.Type().(*types.Named) v := &TypeInfoJSON{ Name: obj.Name(), Size: sizes.Sizeof(T), Align: sizes.Alignof(T), Methods: []anchorJSON{}, // (JS wants non-nil) } // addFact adds the fact "is implemented by T" (by) or // "implements T" (!by) to group. addFact := func(group *implGroupJSON, T types.Type, by bool) { Tobj := deref(T).(*types.Named).Obj() var byKind string if by { // Show underlying kind of implementing type, // e.g. "slice", "array", "struct". s := reflect.TypeOf(T.Underlying()).String() byKind = strings.ToLower(strings.TrimPrefix(s, "*types.")) } group.Facts = append(group.Facts, implFactJSON{ ByKind: byKind, Other: anchorJSON{ Href: a.posURL(Tobj.Pos(), len(Tobj.Name())), Text: types.TypeString(this, T), }, }) } // IMPLEMENTS if r, ok := implements[T]; ok { if isInterface(T) { // "T is implemented by <conc>" ... // "T is implemented by <iface>"... // "T implements <iface>"... group := implGroupJSON{ Descr: types.TypeString(this, T), } // Show concrete types first; use two passes. for _, sub := range r.to { if !isInterface(sub) { addFact(&group, sub, true) } } for _, sub := range r.to { if isInterface(sub) { addFact(&group, sub, true) } } for _, super := range r.from { addFact(&group, super, false) } v.ImplGroups = append(v.ImplGroups, group) } else { // T is concrete. if r.from != nil { // "T implements <iface>"... group := implGroupJSON{ Descr: types.TypeString(this, T), } for _, super := range r.from { addFact(&group, super, false) } v.ImplGroups = append(v.ImplGroups, group) } if r.fromPtr != nil { // "*C implements <iface>"... group := implGroupJSON{ Descr: "*" + types.TypeString(this, T), } for _, psuper := range r.fromPtr { addFact(&group, psuper, false) } v.ImplGroups = append(v.ImplGroups, group) } } } // METHOD SETS for _, sel := range typeutil.IntuitiveMethodSet(T, &a.prog.MethodSets) { meth := sel.Obj().(*types.Func) pos := meth.Pos() // may be 0 for error.Error v.Methods = append(v.Methods, anchorJSON{ Href: a.posURL(pos, len(meth.Name())), Text: types.SelectionString(this, sel), }) } // Since there can be many specs per decl, we // can't attach the link to the keyword 'type' // (as we do with 'func'); we use the Ident. fi, offset := a.fileAndOffset(obj.Pos()) fi.addLink(aLink{ start: offset, end: offset + len(obj.Name()), title: fmt.Sprintf("type info for %s", obj.Name()), onclick: fmt.Sprintf("onClickTypeInfo(%d)", fi.addData(v)), }) // Add info for exported package-level types to the package info. if obj.Exported() && isPackageLevel(obj) { // TODO(adonovan): this.Path() is not unique! // It is possible to declare a non-test package called x_test. a.result.pkgInfo(this.Path()).addType(v) } }