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