internal/lsp: ignore period ('.') triggered completions in comments

Period triggered completions don't provide any use in comments and in
worst case can be nuisance. LSP provides a completion context which
provides more info about what triggered a completion and hence we can
use this to ignore period triggererd completions. This will also provide
us options to deal with retriggered completions etc. better in the
future.

Change-Id: I8449aee0fe3cf5f9acf315865ac854d5c894d044
Reviewed-on: https://go-review.googlesource.com/c/tools/+/250337
Run-TryBot: Danish Dua <danishdua@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go
index aa28525..221ca9e 100644
--- a/internal/lsp/completion.go
+++ b/internal/lsp/completion.go
@@ -25,7 +25,7 @@
 	var surrounding *source.Selection
 	switch fh.Kind() {
 	case source.Go:
-		candidates, surrounding, err = source.Completion(ctx, snapshot, fh, params.Position)
+		candidates, surrounding, err = source.Completion(ctx, snapshot, fh, params.Position, params.Context.TriggerCharacter)
 	case source.Mod:
 		candidates, surrounding = nil, nil
 	}
diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go
index bca2ac2..43eb01c 100644
--- a/internal/lsp/source/completion.go
+++ b/internal/lsp/source/completion.go
@@ -141,6 +141,9 @@
 	qf       types.Qualifier
 	opts     *completionOptions
 
+	// triggerCharacter is the character that triggered this request, if any.
+	triggerCharacter string
+
 	// filename is the name of the file associated with this completion request.
 	filename string
 
@@ -460,7 +463,7 @@
 // The selection is computed based on the preceding identifier and can be used by
 // the client to score the quality of the completion. For instance, some clients
 // may tolerate imperfect matches as valid completion results, since users may make typos.
-func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, protoPos protocol.Position) ([]CompletionItem, *Selection, error) {
+func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, protoPos protocol.Position, triggerCharacter string) ([]CompletionItem, *Selection, error) {
 	ctx, done := event.Start(ctx, "source.Completion")
 	defer done()
 
@@ -519,6 +522,7 @@
 		pkg:                       pkg,
 		snapshot:                  snapshot,
 		qf:                        qualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo()),
+		triggerCharacter:          triggerCharacter,
 		filename:                  fh.URI().Filename(),
 		file:                      pgf.File,
 		path:                      path,
@@ -732,8 +736,14 @@
 	}
 }
 
-// populateCommentCompletions yields completions for comments preceding or in declarationss
+// populateCommentCompletions yields completions for comments preceding or in declarations
 func (c *completer) populateCommentCompletions(ctx context.Context, comment *ast.CommentGroup) {
+	// If the completion was triggered by a period, ignore it. These types of
+	// completions will not be useful in comments.
+	if c.triggerCharacter == "." {
+		return
+	}
+
 	// Using the comment position find the line after
 	file := c.snapshot.FileSet().File(comment.End())
 	if file == nil {
diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go
index 657b98e..85f55bd 100644
--- a/internal/lsp/source/source_test.go
+++ b/internal/lsp/source/source_test.go
@@ -307,7 +307,7 @@
 	list, surrounding, err := source.Completion(r.ctx, r.snapshot, fh, protocol.Position{
 		Line:      float64(src.Start().Line() - 1),
 		Character: float64(src.Start().Column() - 1),
-	})
+	}, "")
 	if err != nil && !errors.As(err, &source.ErrIsDefinition{}) {
 		t.Fatalf("failed for %v: %v", src, err)
 	}