1// Copyright 2019 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package cache 6 7import ( 8 "go/ast" 9 "go/scanner" 10 "go/types" 11 12 "golang.org/x/mod/module" 13 "golang.org/x/tools/internal/lsp/source" 14 "golang.org/x/tools/internal/span" 15 errors "golang.org/x/xerrors" 16) 17 18// pkg contains the type information needed by the source package. 19type pkg struct { 20 m *metadata 21 mode source.ParseMode 22 goFiles []*source.ParsedGoFile 23 compiledGoFiles []*source.ParsedGoFile 24 diagnostics []*source.Diagnostic 25 imports map[packagePath]*pkg 26 version *module.Version 27 parseErrors []scanner.ErrorList 28 typeErrors []types.Error 29 types *types.Package 30 typesInfo *types.Info 31 typesSizes types.Sizes 32 hasFixedFiles bool 33} 34 35// Declare explicit types for package paths, names, and IDs to ensure that we 36// never use an ID where a path belongs, and vice versa. If we confused these, 37// it would result in confusing errors because package IDs often look like 38// package paths. 39type ( 40 packageID string 41 packagePath string 42 packageName string 43) 44 45// Declare explicit types for files and directories to distinguish between the two. 46type ( 47 fileURI span.URI 48 moduleLoadScope string 49 viewLoadScope span.URI 50) 51 52func (p *pkg) ID() string { 53 return string(p.m.id) 54} 55 56func (p *pkg) Name() string { 57 return string(p.m.name) 58} 59 60func (p *pkg) PkgPath() string { 61 return string(p.m.pkgPath) 62} 63 64func (p *pkg) CompiledGoFiles() []*source.ParsedGoFile { 65 return p.compiledGoFiles 66} 67 68func (p *pkg) File(uri span.URI) (*source.ParsedGoFile, error) { 69 for _, cgf := range p.compiledGoFiles { 70 if cgf.URI == uri { 71 return cgf, nil 72 } 73 } 74 for _, gf := range p.goFiles { 75 if gf.URI == uri { 76 return gf, nil 77 } 78 } 79 return nil, errors.Errorf("no parsed file for %s in %v", uri, p.m.id) 80} 81 82func (p *pkg) GetSyntax() []*ast.File { 83 var syntax []*ast.File 84 for _, pgf := range p.compiledGoFiles { 85 syntax = append(syntax, pgf.File) 86 } 87 return syntax 88} 89 90func (p *pkg) GetTypes() *types.Package { 91 return p.types 92} 93 94func (p *pkg) GetTypesInfo() *types.Info { 95 return p.typesInfo 96} 97 98func (p *pkg) GetTypesSizes() types.Sizes { 99 return p.typesSizes 100} 101 102func (p *pkg) IsIllTyped() bool { 103 return p.types == nil || p.typesInfo == nil || p.typesSizes == nil 104} 105 106func (p *pkg) ForTest() string { 107 return string(p.m.forTest) 108} 109 110func (p *pkg) GetImport(pkgPath string) (source.Package, error) { 111 if imp := p.imports[packagePath(pkgPath)]; imp != nil { 112 return imp, nil 113 } 114 // Don't return a nil pointer because that still satisfies the interface. 115 return nil, errors.Errorf("no imported package for %s", pkgPath) 116} 117 118func (p *pkg) MissingDependencies() []string { 119 // We don't invalidate metadata for import deletions, so check the package 120 // imports via the *types.Package. Only use metadata if p.types is nil. 121 if p.types == nil { 122 var md []string 123 for i := range p.m.missingDeps { 124 md = append(md, string(i)) 125 } 126 return md 127 } 128 var md []string 129 for _, pkg := range p.types.Imports() { 130 if _, ok := p.m.missingDeps[packagePath(pkg.Path())]; ok { 131 md = append(md, pkg.Path()) 132 } 133 } 134 return md 135} 136 137func (p *pkg) Imports() []source.Package { 138 var result []source.Package 139 for _, imp := range p.imports { 140 result = append(result, imp) 141 } 142 return result 143} 144 145func (p *pkg) Version() *module.Version { 146 return p.version 147} 148 149func (p *pkg) HasListOrParseErrors() bool { 150 return len(p.m.errors) != 0 || len(p.parseErrors) != 0 151} 152 153func (p *pkg) HasTypeErrors() bool { 154 return len(p.typeErrors) != 0 155} 156