2015-07-27 16:47:18 +00:00
|
|
|
// Copyright 2015 The go-python Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package bind
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"go/doc"
|
2015-11-16 11:54:02 +00:00
|
|
|
"go/types"
|
2015-08-05 13:32:41 +00:00
|
|
|
"reflect"
|
2015-07-27 16:47:18 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Package ties types.Package and ast.Package together.
|
2019-02-22 10:33:05 +00:00
|
|
|
// Package also collects information about specific types (structs, ifaces, etc)
|
2015-07-27 16:47:18 +00:00
|
|
|
type Package struct {
|
|
|
|
pkg *types.Package
|
2015-08-10 14:29:02 +00:00
|
|
|
n int // number of entities to wrap
|
2015-08-05 13:32:41 +00:00
|
|
|
sz types.Sizes
|
2015-07-27 16:47:18 +00:00
|
|
|
doc *doc.Package
|
|
|
|
|
2019-02-22 10:33:05 +00:00
|
|
|
syms *symtab // note: this is now *always* = symbols.current
|
2015-07-28 12:41:35 +00:00
|
|
|
objs map[string]Object
|
2019-02-24 21:17:35 +00:00
|
|
|
consts []*Const
|
|
|
|
vars []*Var
|
|
|
|
structs []*Struct
|
|
|
|
ifaces []*Interface
|
2019-03-02 10:30:58 +00:00
|
|
|
slices []*Slice
|
|
|
|
maps []*Map
|
2019-02-24 21:17:35 +00:00
|
|
|
funcs []*Func
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
|
|
|
|
2019-02-22 10:33:05 +00:00
|
|
|
// accumulates all the packages processed
|
|
|
|
var Packages []*Package
|
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
// NewPackage creates a new Package, tying types.Package and ast.Package together.
|
|
|
|
func NewPackage(pkg *types.Package, doc *doc.Package) (*Package, error) {
|
2019-02-22 10:33:05 +00:00
|
|
|
fmt.Printf("\n--- Processing package: %v ---\n", pkg.Path())
|
2015-08-05 13:32:41 +00:00
|
|
|
sz := int64(reflect.TypeOf(int(0)).Size())
|
2015-07-27 16:47:18 +00:00
|
|
|
p := &Package{
|
2015-07-28 12:41:53 +00:00
|
|
|
pkg: pkg,
|
2015-08-10 14:29:02 +00:00
|
|
|
n: 0,
|
2017-08-09 20:28:00 +00:00
|
|
|
sz: &types.StdSizes{WordSize: sz, MaxAlign: sz},
|
2015-07-28 12:41:53 +00:00
|
|
|
doc: doc,
|
2019-02-22 10:33:05 +00:00
|
|
|
syms: current,
|
2015-07-28 12:41:53 +00:00
|
|
|
objs: map[string]Object{},
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
|
|
|
err := p.process()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-02-22 10:33:05 +00:00
|
|
|
Packages = append(Packages, p)
|
2015-07-27 16:47:18 +00:00
|
|
|
return p, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Name returns the package name.
|
|
|
|
func (p *Package) Name() string {
|
|
|
|
return p.pkg.Name()
|
|
|
|
}
|
|
|
|
|
2015-08-06 16:32:30 +00:00
|
|
|
// ImportPath returns the package import path.
|
|
|
|
func (p *Package) ImportPath() string {
|
|
|
|
return p.doc.ImportPath
|
|
|
|
}
|
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
// getDoc returns the doc string associated with types.Object
|
|
|
|
// parent is the name of the containing scope ("" for global scope)
|
|
|
|
func (p *Package) getDoc(parent string, o types.Object) string {
|
|
|
|
n := o.Name()
|
|
|
|
switch o.(type) {
|
|
|
|
case *types.Const:
|
|
|
|
for _, c := range p.doc.Consts {
|
|
|
|
for _, cn := range c.Names {
|
|
|
|
if n == cn {
|
|
|
|
return c.Doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case *types.Var:
|
|
|
|
for _, v := range p.doc.Vars {
|
|
|
|
for _, vn := range v.Names {
|
|
|
|
if n == vn {
|
|
|
|
return v.Doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case *types.Func:
|
2019-02-19 09:46:15 +00:00
|
|
|
sig := o.Type().(*types.Signature)
|
2019-02-28 06:44:20 +00:00
|
|
|
err, _, _, _ := isPyCompatFunc(sig)
|
2019-02-19 09:46:15 +00:00
|
|
|
if err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
2015-07-27 16:47:18 +00:00
|
|
|
doc := func() string {
|
2015-07-29 14:54:26 +00:00
|
|
|
if o.Parent() == nil || (o.Parent() != nil && parent != "") {
|
2015-07-27 16:47:18 +00:00
|
|
|
for _, typ := range p.doc.Types {
|
|
|
|
if typ.Name != parent {
|
|
|
|
continue
|
|
|
|
}
|
2015-07-29 14:54:26 +00:00
|
|
|
if o.Parent() == nil {
|
|
|
|
for _, m := range typ.Methods {
|
|
|
|
if m.Name == n {
|
|
|
|
return m.Doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for _, m := range typ.Funcs {
|
|
|
|
if m.Name == n {
|
|
|
|
return m.Doc
|
|
|
|
}
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for _, f := range p.doc.Funcs {
|
|
|
|
if n == f.Name {
|
|
|
|
return f.Doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}()
|
|
|
|
|
|
|
|
parseFn := func(tup *types.Tuple) []string {
|
|
|
|
params := []string{}
|
|
|
|
if tup == nil {
|
|
|
|
return params
|
|
|
|
}
|
|
|
|
for i := 0; i < tup.Len(); i++ {
|
|
|
|
paramVar := tup.At(i)
|
2019-02-20 11:09:23 +00:00
|
|
|
paramSig := p.syms.symtype(paramVar.Type())
|
|
|
|
if paramSig == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
paramType := paramSig.pysig
|
2015-07-27 16:47:18 +00:00
|
|
|
if paramVar.Name() != "" {
|
|
|
|
paramType = fmt.Sprintf("%s %s", paramType, paramVar.Name())
|
|
|
|
}
|
|
|
|
params = append(params, paramType)
|
|
|
|
}
|
|
|
|
return params
|
|
|
|
}
|
|
|
|
|
|
|
|
params := parseFn(sig.Params())
|
|
|
|
results := parseFn(sig.Results())
|
|
|
|
|
|
|
|
paramString := strings.Join(params, ", ")
|
|
|
|
resultString := strings.Join(results, ", ")
|
|
|
|
|
|
|
|
//FIXME(sbinet): add receiver for methods?
|
|
|
|
docSig := fmt.Sprintf("%s(%s) %s", o.Name(), paramString, resultString)
|
|
|
|
|
|
|
|
if doc != "" {
|
|
|
|
doc = fmt.Sprintf("%s\n\n%s", docSig, doc)
|
|
|
|
} else {
|
|
|
|
doc = docSig
|
|
|
|
}
|
|
|
|
return doc
|
|
|
|
|
|
|
|
case *types.TypeName:
|
|
|
|
for _, t := range p.doc.Types {
|
|
|
|
if n == t.Name {
|
|
|
|
return t.Doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
// TODO(sbinet)
|
|
|
|
panic(fmt.Errorf("not yet supported: %v (%T)", o, o))
|
|
|
|
}
|
|
|
|
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// process collects informations about a go package.
|
|
|
|
func (p *Package) process() error {
|
|
|
|
var err error
|
|
|
|
|
2019-02-22 10:33:05 +00:00
|
|
|
p.syms.pkg = p.pkg
|
|
|
|
p.syms.addImport(p.pkg)
|
|
|
|
|
2019-02-24 21:17:35 +00:00
|
|
|
funcs := make(map[string]*Func)
|
|
|
|
structs := make(map[string]*Struct)
|
|
|
|
ifaces := make(map[string]*Interface)
|
2019-03-02 10:30:58 +00:00
|
|
|
slices := make(map[string]*Slice)
|
|
|
|
maps := make(map[string]*Map)
|
2015-07-27 16:47:18 +00:00
|
|
|
|
|
|
|
scope := p.pkg.Scope()
|
|
|
|
for _, name := range scope.Names() {
|
|
|
|
obj := scope.Lookup(name)
|
|
|
|
if !obj.Exported() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2015-08-10 14:29:02 +00:00
|
|
|
p.n++
|
2015-08-03 13:12:35 +00:00
|
|
|
p.syms.addSymbol(obj)
|
2015-08-12 08:18:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, name := range scope.Names() {
|
|
|
|
obj := scope.Lookup(name)
|
|
|
|
if !obj.Exported() {
|
|
|
|
continue
|
|
|
|
}
|
2015-08-03 13:12:35 +00:00
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
switch obj := obj.(type) {
|
|
|
|
case *types.Const:
|
|
|
|
p.addConst(obj)
|
|
|
|
|
|
|
|
case *types.Var:
|
|
|
|
p.addVar(obj)
|
|
|
|
|
|
|
|
case *types.Func:
|
2019-02-24 09:22:19 +00:00
|
|
|
fv, err := newFuncFrom(p, "", obj, obj.Type().(*types.Signature))
|
2015-07-27 16:47:18 +00:00
|
|
|
if err != nil {
|
2019-02-16 18:07:53 +00:00
|
|
|
continue
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
2019-02-24 21:17:35 +00:00
|
|
|
funcs[name] = fv
|
2015-07-27 16:47:18 +00:00
|
|
|
|
|
|
|
case *types.TypeName:
|
|
|
|
named := obj.Type().(*types.Named)
|
|
|
|
switch typ := named.Underlying().(type) {
|
|
|
|
case *types.Struct:
|
2019-02-24 09:22:19 +00:00
|
|
|
sv, err := newStruct(p, obj)
|
2015-07-27 16:47:18 +00:00
|
|
|
if err != nil {
|
2019-03-02 10:30:58 +00:00
|
|
|
fmt.Println(err)
|
|
|
|
continue
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
2019-02-24 21:17:35 +00:00
|
|
|
structs[name] = sv
|
2015-07-27 16:47:18 +00:00
|
|
|
|
2015-08-06 14:49:03 +00:00
|
|
|
case *types.Basic:
|
|
|
|
// ok. handled by p.syms-types
|
|
|
|
|
2015-08-11 16:55:57 +00:00
|
|
|
case *types.Array:
|
|
|
|
// ok. handled by p.syms-types
|
|
|
|
|
2015-08-14 11:26:09 +00:00
|
|
|
case *types.Interface:
|
2019-02-24 09:22:19 +00:00
|
|
|
iv, err := newInterface(p, obj)
|
2019-02-13 10:12:58 +00:00
|
|
|
if err != nil {
|
2019-03-02 10:30:58 +00:00
|
|
|
fmt.Println(err)
|
|
|
|
continue
|
2019-02-13 10:12:58 +00:00
|
|
|
}
|
2019-02-24 21:17:35 +00:00
|
|
|
ifaces[name] = iv
|
2015-08-14 11:26:09 +00:00
|
|
|
|
2015-08-06 14:49:03 +00:00
|
|
|
case *types.Signature:
|
|
|
|
// ok. handled by p.syms-types
|
|
|
|
|
|
|
|
case *types.Slice:
|
2019-03-02 10:30:58 +00:00
|
|
|
sl, err := newSlice(p, obj)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
slices[name] = sl
|
2015-08-06 14:49:03 +00:00
|
|
|
|
2019-02-19 18:32:24 +00:00
|
|
|
case *types.Map:
|
2019-03-02 10:30:58 +00:00
|
|
|
mp, err := newMap(p, obj)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
maps[name] = mp
|
2019-02-19 18:32:24 +00:00
|
|
|
|
2019-02-19 19:02:28 +00:00
|
|
|
case *types.Chan:
|
|
|
|
continue // don't handle
|
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("not yet supported: %v (%T)", typ, obj))
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("not yet supported: %v (%T)", obj, obj))
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-02-24 21:17:35 +00:00
|
|
|
// attach docstrings to methods
|
|
|
|
for _, n := range p.syms.names() {
|
|
|
|
sym := p.syms.syms[n]
|
|
|
|
if !sym.isNamed() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
switch typ := sym.GoType().(type) {
|
|
|
|
case *types.Named:
|
|
|
|
for i := 0; i < typ.NumMethods(); i++ {
|
|
|
|
m := typ.Method(i)
|
|
|
|
if !m.Exported() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
doc := p.getDoc(sym.goname, m)
|
|
|
|
mname := types.ObjectString(m, nil)
|
|
|
|
msym := p.syms.sym(mname)
|
|
|
|
if msym == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
msym.doc = doc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
// remove ctors from funcs.
|
|
|
|
// add methods.
|
|
|
|
for sname, s := range structs {
|
2019-02-24 21:17:35 +00:00
|
|
|
styp := s.GoType()
|
|
|
|
ptyp := types.NewPointer(styp)
|
|
|
|
p.syms.addType(nil, ptyp)
|
2015-07-27 16:47:18 +00:00
|
|
|
for name, fct := range funcs {
|
2019-02-24 21:17:35 +00:00
|
|
|
if !fct.Obj().Exported() {
|
|
|
|
continue
|
|
|
|
}
|
2019-02-13 21:13:10 +00:00
|
|
|
ret := fct.Return()
|
|
|
|
if ret == nil {
|
2015-07-27 16:47:18 +00:00
|
|
|
continue
|
|
|
|
}
|
2019-02-13 21:13:10 +00:00
|
|
|
retptr, retIsPtr := ret.(*types.Pointer)
|
|
|
|
|
2019-02-24 21:17:35 +00:00
|
|
|
if ret == styp || (retIsPtr && retptr.Elem() == styp) {
|
2015-07-27 16:47:18 +00:00
|
|
|
delete(funcs, name)
|
2015-07-29 14:54:26 +00:00
|
|
|
fct.doc = p.getDoc(sname, scope.Lookup(name))
|
2015-07-29 15:27:54 +00:00
|
|
|
fct.ctor = true
|
2015-07-27 16:47:18 +00:00
|
|
|
s.ctors = append(s.ctors, fct)
|
|
|
|
structs[sname] = s
|
2019-02-24 21:17:35 +00:00
|
|
|
continue
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-24 21:17:35 +00:00
|
|
|
ntyp, ok := styp.(*types.Named)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
nmeth := ntyp.NumMethods()
|
|
|
|
for mi := 0; mi < nmeth; mi++ {
|
|
|
|
meth := ntyp.Method(mi)
|
|
|
|
if !meth.Exported() {
|
2015-07-27 16:47:18 +00:00
|
|
|
continue
|
|
|
|
}
|
2019-02-24 21:17:35 +00:00
|
|
|
msig := meth.Type().(*types.Signature)
|
|
|
|
m, err := newFuncFrom(p, sname, meth, msig)
|
2015-07-27 16:47:18 +00:00
|
|
|
if err != nil {
|
2019-02-16 18:07:53 +00:00
|
|
|
continue
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
2019-02-24 21:17:35 +00:00
|
|
|
s.meths = append(s.meths, m)
|
|
|
|
if isStringer(meth) {
|
2015-07-29 10:36:45 +00:00
|
|
|
s.prots |= ProtoStringer
|
|
|
|
}
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
2015-07-28 12:41:53 +00:00
|
|
|
p.addStruct(s)
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
|
|
|
|
2019-02-13 10:12:58 +00:00
|
|
|
for iname, ifc := range ifaces {
|
|
|
|
mset := types.NewMethodSet(ifc.GoType())
|
|
|
|
for i := 0; i < mset.Len(); i++ {
|
|
|
|
meth := mset.At(i)
|
|
|
|
if !meth.Obj().Exported() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
m, err := newFuncFrom(p, iname, meth.Obj(), meth.Type().(*types.Signature))
|
|
|
|
if err != nil {
|
2019-02-16 18:07:53 +00:00
|
|
|
continue
|
2019-02-13 10:12:58 +00:00
|
|
|
}
|
2019-02-24 21:17:35 +00:00
|
|
|
ifc.meths = append(ifc.meths, m)
|
2019-02-13 10:12:58 +00:00
|
|
|
}
|
|
|
|
p.addInterface(ifc)
|
|
|
|
}
|
|
|
|
|
2019-03-02 10:30:58 +00:00
|
|
|
for sname, s := range slices {
|
|
|
|
styp := s.GoType()
|
|
|
|
ntyp, ok := styp.(*types.Named)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
nmeth := ntyp.NumMethods()
|
|
|
|
for mi := 0; mi < nmeth; mi++ {
|
|
|
|
meth := ntyp.Method(mi)
|
|
|
|
if !meth.Exported() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
msig := meth.Type().(*types.Signature)
|
|
|
|
m, err := newFuncFrom(p, sname, meth, msig)
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
s.meths = append(s.meths, m)
|
|
|
|
if isStringer(meth) {
|
|
|
|
s.prots |= ProtoStringer
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p.addSlice(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
for sname, s := range maps {
|
|
|
|
styp := s.GoType()
|
|
|
|
ntyp, ok := styp.(*types.Named)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
nmeth := ntyp.NumMethods()
|
|
|
|
for mi := 0; mi < nmeth; mi++ {
|
|
|
|
meth := ntyp.Method(mi)
|
|
|
|
if !meth.Exported() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
msig := meth.Type().(*types.Signature)
|
|
|
|
m, err := newFuncFrom(p, sname, meth, msig)
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
s.meths = append(s.meths, m)
|
|
|
|
if isStringer(meth) {
|
|
|
|
s.prots |= ProtoStringer
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p.addMap(s)
|
|
|
|
}
|
|
|
|
|
2015-07-27 16:47:18 +00:00
|
|
|
for _, fct := range funcs {
|
2015-07-28 12:41:53 +00:00
|
|
|
p.addFunc(fct)
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Package) addConst(obj *types.Const) {
|
2019-02-24 09:22:19 +00:00
|
|
|
nc, err := newConst(p, obj)
|
|
|
|
if err == nil {
|
2019-02-24 21:17:35 +00:00
|
|
|
p.consts = append(p.consts, nc)
|
2019-02-24 09:22:19 +00:00
|
|
|
}
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Package) addVar(obj *types.Var) {
|
2019-02-24 09:22:19 +00:00
|
|
|
nv, err := newVarFrom(p, obj)
|
|
|
|
if err == nil {
|
2019-02-24 21:17:35 +00:00
|
|
|
p.vars = append(p.vars, nv)
|
2019-02-24 09:22:19 +00:00
|
|
|
}
|
2015-07-27 16:47:18 +00:00
|
|
|
}
|
|
|
|
|
2019-02-24 21:17:35 +00:00
|
|
|
func (p *Package) addStruct(s *Struct) {
|
2015-07-28 12:41:53 +00:00
|
|
|
p.structs = append(p.structs, s)
|
2019-02-25 07:01:51 +00:00
|
|
|
s.idx = len(p.structs) - 1
|
2015-07-28 12:41:53 +00:00
|
|
|
p.objs[s.GoName()] = s
|
|
|
|
}
|
|
|
|
|
2019-02-24 21:17:35 +00:00
|
|
|
func (p *Package) addInterface(ifc *Interface) {
|
2019-02-13 10:12:58 +00:00
|
|
|
p.ifaces = append(p.ifaces, ifc)
|
|
|
|
p.objs[ifc.GoName()] = ifc
|
|
|
|
}
|
|
|
|
|
2019-03-02 10:30:58 +00:00
|
|
|
func (p *Package) addSlice(slc *Slice) {
|
|
|
|
p.slices = append(p.slices, slc)
|
|
|
|
p.objs[slc.GoName()] = slc
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Package) addMap(mp *Map) {
|
|
|
|
p.maps = append(p.maps, mp)
|
|
|
|
p.objs[mp.GoName()] = mp
|
|
|
|
}
|
|
|
|
|
2019-02-24 21:17:35 +00:00
|
|
|
func (p *Package) addFunc(f *Func) {
|
2015-07-28 12:41:53 +00:00
|
|
|
p.funcs = append(p.funcs, f)
|
|
|
|
p.objs[f.GoName()] = f
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lookup returns the bind.Object corresponding to a types.Object
|
|
|
|
func (p *Package) Lookup(o types.Object) (Object, bool) {
|
|
|
|
obj, ok := p.objs[o.Name()]
|
|
|
|
return obj, ok
|
|
|
|
}
|
2019-02-25 07:01:51 +00:00
|
|
|
|
|
|
|
func (p *Package) sortStructEmbeds() {
|
|
|
|
for {
|
|
|
|
nswap := 0
|
|
|
|
for _, s := range p.structs {
|
|
|
|
emb := s.FirstEmbed()
|
|
|
|
if emb == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
emss, ok := p.objs[emb.goname]
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
ems := emss.(*Struct)
|
|
|
|
if ems.idx > s.idx {
|
|
|
|
nswap++
|
|
|
|
p.structs[s.idx], p.structs[ems.idx] = p.structs[ems.idx], p.structs[s.idx]
|
|
|
|
s.idx, ems.idx = ems.idx, s.idx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if nswap == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
// fmt.Printf("%s nswap: %v\n", p.pkg.Path(), nswap)
|
|
|
|
}
|
|
|
|
}
|