// NewPackage returns a new Package struct, which can be // used to generate code related to the package. The package // might be given as either an absolute path or an import path. // If the package can't be found or the package is not compilable, // this function returns an error. func NewPackage(path string) (*Package, error) { p := &_package{Path: path, fset: token.NewFileSet()} pkg, err := findPackage(path) if err != nil { return nil, fmt.Errorf("could not find package: %s", err) } fileNames := packageFiles(pkg) if len(fileNames) == 0 { return nil, fmt.Errorf("no go files") } p.astFiles = make([]*ast.File, len(fileNames)) p.files = make(map[string]*file, len(fileNames)) for ii, v := range fileNames { f, err := parseFile(p.fset, v) if err != nil { return nil, fmt.Errorf("could not parse %s: %s", v, err) } p.files[v] = f p.astFiles[ii] = f.ast } context := &types.Config{ IgnoreFuncBodies: true, FakeImportC: true, Error: errorHandler, } ipath := pkg.ImportPath if ipath == "." { // Check won't accept a "." import abs, err := filepath.Abs(pkg.Dir) if err != nil { return nil, err } for _, v := range strings.Split(build.Default.GOPATH, ":") { src := filepath.Join(v, "src") if strings.HasPrefix(abs, src) { ipath = abs[len(src)+1:] break } } } var info types.Info info.Types = make(map[ast.Expr]types.TypeAndValue) info.Defs = make(map[*ast.Ident]types.Object) info.Uses = make(map[*ast.Ident]types.Object) info.Implicits = make(map[ast.Node]types.Object) info.Selections = make(map[*ast.SelectorExpr]*types.Selection) info.Scopes = make(map[ast.Node]*types.Scope) tpkg, err := context.Check(ipath, p.fset, p.astFiles, &info) if err != nil { // This error is caused by using fields in C structs, ignore it if !strings.Contains(err.Error(), "invalid type") { return nil, fmt.Errorf("error checking package: %s", err) } } return &Package{ Package: tpkg, dir: pkg.Dir, pkg: p, info: &info, }, nil }