LoadTypedScope loads the workspace rooted at root with full type information and returns a scope ready for CheckDeclaredSubtype typed resolution. A non-nil error reports an unrecoverable failure (the loader could not even start); a successful return with Enabled() == false indicates the loader ran b
(root string)
| 73 | // missing) — in which case the caller should fall back silently to the |
| 74 | // AST-only path. |
| 75 | func LoadTypedScope(root string) (*TypedScope, error) { |
| 76 | cfg := &packages.Config{ |
| 77 | Mode: packages.NeedName | |
| 78 | packages.NeedFiles | |
| 79 | packages.NeedCompiledGoFiles | |
| 80 | packages.NeedImports | |
| 81 | packages.NeedDeps | |
| 82 | packages.NeedTypes | |
| 83 | packages.NeedSyntax | |
| 84 | packages.NeedTypesInfo, |
| 85 | Dir: root, |
| 86 | Tests: false, |
| 87 | } |
| 88 | pkgs, err := packages.Load(cfg, "./...") |
| 89 | if err != nil { |
| 90 | return nil, err |
| 91 | } |
| 92 | |
| 93 | scope := &TypedScope{ |
| 94 | typedFiles: map[string]*types.Info{}, |
| 95 | errsSubtypeConsts: map[string]*types.Const{}, |
| 96 | } |
| 97 | |
| 98 | packages.Visit(pkgs, nil, func(p *packages.Package) { |
| 99 | if p == nil || p.TypesInfo == nil { |
| 100 | return |
| 101 | } |
| 102 | // Index file → TypesInfo for the walker. |
| 103 | for _, f := range p.CompiledGoFiles { |
| 104 | scope.typedFiles[filepath.Clean(f)] = p.TypesInfo |
| 105 | } |
| 106 | // Capture declared Subtype constants from the canonical errs package |
| 107 | // so CheckDeclaredSubtype can reject selectors that resolve to a foreign-package |
| 108 | // const sharing the same name. |
| 109 | if p.PkgPath == errsPkgPath && p.Types != nil { |
| 110 | collectSubtypeConsts(p.Types, scope.errsSubtypeConsts) |
| 111 | } |
| 112 | }) |
| 113 | return scope, nil |
| 114 | } |
| 115 | |
| 116 | // collectSubtypeConsts scans a *types.Package for exported constants of |
| 117 | // type errs.Subtype whose name starts with "Subtype" and records them by |
no test coverage detected