mirror of
https://github.com/golang/go
synced 2024-11-05 14:46:11 -07:00
internal/lsp/cache: add file contents to ParseGoHandle
Currently there is no need for this because the file contents are part of the file handle. This change is in preparation for an impending improvement that tweaks the source code during the parse stage to fix certain kind of terminal parse errors. Any code that wants to use an *ast.File or *token.File in conjunction with the file contents needs access to the doctored source code so things line up. Change-Id: I59d83d3d6150aa1264761aa2c1f6c1269075a2ce Reviewed-on: https://go-review.googlesource.com/c/tools/+/218979 Run-TryBot: Muir Manders <muir@mnd.rs> Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
cbc0cc175f
commit
49b8ac185c
2
internal/lsp/cache/check.go
vendored
2
internal/lsp/cache/check.go
vendored
@ -295,7 +295,7 @@ func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode sourc
|
||||
for i, ph := range pkg.compiledGoFiles {
|
||||
wg.Add(1)
|
||||
go func(i int, ph source.ParseGoHandle) {
|
||||
files[i], _, parseErrors[i], actualErrors[i] = ph.Parse(ctx)
|
||||
files[i], _, _, parseErrors[i], actualErrors[i] = ph.Parse(ctx)
|
||||
wg.Done()
|
||||
}(i, ph)
|
||||
}
|
||||
|
8
internal/lsp/cache/errors.go
vendored
8
internal/lsp/cache/errors.go
vendored
@ -181,7 +181,7 @@ func typeErrorRange(ctx context.Context, fset *token.FileSet, pkg *pkg, pos toke
|
||||
if err != nil {
|
||||
return span.Span{}, err
|
||||
}
|
||||
_, m, _, err := ph.Cached()
|
||||
_, _, m, _, err := ph.Cached()
|
||||
if err != nil {
|
||||
return span.Span{}, err
|
||||
}
|
||||
@ -217,7 +217,7 @@ func scannerErrorRange(ctx context.Context, fset *token.FileSet, pkg *pkg, posn
|
||||
if err != nil {
|
||||
return span.Span{}, err
|
||||
}
|
||||
file, _, _, err := ph.Cached()
|
||||
file, _, _, _, err := ph.Cached()
|
||||
if err != nil {
|
||||
return span.Span{}, err
|
||||
}
|
||||
@ -236,7 +236,7 @@ func spanToRange(ctx context.Context, pkg *pkg, spn span.Span) (protocol.Range,
|
||||
if err != nil {
|
||||
return protocol.Range{}, err
|
||||
}
|
||||
_, m, _, err := ph.Cached()
|
||||
_, _, m, _, err := ph.Cached()
|
||||
if err != nil {
|
||||
return protocol.Range{}, err
|
||||
}
|
||||
@ -276,7 +276,7 @@ func parseGoListImportCycleError(ctx context.Context, fset *token.FileSet, e pac
|
||||
// Imports have quotation marks around them.
|
||||
circImp := strconv.Quote(importList[1])
|
||||
for _, ph := range pkg.compiledGoFiles {
|
||||
fh, _, _, err := ph.Parse(ctx)
|
||||
fh, _, _, _, err := ph.Parse(ctx)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
36
internal/lsp/cache/parse.go
vendored
36
internal/lsp/cache/parse.go
vendored
@ -41,6 +41,7 @@ type parseGoHandle struct {
|
||||
type parseGoData struct {
|
||||
memoize.NoCopy
|
||||
|
||||
src []byte
|
||||
ast *ast.File
|
||||
parseError error // errors associated with parsing the file
|
||||
mapper *protocol.ColumnMapper
|
||||
@ -54,9 +55,7 @@ func (c *cache) ParseGoHandle(fh source.FileHandle, mode source.ParseMode) sourc
|
||||
}
|
||||
fset := c.fset
|
||||
h := c.store.Bind(key, func(ctx context.Context) interface{} {
|
||||
data := &parseGoData{}
|
||||
data.ast, data.mapper, data.parseError, data.err = parseGo(ctx, fset, fh, mode)
|
||||
return data
|
||||
return parseGo(ctx, fset, fh, mode)
|
||||
})
|
||||
return &parseGoHandle{
|
||||
handle: h,
|
||||
@ -77,22 +76,22 @@ func (pgh *parseGoHandle) Mode() source.ParseMode {
|
||||
return pgh.mode
|
||||
}
|
||||
|
||||
func (pgh *parseGoHandle) Parse(ctx context.Context) (*ast.File, *protocol.ColumnMapper, error, error) {
|
||||
func (pgh *parseGoHandle) Parse(ctx context.Context) (*ast.File, []byte, *protocol.ColumnMapper, error, error) {
|
||||
v := pgh.handle.Get(ctx)
|
||||
if v == nil {
|
||||
return nil, nil, nil, errors.Errorf("no parsed file for %s", pgh.File().Identity().URI)
|
||||
return nil, nil, nil, nil, errors.Errorf("no parsed file for %s", pgh.File().Identity().URI)
|
||||
}
|
||||
data := v.(*parseGoData)
|
||||
return data.ast, data.mapper, data.parseError, data.err
|
||||
return data.ast, data.src, data.mapper, data.parseError, data.err
|
||||
}
|
||||
|
||||
func (pgh *parseGoHandle) Cached() (*ast.File, *protocol.ColumnMapper, error, error) {
|
||||
func (pgh *parseGoHandle) Cached() (*ast.File, []byte, *protocol.ColumnMapper, error, error) {
|
||||
v := pgh.handle.Cached()
|
||||
if v == nil {
|
||||
return nil, nil, nil, errors.Errorf("no cached AST for %s", pgh.file.Identity().URI)
|
||||
return nil, nil, nil, nil, errors.Errorf("no cached AST for %s", pgh.file.Identity().URI)
|
||||
}
|
||||
data := v.(*parseGoData)
|
||||
return data.ast, data.mapper, data.parseError, data.err
|
||||
return data.ast, data.src, data.mapper, data.parseError, data.err
|
||||
}
|
||||
|
||||
func hashParseKey(ph source.ParseGoHandle) string {
|
||||
@ -110,16 +109,16 @@ func hashParseKeys(phs []source.ParseGoHandle) string {
|
||||
return hashContents(b.Bytes())
|
||||
}
|
||||
|
||||
func parseGo(ctx context.Context, fset *token.FileSet, fh source.FileHandle, mode source.ParseMode) (file *ast.File, mapper *protocol.ColumnMapper, parseError error, err error) {
|
||||
func parseGo(ctx context.Context, fset *token.FileSet, fh source.FileHandle, mode source.ParseMode) *parseGoData {
|
||||
ctx, done := trace.StartSpan(ctx, "cache.parseGo", telemetry.File.Of(fh.Identity().URI.Filename()))
|
||||
defer done()
|
||||
|
||||
if fh.Identity().Kind != source.Go {
|
||||
return nil, nil, nil, errors.Errorf("cannot parse non-Go file %s", fh.Identity().URI)
|
||||
return &parseGoData{err: errors.Errorf("cannot parse non-Go file %s", fh.Identity().URI)}
|
||||
}
|
||||
buf, _, err := fh.Read(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return &parseGoData{err: err}
|
||||
}
|
||||
parseLimit <- struct{}{}
|
||||
defer func() { <-parseLimit }()
|
||||
@ -127,13 +126,13 @@ func parseGo(ctx context.Context, fset *token.FileSet, fh source.FileHandle, mod
|
||||
if mode == source.ParseHeader {
|
||||
parserMode = parser.ImportsOnly | parser.ParseComments
|
||||
}
|
||||
file, parseError = parser.ParseFile(fset, fh.Identity().URI.Filename(), buf, parserMode)
|
||||
file, parseError := parser.ParseFile(fset, fh.Identity().URI.Filename(), buf, parserMode)
|
||||
var tok *token.File
|
||||
if file != nil {
|
||||
// Fix any badly parsed parts of the AST.
|
||||
tok = fset.File(file.Pos())
|
||||
if tok == nil {
|
||||
return nil, nil, nil, errors.Errorf("successfully parsed but no token.File for %s (%v)", fh.Identity().URI, parseError)
|
||||
return &parseGoData{err: errors.Errorf("successfully parsed but no token.File for %s (%v)", fh.Identity().URI, parseError)}
|
||||
}
|
||||
if mode == source.ParseExported {
|
||||
trimAST(file)
|
||||
@ -149,7 +148,7 @@ func parseGo(ctx context.Context, fset *token.FileSet, fh source.FileHandle, mod
|
||||
if err == nil {
|
||||
err = errors.Errorf("no AST for %s", fh.Identity().URI)
|
||||
}
|
||||
return nil, nil, parseError, err
|
||||
return &parseGoData{parseError: parseError, err: err}
|
||||
}
|
||||
m := &protocol.ColumnMapper{
|
||||
URI: fh.Identity().URI,
|
||||
@ -157,7 +156,12 @@ func parseGo(ctx context.Context, fset *token.FileSet, fh source.FileHandle, mod
|
||||
Content: buf,
|
||||
}
|
||||
|
||||
return file, m, parseError, nil
|
||||
return &parseGoData{
|
||||
src: buf,
|
||||
ast: file,
|
||||
mapper: m,
|
||||
parseError: parseError,
|
||||
}
|
||||
}
|
||||
|
||||
// trimAST clears any part of the AST not relevant to type checking
|
||||
|
2
internal/lsp/cache/pkg.go
vendored
2
internal/lsp/cache/pkg.go
vendored
@ -71,7 +71,7 @@ func (p *pkg) File(uri span.URI) (source.ParseGoHandle, error) {
|
||||
func (p *pkg) GetSyntax() []*ast.File {
|
||||
var syntax []*ast.File
|
||||
for _, ph := range p.compiledGoFiles {
|
||||
file, _, _, err := ph.Cached()
|
||||
file, _, _, _, err := ph.Cached()
|
||||
if err == nil {
|
||||
syntax = append(syntax, file)
|
||||
}
|
||||
|
4
internal/lsp/cache/snapshot.go
vendored
4
internal/lsp/cache/snapshot.go
vendored
@ -734,8 +734,8 @@ func (s *snapshot) shouldInvalidateMetadata(ctx context.Context, originalFH, cur
|
||||
return originalFH.Identity().URI == modfile
|
||||
}
|
||||
// Get the original and current parsed files in order to check package name and imports.
|
||||
original, _, _, originalErr := s.view.session.cache.ParseGoHandle(originalFH, source.ParseHeader).Parse(ctx)
|
||||
current, _, _, currentErr := s.view.session.cache.ParseGoHandle(currentFH, source.ParseHeader).Parse(ctx)
|
||||
original, _, _, _, originalErr := s.view.session.cache.ParseGoHandle(originalFH, source.ParseHeader).Parse(ctx)
|
||||
current, _, _, _, currentErr := s.view.session.cache.ParseGoHandle(currentFH, source.ParseHeader).Parse(ctx)
|
||||
if originalErr != nil || currentErr != nil {
|
||||
return (originalErr == nil) != (currentErr == nil)
|
||||
}
|
||||
|
2
internal/lsp/cache/view.go
vendored
2
internal/lsp/cache/view.go
vendored
@ -245,7 +245,7 @@ func (v *view) buildBuiltinPackage(ctx context.Context, goFiles []string) error
|
||||
fset := v.session.cache.fset
|
||||
h := v.session.cache.store.Bind(pgh.File().Identity(), func(ctx context.Context) interface{} {
|
||||
data := &builtinPackageData{}
|
||||
file, _, _, err := pgh.Parse(ctx)
|
||||
file, _, _, _, err := pgh.Parse(ctx)
|
||||
if err != nil {
|
||||
data.err = err
|
||||
return data
|
||||
|
@ -34,7 +34,7 @@ func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLink
|
||||
if fh.Identity().Kind == source.Mod {
|
||||
return nil, nil
|
||||
}
|
||||
file, m, _, err := view.Session().Cache().ParseGoHandle(fh, source.ParseFull).Parse(ctx)
|
||||
file, _, m, _, err := view.Session().Cache().ParseGoHandle(fh, source.ParseFull).Parse(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, pos proto
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("getting file for Completion: %v", err)
|
||||
}
|
||||
file, m, _, err := pgh.Cached()
|
||||
file, src, m, _, err := pgh.Cached()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -500,11 +500,9 @@ func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, pos proto
|
||||
// Otherwise, manually extract the prefix if our containing token
|
||||
// is a keyword. This improves completion after an "accidental
|
||||
// keyword", e.g. completing to "variance" in "someFunc(var<>)".
|
||||
if contents, _, err := pgh.File().Read(ctx); err == nil {
|
||||
id := scanKeyword(c.pos, c.snapshot.View().Session().Cache().FileSet().File(c.pos), contents)
|
||||
if id != nil {
|
||||
c.setSurrounding(id)
|
||||
}
|
||||
id := scanKeyword(c.pos, c.snapshot.View().Session().Cache().FileSet().File(c.pos), src)
|
||||
if id != nil {
|
||||
c.setSurrounding(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ func missingModulesDiagnostics(ctx context.Context, snapshot Snapshot, reports m
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, m, _, err := snapshot.View().Session().Cache().ParseGoHandle(fh, ParseHeader).Parse(ctx)
|
||||
file, _, m, _, err := snapshot.View().Session().Cache().ParseGoHandle(fh, ParseHeader).Parse(ctx)
|
||||
if err != nil {
|
||||
log.Error(ctx, "could not parse go file when checking for missing modules", err)
|
||||
return err
|
||||
|
@ -19,7 +19,7 @@ func FoldingRange(ctx context.Context, snapshot Snapshot, fh FileHandle, lineFol
|
||||
// TODO(suzmue): consider limiting the number of folding ranges returned, and
|
||||
// implement a way to prioritize folding ranges in that case.
|
||||
pgh := snapshot.View().Session().Cache().ParseGoHandle(fh, ParseFull)
|
||||
file, m, _, err := pgh.Parse(ctx)
|
||||
file, _, m, _, err := pgh.Parse(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ func Format(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.T
|
||||
defer done()
|
||||
|
||||
pgh := snapshot.View().Session().Cache().ParseGoHandle(fh, ParseFull)
|
||||
file, m, parseErrors, err := pgh.Parse(ctx)
|
||||
file, _, m, parseErrors, err := pgh.Parse(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -108,7 +108,7 @@ func computeImportEdits(ctx context.Context, view View, ph ParseGoHandle, option
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
origAST, origMapper, _, err := ph.Parse(ctx)
|
||||
origAST, _, origMapper, _, err := ph.Parse(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -144,7 +144,7 @@ func computeOneImportFixEdits(ctx context.Context, view View, ph ParseGoHandle,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
origAST, origMapper, _, err := ph.Parse(ctx)
|
||||
origAST, _, origMapper, _, err := ph.Parse(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func Highlight(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protoc
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting file for Highlight: %v", err)
|
||||
}
|
||||
file, m, _, err := pgh.Parse(ctx)
|
||||
file, _, m, _, err := pgh.Parse(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func Identifier(ctx context.Context, snapshot Snapshot, fh FileHandle, pos proto
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting file for Identifier: %v", err)
|
||||
}
|
||||
file, m, _, err := pgh.Cached()
|
||||
file, _, m, _, err := pgh.Cached()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ func getASTFile(pkg Package, f FileHandle, pos protocol.Position) (*ast.File, to
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
file, m, _, err := pgh.Cached()
|
||||
file, _, m, _, err := pgh.Cached()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ func SignatureHelp(ctx context.Context, snapshot Snapshot, fh FileHandle, pos pr
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("getting file for SignatureHelp: %v", err)
|
||||
}
|
||||
file, m, _, err := pgh.Cached()
|
||||
file, _, m, _, err := pgh.Cached()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func DocumentSymbols(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]p
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting file for DocumentSymbols: %v", err)
|
||||
}
|
||||
file, _, _, err := pgh.Cached()
|
||||
file, _, _, _, err := pgh.Cached()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ func IsGenerated(ctx context.Context, snapshot Snapshot, uri span.URI) bool {
|
||||
return false
|
||||
}
|
||||
ph := snapshot.View().Session().Cache().ParseGoHandle(fh, ParseHeader)
|
||||
parsed, _, _, err := ph.Parse(ctx)
|
||||
parsed, _, _, _, err := ph.Parse(ctx)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@ -647,7 +647,7 @@ func findPosInPackage(v View, searchpkg Package, pos token.Pos) (*ast.File, Pack
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
file, _, _, err := ph.Cached()
|
||||
file, _, _, _, err := ph.Cached()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -671,7 +671,7 @@ func findMapperInPackage(v View, searchpkg Package, uri span.URI) (*protocol.Col
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, m, _, err := ph.Cached()
|
||||
_, _, m, _, err := ph.Cached()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -248,10 +248,10 @@ type ParseGoHandle interface {
|
||||
|
||||
// Parse returns the parsed AST for the file.
|
||||
// If the file is not available, returns nil and an error.
|
||||
Parse(ctx context.Context) (*ast.File, *protocol.ColumnMapper, error, error)
|
||||
Parse(ctx context.Context) (file *ast.File, src []byte, m *protocol.ColumnMapper, parseErr error, err error)
|
||||
|
||||
// Cached returns the AST for this handle, if it has already been stored.
|
||||
Cached() (*ast.File, *protocol.ColumnMapper, error, error)
|
||||
Cached() (file *ast.File, src []byte, m *protocol.ColumnMapper, parseErr error, err error)
|
||||
}
|
||||
|
||||
// ModTidyHandle represents a handle to the modfile for a go.mod.
|
||||
|
@ -42,7 +42,7 @@ func WorkspaceSymbols(ctx context.Context, views []View, query string) ([]protoc
|
||||
}
|
||||
seen[pkg.PkgPath()] = struct{}{}
|
||||
for _, fh := range pkg.CompiledGoFiles() {
|
||||
file, _, _, err := fh.Cached()
|
||||
file, _, _, _, err := fh.Cached()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user