// Name = identifier | "?" | QualifiedName . // // If materializePkg is set, the returned package is guaranteed to be set. // For fully qualified names, the returned package may be a fake package // (without name, scope, and not in the p.imports map), created for the // sole purpose of providing a package path. Fake packages are created // when the package id is not found in the p.imports map; in that case // we cannot create a real package because we don't have a package name. // For non-qualified names, the returned package is the imported package. // func (p *parser) parseName(materializePkg bool) (pkg *types.Package, name string) { switch p.tok { case scanner.Ident: pkg = p.imports[p.id] name = p.lit p.next() case '?': // anonymous pkg = p.imports[p.id] p.next() case '@': // exported name prefixed with package path var id string id, name = p.parseQualifiedName() if materializePkg { // we don't have a package name - if the package // doesn't exist yet, create a fake package instead pkg = p.getPkg(id, "") if pkg == nil { pkg = types.NewPackage(id, "") } } default: p.error("name expected") } return }
func (p *importer) pkg() *types.Package { // if the package was seen before, i is its index (>= 0) i := p.int() if i >= 0 { return p.pkgList[i] } // otherwise, i is the package tag (< 0) if i != packageTag { panic(fmt.Sprintf("unexpected package tag %d", i)) } // read package data name := p.string() path := p.string() // if the package was imported before, use that one; otherwise create a new one pkg := p.imports[path] if pkg == nil { pkg = types.NewPackage(path, name) p.imports[path] = pkg } p.pkgList = append(p.pkgList, pkg) return pkg }
func (imp *importer) newPackageInfo(path string) *PackageInfo { pkg := types.NewPackage(path, "") if imp.conf.PackageCreated != nil { imp.conf.PackageCreated(pkg) } info := &PackageInfo{ Pkg: pkg, Info: types.Info{ Types: make(map[ast.Expr]types.TypeAndValue), Defs: make(map[*ast.Ident]types.Object), Uses: make(map[*ast.Ident]types.Object), Implicits: make(map[ast.Node]types.Object), Scopes: make(map[ast.Node]*types.Scope), Selections: make(map[*ast.SelectorExpr]*types.Selection), }, errorFunc: imp.conf.TypeChecker.Error, } // Copy the types.Config so we can vary it across PackageInfos. tc := imp.conf.TypeChecker tc.IgnoreFuncBodies = false if f := imp.conf.TypeCheckFuncBodies; f != nil { tc.IgnoreFuncBodies = !f(path) } tc.Import = func(_ map[string]*types.Package, to string) (*types.Package, error) { return imp.doImport(info, to) } tc.Error = info.appendError // appendError wraps the user's Error function info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info) imp.typecheckerMu.Lock() imp.prog.AllPackages[pkg] = info imp.typecheckerMu.Unlock() return info }
// getPkg returns the package for a given id. If the package is // not found but we have a package name, create the package and // add it to the p.imports map. // func (p *parser) getPkg(id, name string) *types.Package { // package unsafe is not in the imports map - handle explicitly if id == "unsafe" { return types.Unsafe } pkg := p.imports[id] if pkg == nil && name != "" { pkg = types.NewPackage(id, name) p.imports[id] = pkg } return pkg }