Skip to content

Commit ef6787d

Browse files
committed
internal/lsp: track and parse non-compiled go files
When packages.Load'ing cgo packages, the authored files show up in GoFiles, and the generated files show up in CompiledGoFiles. We need the AST and type information for the latter, since they're the only thing we can type check. But we also need the contents (and column mapper) for the authored file so that we can navigate into it. Store GoFiles in package metadata and checked Packages. Parse the extra files, just for their mappers. Refactor the View functions a little bit, since there's only one place that actually needs to find the mapper for a file. Updates golang/go#35720. Change-Id: I9f96872a9a592bf0e11da27ebd8976c6db8752c9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/208502 Run-TryBot: Heschi Kreinick <[email protected]> Reviewed-by: Ian Cottrell <[email protected]> Reviewed-by: Rebecca Stambler <[email protected]>
1 parent 761dbfd commit ef6787d

File tree

9 files changed

+82
-31
lines changed

9 files changed

+82
-31
lines changed

internal/lsp/cache/check.go

+28-11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"golang.org/x/tools/internal/lsp/source"
1919
"golang.org/x/tools/internal/lsp/telemetry"
2020
"golang.org/x/tools/internal/memoize"
21+
"golang.org/x/tools/internal/span"
2122
"golang.org/x/tools/internal/telemetry/log"
2223
"golang.org/x/tools/internal/telemetry/trace"
2324
errors "golang.org/x/xerrors"
@@ -27,6 +28,8 @@ import (
2728
type checkPackageHandle struct {
2829
handle *memoize.Handle
2930

31+
goFiles []source.ParseGoHandle
32+
3033
// compiledGoFiles are the ParseGoHandles that compose the package.
3134
compiledGoFiles []source.ParseGoHandle
3235

@@ -77,7 +80,8 @@ func (s *snapshot) checkPackageHandle(ctx context.Context, id packageID, mode so
7780
//
7881

7982
m := cph.m
80-
files := cph.compiledGoFiles
83+
goFiles := cph.goFiles
84+
compiledGoFiles := cph.compiledGoFiles
8185
key := cph.key
8286
fset := s.view.session.cache.fset
8387

@@ -89,7 +93,7 @@ func (s *snapshot) checkPackageHandle(ctx context.Context, id packageID, mode so
8993
}(dep)
9094
}
9195
data := &checkPackageData{}
92-
data.pkg, data.err = typeCheck(ctx, fset, m, mode, files, deps)
96+
data.pkg, data.err = typeCheck(ctx, fset, m, mode, goFiles, compiledGoFiles, deps)
9397
return data
9498
})
9599
cph.handle = h
@@ -106,13 +110,18 @@ func (s *snapshot) buildKey(ctx context.Context, id packageID, mode source.Parse
106110
if m == nil {
107111
return nil, nil, errors.Errorf("no metadata for %s", id)
108112
}
109-
phs, err := s.compiledParseGoHandles(ctx, m, mode)
113+
goFiles, err := s.parseGoHandles(ctx, m.goFiles, mode)
114+
if err != nil {
115+
return nil, nil, err
116+
}
117+
compiledGoFiles, err := s.parseGoHandles(ctx, m.compiledGoFiles, mode)
110118
if err != nil {
111119
return nil, nil, err
112120
}
113121
cph := &checkPackageHandle{
114122
m: m,
115-
compiledGoFiles: phs,
123+
goFiles: goFiles,
124+
compiledGoFiles: compiledGoFiles,
116125
mode: mode,
117126
}
118127

@@ -206,9 +215,9 @@ func (cph *checkPackageHandle) cached() (*pkg, error) {
206215
return data.pkg, data.err
207216
}
208217

209-
func (s *snapshot) compiledParseGoHandles(ctx context.Context, m *metadata, mode source.ParseMode) ([]source.ParseGoHandle, error) {
210-
phs := make([]source.ParseGoHandle, 0, len(m.compiledGoFiles))
211-
for _, uri := range m.compiledGoFiles {
218+
func (s *snapshot) parseGoHandles(ctx context.Context, files []span.URI, mode source.ParseMode) ([]source.ParseGoHandle, error) {
219+
phs := make([]source.ParseGoHandle, 0, len(files))
220+
for _, uri := range files {
212221
f, err := s.view.GetFile(ctx, uri)
213222
if err != nil {
214223
return nil, err
@@ -219,7 +228,7 @@ func (s *snapshot) compiledParseGoHandles(ctx context.Context, m *metadata, mode
219228
return phs, nil
220229
}
221230

222-
func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode source.ParseMode, phs []source.ParseGoHandle, deps map[packagePath]*checkPackageHandle) (*pkg, error) {
231+
func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode source.ParseMode, goFiles []source.ParseGoHandle, compiledGoFiles []source.ParseGoHandle, deps map[packagePath]*checkPackageHandle) (*pkg, error) {
223232
ctx, done := trace.StartSpan(ctx, "cache.importer.typeCheck", telemetry.Package.Of(m.id))
224233
defer done()
225234

@@ -232,7 +241,8 @@ func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode sourc
232241
id: m.id,
233242
pkgPath: m.pkgPath,
234243
mode: mode,
235-
compiledGoFiles: phs,
244+
goFiles: goFiles,
245+
compiledGoFiles: compiledGoFiles,
236246
imports: make(map[packagePath]*pkg),
237247
typesSizes: m.typesSizes,
238248
typesInfo: &types.Info{
@@ -252,11 +262,18 @@ func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode sourc
252262
for i, ph := range pkg.compiledGoFiles {
253263
wg.Add(1)
254264
go func(i int, ph source.ParseGoHandle) {
255-
defer wg.Done()
256-
257265
files[i], _, parseErrors[i], _ = ph.Parse(ctx)
266+
wg.Done()
258267
}(i, ph)
259268
}
269+
for _, ph := range pkg.goFiles {
270+
wg.Add(1)
271+
// We need to parse the non-compiled go files, but we don't care about their errors.
272+
go func(ph source.ParseGoHandle) {
273+
ph.Parse(ctx)
274+
wg.Done()
275+
}(ph)
276+
}
260277
wg.Wait()
261278

262279
for _, e := range parseErrors {

internal/lsp/cache/load.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type metadata struct {
2323
id packageID
2424
pkgPath packagePath
2525
name string
26+
goFiles []span.URI
2627
compiledGoFiles []span.URI
2728
typesSizes types.Sizes
2829
errors []packages.Error
@@ -210,14 +211,19 @@ func (s *snapshot) updateImports(ctx context.Context, pkgPath packagePath, pkg *
210211
errors: pkg.Errors,
211212
config: cfg,
212213
}
213-
seen[id] = struct{}{}
214+
214215
for _, filename := range pkg.CompiledGoFiles {
215216
uri := span.FileURI(filename)
216217
m.compiledGoFiles = append(m.compiledGoFiles, uri)
217-
218+
s.addID(uri, m.id)
219+
}
220+
for _, filename := range pkg.GoFiles {
221+
uri := span.FileURI(filename)
222+
m.goFiles = append(m.goFiles, uri)
218223
s.addID(uri, m.id)
219224
}
220225

226+
seen[id] = struct{}{}
221227
copied := make(map[packageID]struct{})
222228
for k, v := range seen {
223229
copied[k] = v

internal/lsp/cache/pkg.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type pkg struct {
2222
pkgPath packagePath
2323
mode source.ParseMode
2424

25+
goFiles []source.ParseGoHandle
2526
compiledGoFiles []source.ParseGoHandle
2627
errors []*source.Error
2728
imports map[packagePath]*pkg
@@ -49,7 +50,12 @@ func (p *pkg) CompiledGoFiles() []source.ParseGoHandle {
4950
}
5051

5152
func (p *pkg) File(uri span.URI) (source.ParseGoHandle, error) {
52-
for _, ph := range p.CompiledGoFiles() {
53+
for _, ph := range p.compiledGoFiles {
54+
if ph.File().Identity().URI == uri {
55+
return ph, nil
56+
}
57+
}
58+
for _, ph := range p.goFiles {
5359
if ph.File().Identity().URI == uri {
5460
return ph, nil
5561
}

internal/lsp/cache/view.go

+31-12
Original file line numberDiff line numberDiff line change
@@ -432,12 +432,12 @@ func (v *view) mapFile(uri span.URI, f viewFile) {
432432
}
433433
}
434434

435-
func (v *view) FindPosInPackage(searchpkg source.Package, pos token.Pos) (*ast.File, *protocol.ColumnMapper, source.Package, error) {
435+
func (v *view) FindPosInPackage(searchpkg source.Package, pos token.Pos) (*ast.File, source.Package, error) {
436436
tok := v.session.cache.fset.File(pos)
437437
if tok == nil {
438-
return nil, nil, nil, errors.Errorf("no file for pos in package %s", searchpkg.ID())
438+
return nil, nil, errors.Errorf("no file for pos in package %s", searchpkg.ID())
439439
}
440-
uri := span.FileURI(tok.Position(pos).Filename)
440+
uri := span.FileURI(tok.Name())
441441

442442
// Special case for ignored files.
443443
var (
@@ -451,16 +451,37 @@ func (v *view) FindPosInPackage(searchpkg source.Package, pos token.Pos) (*ast.F
451451
ph, pkg, err = findFileInPackage(searchpkg, uri)
452452
}
453453
if err != nil {
454-
return nil, nil, nil, err
454+
return nil, nil, err
455455
}
456-
file, m, _, err := ph.Cached()
456+
file, _, _, err := ph.Cached()
457457
if err != nil {
458-
return nil, nil, nil, err
458+
return nil, nil, err
459459
}
460460
if !(file.Pos() <= pos && pos <= file.End()) {
461-
return nil, nil, nil, err
461+
return nil, nil, fmt.Errorf("pos %v, apparently in file %q, is not between %v and %v", pos, ph.File().Identity().URI, file.Pos(), file.End())
462462
}
463-
return file, m, pkg, nil
463+
return file, pkg, nil
464+
}
465+
466+
func (v *view) FindMapperInPackage(searchpkg source.Package, uri span.URI) (*protocol.ColumnMapper, error) {
467+
// Special case for ignored files.
468+
var (
469+
ph source.ParseGoHandle
470+
err error
471+
)
472+
if v.Ignore(uri) {
473+
ph, _, err = v.findIgnoredFile(uri)
474+
} else {
475+
ph, _, err = findFileInPackage(searchpkg, uri)
476+
}
477+
if err != nil {
478+
return nil, err
479+
}
480+
_, m, _, err := ph.Cached()
481+
if err != nil {
482+
return nil, err
483+
}
484+
return m, nil
464485
}
465486

466487
func (v *view) findIgnoredFile(uri span.URI) (source.ParseGoHandle, source.Package, error) {
@@ -482,10 +503,8 @@ func findFileInPackage(pkg source.Package, uri span.URI) (source.ParseGoHandle,
482503
queue = queue[1:]
483504
seen[pkg.ID()] = true
484505

485-
for _, ph := range pkg.CompiledGoFiles() {
486-
if ph.File().Identity().URI == uri {
487-
return ph, pkg, nil
488-
}
506+
if f, err := pkg.File(uri); err == nil {
507+
return f, pkg, nil
489508
}
490509
for _, dep := range pkg.Imports() {
491510
if !seen[dep.ID()] {

internal/lsp/source/completion_format.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func (c *completer) item(cand candidate) (CompletionItem, error) {
160160
if cand.imp != nil && cand.imp.pkg != nil {
161161
searchPkg = cand.imp.pkg
162162
}
163-
file, _, pkg, err := c.snapshot.View().FindPosInPackage(searchPkg, obj.Pos())
163+
file, pkg, err := c.snapshot.View().FindPosInPackage(searchPkg, obj.Pos())
164164
if err != nil {
165165
return item, nil
166166
}

internal/lsp/source/identifier.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ func hasErrorType(obj types.Object) bool {
242242
}
243243

244244
func objToNode(v View, pkg Package, obj types.Object) (ast.Decl, error) {
245-
declAST, _, _, err := v.FindPosInPackage(pkg, obj.Pos())
245+
declAST, _, err := v.FindPosInPackage(pkg, obj.Pos())
246246
if err != nil {
247247
return nil, err
248248
}

internal/lsp/source/implementation.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func (i *IdentifierInfo) Implementation(ctx context.Context) ([]protocol.Locatio
6565
if pkgs[obj] == nil || len(pkg.CompiledGoFiles()) == 0 {
6666
continue
6767
}
68-
file, _, _, err := i.Snapshot.View().FindPosInPackage(pkgs[obj], obj.Pos())
68+
file, _, err := i.Snapshot.View().FindPosInPackage(pkgs[obj], obj.Pos())
6969
if err != nil {
7070
return nil, err
7171
}

internal/lsp/source/util.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ func nodeToMappedRange(view View, m *protocol.ColumnMapper, n ast.Node) (mappedR
169169
}
170170

171171
func posToMappedRange(v View, pkg Package, pos, end token.Pos) (mappedRange, error) {
172-
_, m, _, err := v.FindPosInPackage(pkg, pos)
172+
logicalFilename := v.Session().Cache().FileSet().File(pos).Position(pos).Filename
173+
m, err := v.FindMapperInPackage(pkg, span.FileURI(logicalFilename))
173174
if err != nil {
174175
return mappedRange{}, err
175176
}

internal/lsp/source/view.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ type View interface {
126126

127127
// FindFileInPackage returns the AST and type information for a file that may
128128
// belong to or be part of a dependency of the given package.
129-
FindPosInPackage(pkg Package, pos token.Pos) (*ast.File, *protocol.ColumnMapper, Package, error)
129+
FindPosInPackage(pkg Package, pos token.Pos) (*ast.File, Package, error)
130+
131+
FindMapperInPackage(pkg Package, uri span.URI) (*protocol.ColumnMapper, error)
130132

131133
// Snapshot returns the current snapshot for the view.
132134
Snapshot() Snapshot

0 commit comments

Comments
 (0)