Skip to content

Commit 86c93e8

Browse files
committed
gopls: unimported completion should use the completion matcher
Fix a bug where unimported completion was using strings.HasPrefix directly, rather than using the configured completion matcher. Fixes golang/go#60545 Change-Id: I96e8e0b2dbfd9f007b166d4a82399c591ffd823a Reviewed-on: https://go-review.googlesource.com/c/tools/+/499795 TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Robert Findley <[email protected]> Reviewed-by: Alan Donovan <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent 04ceacb commit 86c93e8

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

gopls/internal/lsp/source/completion/completion.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,8 +1210,10 @@ func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
12101210

12111211
// quickParse does a quick parse of a single file of package m,
12121212
// extracts exported package members and adds candidates to c.items.
1213-
var itemsMu sync.Mutex // guards c.items
1214-
var enough int32 // atomic bool
1213+
// TODO(rfindley): synchronizing access to c here does not feel right.
1214+
// Consider adding a concurrency-safe API for completer.
1215+
var cMu sync.Mutex // guards c.items and c.matcher
1216+
var enough int32 // atomic bool
12151217
quickParse := func(uri span.URI, m *source.Metadata) error {
12161218
if atomic.LoadInt32(&enough) != 0 {
12171219
return nil
@@ -1231,13 +1233,22 @@ func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
12311233
return
12321234
}
12331235

1234-
if !id.IsExported() ||
1235-
sel.Sel.Name != "_" && !strings.HasPrefix(id.Name, sel.Sel.Name) {
1236-
return // not a match
1236+
if !id.IsExported() {
1237+
return
1238+
}
1239+
1240+
cMu.Lock()
1241+
score := c.matcher.Score(id.Name)
1242+
cMu.Unlock()
1243+
1244+
if sel.Sel.Name != "_" && score == 0 {
1245+
return // not a match; avoid constructing the completion item below
12371246
}
12381247

12391248
// The only detail is the kind and package: `var (from "example.com/foo")`
12401249
// TODO(adonovan): pretty-print FuncDecl.FuncType or TypeSpec.Type?
1250+
// TODO(adonovan): should this score consider the actual c.matcher.Score
1251+
// of the item? How does this compare with the deepState.enqueue path?
12411252
item := CompletionItem{
12421253
Label: id.Name,
12431254
Detail: fmt.Sprintf("%s (from %q)", strings.ToLower(tok.String()), m.PkgPath),
@@ -1298,12 +1309,12 @@ func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
12981309
item.snippet = &sn
12991310
}
13001311

1301-
itemsMu.Lock()
1312+
cMu.Lock()
13021313
c.items = append(c.items, item)
13031314
if len(c.items) >= unimportedMemberTarget {
13041315
atomic.StoreInt32(&enough, 1)
13051316
}
1306-
itemsMu.Unlock()
1317+
cMu.Unlock()
13071318
})
13081319
return nil
13091320
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
This test checks that unimported completion is case-insensitive.
2+
3+
-- go.mod --
4+
module mod.test
5+
6+
go 1.18
7+
8+
-- main.go --
9+
package main
10+
11+
func main() {
12+
fmt.p //@complete(re"p()","Print", "Printf", "Println"), diag("fmt", re"(undefined|undeclared)")
13+
}
14+
15+
-- other.go --
16+
package main
17+
18+
// Including another package that imports "fmt" causes completion to use the
19+
// existing metadata, which is the codepath leading to golang/go#60545.
20+
import "fmt"
21+
22+
func _() {
23+
fmt.Println()
24+
}

0 commit comments

Comments
 (0)