Skip to content

Commit db38d36

Browse files
xieyuschengopherbot
authored andcommitted
gopls/internal/golang/completion: don't offer internal std packages
This CL ensures completions should not offer symbols from unimported packages that cannot be imported because they are "internal". Fixes golang/go#44890 Fixes golang/go#74611 Change-Id: Iae6cdd67518274b8c838c215ec12ef74e3a66c0d Reviewed-on: https://go-review.googlesource.com/c/tools/+/701635 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Alan Donovan <[email protected]> Commit-Queue: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Alan Donovan <[email protected]>
1 parent 74b9e56 commit db38d36

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

gopls/internal/golang/completion/deep_completion.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"time"
1212

1313
"golang.org/x/tools/gopls/internal/util/typesutil"
14+
"golang.org/x/tools/internal/analysisinternal"
1415
)
1516

1617
// MaxDeepCompletions limits deep completion results because in most cases
@@ -161,6 +162,10 @@ func (c *completer) deepSearch(ctx context.Context, minDepth int, deadline *time
161162
continue
162163
}
163164

165+
if cand.imp != nil && !analysisinternal.CanImport(string(c.pkg.Metadata().PkgPath), cand.imp.importPath) {
166+
continue // inaccessible internal package
167+
}
168+
164169
// If we want a type name, don't offer non-type name candidates.
165170
// However, do offer package names since they can contain type names,
166171
// and do offer any candidate without a type since we aren't sure if it

gopls/internal/test/integration/completion/completion_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,49 @@ func compareCompletionLabels(want []string, gotItems []protocol.CompletionItem)
300300
return ""
301301
}
302302

303+
func TestIssue74611(t *testing.T) {
304+
// Completions should not offer symbols from unimported packages
305+
// that cannot be imported because they are "internal".
306+
//
307+
// Ideally, we should test std case as well but because mocking
308+
// a fake stdlib is hard, we just test the 3rd user case.
309+
// std test is done interactively.
310+
const files = `-- go.mod --
311+
module mod.com/cmd
312+
313+
go 1.21
314+
315+
-- a.go --
316+
package pkg
317+
import "fmt"
318+
319+
func main() {
320+
fmt.Println("call Println to use fmt")
321+
_ = maps
322+
} // (completion requested at start of line)
323+
`
324+
325+
WithOptions().Run(t, files, func(t *testing.T, env *Env) {
326+
filename := "a.go"
327+
// Trigger unimported completions for the maps package.
328+
env.OpenFile(filename)
329+
env.Await(env.DoneWithOpen())
330+
loc := env.RegexpSearch(filename, "\n}")
331+
completions := env.Completion(loc)
332+
if len(completions.Items) == 0 {
333+
t.Fatalf("no completion items")
334+
}
335+
runtimeMaps := `"internal/runtime/maps"`
336+
found := slices.ContainsFunc(completions.Items, func(item protocol.CompletionItem) bool {
337+
return item.Detail == runtimeMaps
338+
})
339+
340+
if found {
341+
t.Fatalf("unwanted completion: %s", runtimeMaps)
342+
}
343+
})
344+
}
345+
303346
func TestUnimportedCompletion(t *testing.T) {
304347
const mod = `
305348
-- go.mod --

internal/analysisinternal/analysis_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ func TestCanImport(t *testing.T) {
2222
}{
2323
{"fmt", "internal", true},
2424
{"fmt", "internal/foo", true},
25+
{"fmt", "fmt/internal/foo", true},
26+
{"fmt", "cmd/internal/archive", false},
2527
{"a.com/b", "internal", false},
2628
{"a.com/b", "xinternal", true},
2729
{"a.com/b", "internal/foo", false},

0 commit comments

Comments
 (0)