lsp/completion: fix postfix completions preceding assignments

In cases like:

  foo.<>
  bar = 123

We weren't detecting that the selector preceding <> was a statement.
The above is parsed as "foo.<>bar = 123", so it looks like <> is
contained in an AssignStmt. This matters because we give different
postfix completions depending on whether it is valid to replace the
surrounding selector with a statement or not.

Updates golang/go#45718.

Change-Id: I8f74505b2c8c7060f1e94433904ff0a987d0cc57
Reviewed-on: https://go-review.googlesource.com/c/tools/+/313269
Run-TryBot: Muir Manders <muir@mnd.rs>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Trust: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Muir Manders 2021-04-23 15:10:27 -07:00 committed by Robert Findley
parent f74a6698e3
commit 716a04c652
3 changed files with 31 additions and 3 deletions

View File

@ -303,11 +303,25 @@ func (c *completer) addPostfixSnippetCandidates(ctx context.Context, sel *ast.Se
return
}
tokFile := c.snapshot.FileSet().File(c.pos)
// Only replace sel with a statement if sel is already a statement.
var stmtOK bool
for i, n := range c.path {
if n == sel && i < len(c.path)-1 {
_, stmtOK = c.path[i+1].(*ast.ExprStmt)
switch p := c.path[i+1].(type) {
case *ast.ExprStmt:
stmtOK = true
case *ast.AssignStmt:
// In cases like:
//
// foo.<>
// bar = 123
//
// detect that "foo." makes up the entire statement since the
// apparent selector spans lines.
stmtOK = tokFile.Line(c.pos) < tokFile.Line(p.TokPos)
}
break
}
}
@ -328,7 +342,6 @@ func (c *completer) addPostfixSnippetCandidates(ctx context.Context, sel *ast.Se
//
// and adjust afterDot so that we don't mistakenly delete the
// newline thinking "bar" is part of our selector.
tokFile := c.snapshot.FileSet().File(c.pos)
if startLine := tokFile.Line(sel.Pos()); startLine != tokFile.Line(afterDot) {
if tokFile.Line(c.pos) != startLine {
return

View File

@ -25,3 +25,18 @@ func _() {
var blah func() []int
blah().append //@complete(" //")
}
func _() {
/* append! */ //@item(postfixAppend, "append!", "append and re-assign slice", "snippet")
/* last! */ //@item(postfixLast, "last!", "s[len(s)-1]", "snippet")
/* print! */ //@item(postfixPrint, "print!", "print to stdout", "snippet")
/* range! */ //@item(postfixRange, "range!", "range over slice", "snippet")
/* reverse! */ //@item(postfixReverse, "reverse!", "reverse slice", "snippet")
/* sort! */ //@item(postfixSort, "sort!", "sort.Slice()", "snippet")
/* var! */ //@item(postfixVar, "var!", "assign to variable", "snippet")
var foo []int
foo. //@complete(" //", postfixAppend, postfixCopy, postfixLast, postfixPrint, postfixRange, postfixReverse, postfixSort, postfixVar)
foo = nil
}

View File

@ -1,7 +1,7 @@
-- summary --
CallHierarchyCount = 2
CodeLensCount = 5
CompletionsCount = 262
CompletionsCount = 263
CompletionSnippetCount = 95
UnimportedCompletionsCount = 5
DeepCompletionsCount = 5