mirror of https://github.com/golang/go.git
internal/lsp: handle breakage caused by CL 207598
textDocument/didChange events need to indicate if the change includes
the full file content or just a diff. Previously, the
contentChange.Range field was a pointer, so if it was nil, then we would
conclude that the file change was for the whole file. Now, the best we
can do is compare it to an empty range, but this still doesn't work if
you are at the beginning of a file. I think that the range needs to be a
pointer for this to work correctly.
Also, some minor changes that came up along the way while debugging:
(1) Don't close over the *cache variable for fear of pinning anything in
memory
(2) Improve the error message when the token.File is nil
(3) Check for a nil token.File earlier
Change-Id: If9f310e92b7fb740b45e6cd3f9ca678a6fb52ff6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/207906
Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
parent
298f0cb188
commit
7f7817c0f9
|
|
@ -52,9 +52,10 @@ func (c *cache) ParseGoHandle(fh source.FileHandle, mode source.ParseMode) sourc
|
|||
file: fh.Identity(),
|
||||
mode: mode,
|
||||
}
|
||||
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, c, fh, mode)
|
||||
data.ast, data.mapper, data.parseError, data.err = parseGo(ctx, fset, fh, mode)
|
||||
return data
|
||||
})
|
||||
return &parseGoHandle{
|
||||
|
|
@ -105,7 +106,7 @@ func hashParseKeys(phs []source.ParseGoHandle) string {
|
|||
return hashContents(b.Bytes())
|
||||
}
|
||||
|
||||
func parseGo(ctx context.Context, c *cache, 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) (file *ast.File, mapper *protocol.ColumnMapper, parseError error, err error) {
|
||||
ctx, done := trace.StartSpan(ctx, "cache.parseGo", telemetry.File.Of(fh.Identity().URI.Filename()))
|
||||
defer done()
|
||||
|
||||
|
|
@ -119,18 +120,21 @@ func parseGo(ctx context.Context, c *cache, fh source.FileHandle, mode source.Pa
|
|||
if mode == source.ParseHeader {
|
||||
parserMode = parser.ImportsOnly | parser.ParseComments
|
||||
}
|
||||
file, parseError = parser.ParseFile(c.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)
|
||||
}
|
||||
if mode == source.ParseExported {
|
||||
trimAST(file)
|
||||
}
|
||||
// Fix any badly parsed parts of the AST.
|
||||
tok := c.fset.File(file.Pos())
|
||||
if err := fix(ctx, file, tok, buf); err != nil {
|
||||
log.Error(ctx, "failed to fix AST", err)
|
||||
}
|
||||
}
|
||||
|
||||
if file == nil {
|
||||
// If the file is nil only due to parse errors,
|
||||
// the parse errors are the actual errors.
|
||||
|
|
@ -140,10 +144,6 @@ func parseGo(ctx context.Context, c *cache, fh source.FileHandle, mode source.Pa
|
|||
}
|
||||
return nil, nil, parseError, err
|
||||
}
|
||||
tok := c.FileSet().File(file.Pos())
|
||||
if tok == nil {
|
||||
return nil, nil, parseError, errors.Errorf("no token.File for %s", fh.Identity().URI)
|
||||
}
|
||||
uri := fh.Identity().URI
|
||||
content, _, err := fh.Read(ctx)
|
||||
if err != nil {
|
||||
|
|
@ -151,7 +151,7 @@ func parseGo(ctx context.Context, c *cache, fh source.FileHandle, mode source.Pa
|
|||
}
|
||||
m := &protocol.ColumnMapper{
|
||||
URI: uri,
|
||||
Converter: span.NewTokenConverter(c.FileSet(), tok),
|
||||
Converter: span.NewTokenConverter(fset, tok),
|
||||
Content: content,
|
||||
}
|
||||
return file, m, parseError, nil
|
||||
|
|
|
|||
|
|
@ -96,9 +96,11 @@ func fullChange(changes []protocol.TextDocumentContentChangeEvent) (string, bool
|
|||
return "", false
|
||||
}
|
||||
// The length of the changes must be 1 at this point.
|
||||
if changes[0].RangeLength == 0 { // used to check changes[0].Range == nil
|
||||
// TODO: This breaks if you insert a character at the beginning of the file.
|
||||
if (changes[0].Range == protocol.Range{} && changes[0].RangeLength == 0) {
|
||||
return changes[0].Text, true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue