golang.org/x/tools/gopls@v0.15.3/internal/cache/pkg.go (about) 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 5 package cache 6 7 import ( 8 "fmt" 9 "go/ast" 10 "go/scanner" 11 "go/token" 12 "go/types" 13 "sync" 14 15 "golang.org/x/tools/gopls/internal/cache/metadata" 16 "golang.org/x/tools/gopls/internal/cache/methodsets" 17 "golang.org/x/tools/gopls/internal/cache/parsego" 18 "golang.org/x/tools/gopls/internal/cache/xrefs" 19 "golang.org/x/tools/gopls/internal/protocol" 20 ) 21 22 // Convenient aliases for very heavily used types. 23 type ( 24 PackageID = metadata.PackageID 25 PackagePath = metadata.PackagePath 26 PackageName = metadata.PackageName 27 ImportPath = metadata.ImportPath 28 ParsedGoFile = parsego.File 29 ) 30 31 const ( 32 ParseHeader = parsego.ParseHeader 33 ParseFull = parsego.ParseFull 34 ) 35 36 // A Package is the union of package metadata and type checking results. 37 // 38 // TODO(rfindley): for now, we do not persist the post-processing of 39 // loadDiagnostics, because the value of the snapshot.packages map is just the 40 // package handle. Fix this. 41 type Package struct { 42 metadata *metadata.Package 43 loadDiagnostics []*Diagnostic 44 pkg *syntaxPackage 45 } 46 47 // syntaxPackage contains parse trees and type information for a package. 48 type syntaxPackage struct { 49 // -- identifiers -- 50 id PackageID 51 52 // -- outputs -- 53 fset *token.FileSet // for now, same as the snapshot's FileSet 54 goFiles []*ParsedGoFile 55 compiledGoFiles []*ParsedGoFile 56 diagnostics []*Diagnostic 57 parseErrors []scanner.ErrorList 58 typeErrors []types.Error 59 types *types.Package 60 typesInfo *types.Info 61 importMap map[PackagePath]*types.Package 62 63 xrefsOnce sync.Once 64 _xrefs []byte // only used by the xrefs method 65 66 methodsetsOnce sync.Once 67 _methodsets *methodsets.Index // only used by the methodsets method 68 } 69 70 func (p *syntaxPackage) xrefs() []byte { 71 p.xrefsOnce.Do(func() { 72 p._xrefs = xrefs.Index(p.compiledGoFiles, p.types, p.typesInfo) 73 }) 74 return p._xrefs 75 } 76 77 func (p *syntaxPackage) methodsets() *methodsets.Index { 78 p.methodsetsOnce.Do(func() { 79 p._methodsets = methodsets.NewIndex(p.fset, p.types) 80 }) 81 return p._methodsets 82 } 83 84 func (p *Package) String() string { return string(p.metadata.ID) } 85 86 func (p *Package) Metadata() *metadata.Package { return p.metadata } 87 88 // A loadScope defines a package loading scope for use with go/packages. 89 // 90 // TODO(rfindley): move this to load.go. 91 type loadScope interface { 92 aScope() 93 } 94 95 type ( 96 fileLoadScope protocol.DocumentURI // load packages containing a file (including command-line-arguments) 97 packageLoadScope string // load a specific package (the value is its PackageID) 98 moduleLoadScope struct { 99 dir string // dir containing the go.mod file 100 modulePath string // parsed module path 101 } 102 viewLoadScope struct{} // load the workspace 103 ) 104 105 // Implement the loadScope interface. 106 func (fileLoadScope) aScope() {} 107 func (packageLoadScope) aScope() {} 108 func (moduleLoadScope) aScope() {} 109 func (viewLoadScope) aScope() {} 110 111 func (p *Package) CompiledGoFiles() []*ParsedGoFile { 112 return p.pkg.compiledGoFiles 113 } 114 115 func (p *Package) File(uri protocol.DocumentURI) (*ParsedGoFile, error) { 116 return p.pkg.File(uri) 117 } 118 119 func (pkg *syntaxPackage) File(uri protocol.DocumentURI) (*ParsedGoFile, error) { 120 for _, cgf := range pkg.compiledGoFiles { 121 if cgf.URI == uri { 122 return cgf, nil 123 } 124 } 125 for _, gf := range pkg.goFiles { 126 if gf.URI == uri { 127 return gf, nil 128 } 129 } 130 return nil, fmt.Errorf("no parsed file for %s in %v", uri, pkg.id) 131 } 132 133 func (p *Package) GetSyntax() []*ast.File { 134 var syntax []*ast.File 135 for _, pgf := range p.pkg.compiledGoFiles { 136 syntax = append(syntax, pgf.File) 137 } 138 return syntax 139 } 140 141 func (p *Package) FileSet() *token.FileSet { 142 return p.pkg.fset 143 } 144 145 func (p *Package) GetTypes() *types.Package { 146 return p.pkg.types 147 } 148 149 func (p *Package) GetTypesInfo() *types.Info { 150 return p.pkg.typesInfo 151 } 152 153 // DependencyTypes returns the type checker's symbol for the specified 154 // package. It returns nil if path is not among the transitive 155 // dependencies of p, or if no symbols from that package were 156 // referenced during the type-checking of p. 157 func (p *Package) DependencyTypes(path PackagePath) *types.Package { 158 return p.pkg.importMap[path] 159 } 160 161 func (p *Package) GetParseErrors() []scanner.ErrorList { 162 return p.pkg.parseErrors 163 } 164 165 func (p *Package) GetTypeErrors() []types.Error { 166 return p.pkg.typeErrors 167 }