// 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.sharedPkgs[p.id] name = p.lit p.next() case '?': // anonymous pkg = p.sharedPkgs[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 }
// 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.localPkgs and p.sharedPkgs maps. // // id identifies a package, usually by a canonical package path like // "encoding/json" but possibly by a non-canonical import path like // "./json". // func (p *parser) getPkg(id, name string) *types.Package { // package unsafe is not in the packages maps - handle explicitly if id == "unsafe" { return types.Unsafe } pkg := p.localPkgs[id] if pkg == nil && name != "" { // first import of id from this package pkg = p.sharedPkgs[id] if pkg == nil { // first import of id by this importer pkg = types.NewPackage(id, name) p.sharedPkgs[id] = pkg } if p.localPkgs == nil { p.localPkgs = make(map[string]*types.Package) } p.localPkgs[id] = pkg } return pkg }