diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go index 9964e0ac38..30f3d6ee5e 100644 --- a/internal/lsp/source/completion.go +++ b/internal/lsp/source/completion.go @@ -917,8 +917,9 @@ func (c *completer) lexical() error { // if an object literal makes a good candidate. For example, if // our expected type is "[]int", this will add a candidate of // "[]int{}". - if _, named := deref(c.expectedType.objType).(*types.Named); !named { - c.literal(c.expectedType.objType, nil) + t := deref(c.expectedType.objType) + if _, named := t.(*types.Named); !named { + c.literal(t, nil) } } diff --git a/internal/lsp/source/completion_literal.go b/internal/lsp/source/completion_literal.go index 816e1b3148..287d43d046 100644 --- a/internal/lsp/source/completion_literal.go +++ b/internal/lsp/source/completion_literal.go @@ -65,9 +65,16 @@ func (c *completer) literal(literalType types.Type, imp *importInfo) { // Check if an object of type literalType would match our expected type. cand := candidate{ - obj: c.fakeObj(literalType), - addressable: true, + obj: c.fakeObj(literalType), } + + switch literalType.Underlying().(type) { + // These literal types are addressable (e.g. "&[]int{}"), others are + // not (e.g. can't do "&(func(){})"). + case *types.Struct, *types.Array, *types.Slice, *types.Map: + cand.addressable = true + } + if !c.matchingCandidate(&cand) { return } diff --git a/internal/lsp/testdata/snippets/literal_snippets.go.in b/internal/lsp/testdata/snippets/literal_snippets.go.in index dfb210b63c..9906a2b78a 100644 --- a/internal/lsp/testdata/snippets/literal_snippets.go.in +++ b/internal/lsp/testdata/snippets/literal_snippets.go.in @@ -10,8 +10,12 @@ import ( func _() { []int{} //@item(litIntSlice, "[]int{}", "", "var") + &[]int{} //@item(litIntSliceAddr, "&[]int{}", "", "var") make([]int, 0) //@item(makeIntSlice, "make([]int, 0)", "", "func") + var _ *[]int = in //@snippet(" //", litIntSliceAddr, "&[]int{$0\\}", "&[]int{$0\\}") + var _ **[]int = in //@complete(" //") + var slice []int slice = i //@snippet(" //", litIntSlice, "[]int{$0\\}", "[]int{$0\\}") slice = m //@snippet(" //", makeIntSlice, "make([]int, ${1:})", "make([]int, ${1:0})") @@ -164,6 +168,9 @@ func _() { func _() { float64() //@item(litFloat64, "float64()", "float64", "var") + // don't complete to "&float64()" + var _ *float64 = float64 //@complete(" //") + var f float64 f = fl //@complete(" //", litFloat64),snippet(" //", litFloat64, "float64($0)", "float64($0)") diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden index 25d58cebe2..1afb5eae2c 100644 --- a/internal/lsp/testdata/summary.txt.golden +++ b/internal/lsp/testdata/summary.txt.golden @@ -1,6 +1,6 @@ -- summary -- -CompletionsCount = 223 -CompletionSnippetCount = 61 +CompletionsCount = 225 +CompletionSnippetCount = 62 UnimportedCompletionsCount = 4 DeepCompletionsCount = 5 FuzzyCompletionsCount = 8