func (f *File) methodSet(set *types.MethodSet) { // Build the set of things we're looking for. methods := make([]method, 0, set.Len()) docs := make([]string, set.Len()) for i := 0; i < set.Len(); i++ { if ast.IsExported(set.At(i).Obj().Name()) { m := method{ i, set.At(i), } methods = append(methods, m) } } if len(methods) == 0 { return } // Collect the docs. for _, file := range f.allFiles { visitor := &methodVisitor{ File: file, methods: methods, docs: docs, } ast.Walk(visitor, file.file) methods = visitor.methods } // Print them in order. The incoming method set is sorted by name. for _, doc := range docs { if doc != "" { fmt.Print(doc) } } }
// containsAllIdsOf reports whether the method identifiers of T are a // superset of those in U. If U belongs to an interface type, the // result is equal to types.Assignable(T, U), but is cheaper to compute. // // TODO(gri): make this a method of *types.MethodSet. // func containsAllIdsOf(T, U *types.MethodSet) bool { t, tlen := 0, T.Len() u, ulen := 0, U.Len() for t < tlen && u < ulen { tMeth := T.At(t).Obj() uMeth := U.At(u).Obj() tId := tMeth.Id() uId := uMeth.Id() if tId > uId { // U has a method T lacks: fail. return false } if tId < uId { // T has a method U lacks: ignore it. t++ continue } // U and T both have a method of this Id. Check types. if !types.Identical(tMeth.Type(), uMeth.Type()) { return false // type mismatch } u++ t++ } return u == ulen }
func (l langType) uncommonBuild(i int, sizes types.Sizes, name string, t types.Type) string { pkgPath := "" tt := t switch tt.(type) { case *types.Pointer: el, ok := tt.(*types.Pointer).Elem().(*types.Named) if ok { tt = el } } switch tt.(type) { case *types.Named: obj := tt.(*types.Named).Obj() if obj != nil { pkg := obj.Pkg() if pkg != nil { pkgPath = pkg.Path() } } } var methods *types.MethodSet numMethods := 0 methods = l.PogoComp().MethodSetFor(t) numMethods = methods.Len() if name != "" || numMethods > 0 { ret := "Go_haxegoruntime_newPPtrTToUUncommonTType.callFromRT(0,\n" ret += "\t\t/*name:*/ \"" + name + "\",\n" ret += "\t\t/*pkgPath:*/ \"" + pkgPath + "\",\n" ret += "\t\t/*methods:*/ " meths := "Go_haxegoruntime_newMMethodSSlice.callFromRT(0)" //_, isIF := t.Underlying().(*types.Interface) //if !isIF { for m := 0; m < numMethods; m++ { sel := methods.At(m) ssaFn := l.PogoComp().RootProgram().Method(sel) if l.PogoComp().FnIsCalled(ssaFn) { fn := "null" fnToCall := "null" var name, str, path string fid, haveFn := l.hc.pte.At(sel.Obj().Type()).(int) if haveFn { fn = fmt.Sprintf("type%d()", fid) } name = sel.Obj().Name() str = sel.String() funcObj, ok := sel.Obj().(*types.Func) if ok { pn := "unknown" if funcObj.Pkg() != nil { pn = sel.Obj().Pkg().Name() path = sel.Obj().Pkg().Path() } fnToCall = `Go_` + l.LangName( pn+":"+sel.Recv().String(), funcObj.Name()) } // now write out the method information meths = "Go_haxegoruntime_addMMethod.callFromRT(0," + meths + ",\n" meths += fmt.Sprintf("\n\t\t\t/*name:*/ \"%s\", // %s\n", name, str) rune1, _ := utf8.DecodeRune([]byte(name)) if unicode.IsUpper(rune1) { path = "" } meths += fmt.Sprintf("\t\t\t/*pkgPath:*/ \"%s\",\n", path) // TODO should the two lines below be different? meths += fmt.Sprintf("\t\t\t/*mtyp:*/ %s,\n", fn) meths += fmt.Sprintf("\t\t\t/*typ:*/ %s,\n", fn) // add links to the functions ... if l.hc.funcNamesUsed[fnToCall] { fnToCall += ".call" } else { //println("DEBUG uncommonBuild function name not found: ", fnToCall) fnToCall = "null /* " + fnToCall + " */ " } meths += "\t\t\t" + fnToCall + "," + fnToCall + ")" } } //} ret += meths return ret + "\t)" } return "null" }