func (x *exporter) exportObject(obj types.Object) { switch t := obj.(type) { case *types.Var: if !obj.IsExported() { return } x.write("\tvar @\"\".%s ", obj.Name()) x.exportName(obj.Type()) x.write("\n") case *types.Func: sig := t.Type().(*types.Signature) recv := sig.Recv() if recv == nil && !t.IsExported() { return // The package "go/ast" has an interface "Decl" (http://golang.org/pkg/go/ast/#Decl) // containing "filtered or unexported methods", specifically a method named "declNode". // // No implementation of that method actually does anything, but it forces type // correctness and also disallows other packages from defining new types that // satisfies that interface. // // As the interface is exported and the types implementing the interface are too, // "declNode" must be exported to be able to properly type check any code that type // casts from and to that interface. // // To be clear; exporting *all* receiver methods is a superset of the methods // that must be exported. } x.write("\tfunc ") if recv != nil { x.write("(") x.exportName(recv) x.write(") ") } x.write(`@"".%s`, t.Name()) x.writeFunc = false x.exportName(sig) x.write("\n") case *types.Const: if !t.IsExported() { return } x.write("\tconst @\"\".%s ", t.Name()) x.exportName(t.Type()) x.write(" = ") x.exportName(t.Val()) x.write("\n") case *types.TypeName: // Some types that are not exported outside of the package actually // need to be exported for the compiler. // // An example would be a package having an exported struct type // that has a member variable of some unexported type: // // As declaring variables of the exported struct type is allowed // outside of the package, the compiler needs to know the size // of the struct. // // To be clear; exporting *all* types is a superset of the types // that must be exported. x.write("\ttype @\"\".%s ", obj.Name()) x.exportName(obj.Type().Underlying()) x.write("\n") if u, ok := obj.Type().(*types.Named); ok { for i := 0; i < u.NumMethods(); i++ { m := u.Method(i) x.exportObject(m) } } default: panic(fmt.Sprintf("UNHANDLED %T", t)) } }