func (gopaths GoPaths) FindWorkingPath(dir string) (string, error) { order := make([]string, len(gopaths)) copy(order, gopaths) sort.Sort(descendingLenStrings(order)) dir = path.Clean(dir) for _, gp := range order { if strings.HasPrefix(dir, path.Join(gp, "src")) { return gp, nil } } return "", errors.New("working gopath not found") }
// add adds t to the structures for global and per-package lookups func (tt *GlobalNames) Add(t *Named) error { // Add type to global type map if _, ok := tt.names[t.FullName()]; ok { return errors.New("type %s already defined", t.FullName()) } tt.names[t.FullName()] = t // Add type to per-package structure pkgMap, ok := tt.pkgs[t.PkgPath] if !ok { pkgMap = make(map[string]*Named) tt.pkgs[t.PkgPath] = pkgMap } pkgMap[t.Name] = t return nil }
func compileTypeExpr(pkgPath string, fimp *util.FileImports, expr ast.Expr) (typ Type, err error) { switch q := expr.(type) { // Built-in types or references to other types in this package case *ast.Ident: switch q.Name { case "bool": typ = Builtin[Bool] case "int": typ = Builtin[Int] case "int8": typ = Builtin[Int8] case "int16": typ = Builtin[Int16] case "int32": typ = Builtin[Int32] case "int64": typ = Builtin[Int64] case "uint": typ = Builtin[Uint] case "uint8": typ = Builtin[Uint8] case "uint16": typ = Builtin[Uint16] case "uint32": typ = Builtin[Uint32] case "uint64": typ = Builtin[Uint64] case "uintptr": typ = Builtin[Uintptr] case "float32": typ = Builtin[Float32] case "float64": typ = Builtin[Float64] case "complex64": typ = Builtin[Complex64] case "complex128": typ = Builtin[Complex128] case "string": typ = Builtin[String] default: // Name of another type defined in this package typ = &Link{PkgPath: pkgPath, Name: q.Name} } return typ, nil case *ast.ParenExpr: return compileTypeExpr(pkgPath, fimp, q) case *ast.SelectorExpr: pkgAlias, ok := q.X.(*ast.Ident) if !ok { panic("package alias is not an identifier") } typeName := q.Sel.Name impPath, ok := fimp.Alias[pkgAlias.Name] if !ok { return nil, errors.New("no import with given alias") } return &Link{PkgPath: impPath, Name: typeName}, nil case *ast.StarExpr: base, err := compileTypeExpr(pkgPath, fimp, q.X) if err != nil { return nil, err } return &Pointer{Base: base}, nil case *ast.ArrayType: elt, err := compileTypeExpr(pkgPath, fimp, q.Elt) if err != nil { return nil, err } if q.Len == nil { return &Slice{Elt: elt}, nil } if _, ok := q.Len.(*ast.Ellipsis); ok { return &Array{Len: -1 /*XXX*/, Elt: elt}, nil } return nil, errors.New("unknown array length") case *ast.ChanType: value, err := compileTypeExpr(pkgPath, fimp, q.Value) if err != nil { return nil, err } return &Chan{Dir: q.Dir, Elt: value}, nil case *ast.FuncType: // TODO: Compile signature details return &Signature{}, nil case *ast.InterfaceType: // TODO: Compile interface details return &Interface{}, nil case *ast.MapType: key, err := compileTypeExpr(pkgPath, fimp, q.Key) if err != nil { return nil, err } value, err := compileTypeExpr(pkgPath, fimp, q.Value) if err != nil { return nil, err } return &Map{Key: key, Value: value}, nil case *ast.StructType: // TODO: Compile struct details return &Struct{}, nil } return nil, errors.New("unexpected type definition") }