internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
// Copyright 2019 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package source
|
|
|
|
|
|
|
|
import (
|
2020-04-05 23:18:15 -06:00
|
|
|
"context"
|
2019-10-15 10:26:11 -06:00
|
|
|
"go/ast"
|
|
|
|
"go/token"
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
"go/types"
|
|
|
|
"strings"
|
2019-09-05 13:04:13 -06:00
|
|
|
"unicode"
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
|
2019-10-15 10:26:11 -06:00
|
|
|
"golang.org/x/tools/internal/lsp/diff"
|
2019-09-24 22:46:57 -06:00
|
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
"golang.org/x/tools/internal/lsp/snippet"
|
2020-03-07 19:28:21 -07:00
|
|
|
"golang.org/x/tools/internal/telemetry/event"
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
)
|
|
|
|
|
2019-09-05 13:04:13 -06:00
|
|
|
// literal generates composite literal, function literal, and make()
|
|
|
|
// completion items.
|
2020-04-05 23:18:15 -06:00
|
|
|
func (c *completer) literal(ctx context.Context, literalType types.Type, imp *importInfo) {
|
2019-12-29 00:22:12 -07:00
|
|
|
if !c.opts.literal {
|
2019-12-06 15:29:09 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-01-17 14:53:10 -07:00
|
|
|
expType := c.inference.objType
|
2019-11-15 23:28:29 -07:00
|
|
|
|
internal/lsp/source: untangle completion type comparison
The code to check if a candidate object matches our candidate
inference had become complicated, messy, and in some cases incorrect.
The main source of the complexity is the "derived" expected and
candidate types. When considering a candidate object "foo", we also
consider "&foo", "foo()", and "*foo", as appropriate. On the expected
side of things, when completing the a variadic function parameter we
expect either the variadic slice type and the scalar element type.
The code had grown organically to handle the expanding concerns, but
that resulted in confused code that didn't handle the interplay
between the various facets of candidate inference.
For example, we were inappropriately invoking func candidates when
completing variadic args:
func foo(...func())
func bar() {}
foo(bar<>) // oops - expanded to "bar()"
and we weren't type matching functions properly as builtin args:
func myMap() map[string]int { ... }
delete(myM<>) // we weren't preferring (or invoking) "myMap()"
We also had methods like "typeMatches" which took both a "candidate"
object and a "candType" type, which doesn't make sense because the
candidate contains the type already.
Now instead we explicitly iterate over all the derived candidate and
expected types so they are treated the same. There are still some
warts left but I think this is a step in the right direction.
Change-Id: If84a84b34a8fb771a32231f7ab64ca192f611b3d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/218877
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2020-02-08 20:59:28 -07:00
|
|
|
if c.inference.variadicType != nil {
|
2019-11-15 23:28:29 -07:00
|
|
|
// Don't offer literal slice candidates for variadic arguments.
|
|
|
|
// For example, don't offer "[]interface{}{}" in "fmt.Print(<>)".
|
2020-01-17 14:53:10 -07:00
|
|
|
if c.inference.matchesVariadic(literalType) {
|
2019-11-15 23:28:29 -07:00
|
|
|
return
|
|
|
|
}
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
|
2019-11-15 23:28:29 -07:00
|
|
|
// Otherwise, consider our expected type to be the variadic
|
|
|
|
// element type, not the slice type.
|
internal/lsp/source: untangle completion type comparison
The code to check if a candidate object matches our candidate
inference had become complicated, messy, and in some cases incorrect.
The main source of the complexity is the "derived" expected and
candidate types. When considering a candidate object "foo", we also
consider "&foo", "foo()", and "*foo", as appropriate. On the expected
side of things, when completing the a variadic function parameter we
expect either the variadic slice type and the scalar element type.
The code had grown organically to handle the expanding concerns, but
that resulted in confused code that didn't handle the interplay
between the various facets of candidate inference.
For example, we were inappropriately invoking func candidates when
completing variadic args:
func foo(...func())
func bar() {}
foo(bar<>) // oops - expanded to "bar()"
and we weren't type matching functions properly as builtin args:
func myMap() map[string]int { ... }
delete(myM<>) // we weren't preferring (or invoking) "myMap()"
We also had methods like "typeMatches" which took both a "candidate"
object and a "candType" type, which doesn't make sense because the
candidate contains the type already.
Now instead we explicitly iterate over all the derived candidate and
expected types so they are treated the same. There are still some
warts left but I think this is a step in the right direction.
Change-Id: If84a84b34a8fb771a32231f7ab64ca192f611b3d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/218877
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2020-02-08 20:59:28 -07:00
|
|
|
expType = c.inference.variadicType
|
2019-11-15 23:28:29 -07:00
|
|
|
}
|
2019-11-03 18:47:21 -07:00
|
|
|
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
// Avoid literal candidates if the expected type is an empty
|
|
|
|
// interface. It isn't very useful to suggest a literal candidate of
|
|
|
|
// every possible type.
|
2019-11-03 18:47:21 -07:00
|
|
|
if expType != nil && isEmptyInterface(expType) {
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// We handle unnamed literal completions explicitly before searching
|
|
|
|
// for candidates. Avoid named-type literal completions for
|
|
|
|
// unnamed-type expected type since that results in duplicate
|
|
|
|
// candidates. For example, in
|
|
|
|
//
|
|
|
|
// type mySlice []int
|
|
|
|
// var []int = <>
|
|
|
|
//
|
|
|
|
// don't offer "mySlice{}" since we have already added a candidate
|
|
|
|
// of "[]int{}".
|
2019-11-03 18:47:21 -07:00
|
|
|
if _, named := literalType.(*types.Named); named && expType != nil {
|
|
|
|
if _, named := deref(expType).(*types.Named); !named {
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-22 10:58:14 -07:00
|
|
|
// Check if an object of type literalType would match our expected type.
|
|
|
|
cand := candidate{
|
2019-12-26 22:31:56 -07:00
|
|
|
obj: c.fakeObj(literalType),
|
2019-12-22 10:58:14 -07:00
|
|
|
}
|
2019-12-26 22:31:56 -07:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
internal/lsp/source: untangle completion type comparison
The code to check if a candidate object matches our candidate
inference had become complicated, messy, and in some cases incorrect.
The main source of the complexity is the "derived" expected and
candidate types. When considering a candidate object "foo", we also
consider "&foo", "foo()", and "*foo", as appropriate. On the expected
side of things, when completing the a variadic function parameter we
expect either the variadic slice type and the scalar element type.
The code had grown organically to handle the expanding concerns, but
that resulted in confused code that didn't handle the interplay
between the various facets of candidate inference.
For example, we were inappropriately invoking func candidates when
completing variadic args:
func foo(...func())
func bar() {}
foo(bar<>) // oops - expanded to "bar()"
and we weren't type matching functions properly as builtin args:
func myMap() map[string]int { ... }
delete(myM<>) // we weren't preferring (or invoking) "myMap()"
We also had methods like "typeMatches" which took both a "candidate"
object and a "candType" type, which doesn't make sense because the
candidate contains the type already.
Now instead we explicitly iterate over all the derived candidate and
expected types so they are treated the same. There are still some
warts left but I think this is a step in the right direction.
Change-Id: If84a84b34a8fb771a32231f7ab64ca192f611b3d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/218877
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2020-02-08 20:59:28 -07:00
|
|
|
if !c.matchingCandidate(&cand) {
|
2019-12-22 10:58:14 -07:00
|
|
|
return
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
}
|
|
|
|
|
2019-10-15 10:26:11 -06:00
|
|
|
var (
|
|
|
|
qf = c.qf
|
|
|
|
sel = enclosingSelector(c.path, c.pos)
|
|
|
|
)
|
|
|
|
|
|
|
|
// Don't qualify the type name if we are in a selector expression
|
|
|
|
// since the package name is already present.
|
|
|
|
if sel != nil {
|
|
|
|
qf = func(_ *types.Package) string { return "" }
|
|
|
|
}
|
|
|
|
|
|
|
|
typeName := types.TypeString(literalType, qf)
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
|
|
|
|
// A type name of "[]int" doesn't work very will with the matcher
|
|
|
|
// since "[" isn't a valid identifier prefix. Here we strip off the
|
|
|
|
// slice (and array) prefix yielding just "int".
|
|
|
|
matchName := typeName
|
|
|
|
switch t := literalType.(type) {
|
|
|
|
case *types.Slice:
|
2019-10-15 10:26:11 -06:00
|
|
|
matchName = types.TypeString(t.Elem(), qf)
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
case *types.Array:
|
2019-10-15 10:26:11 -06:00
|
|
|
matchName = types.TypeString(t.Elem(), qf)
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
}
|
|
|
|
|
2020-04-05 23:18:15 -06:00
|
|
|
addlEdits, err := c.importEdits(ctx, imp)
|
2019-10-15 15:42:30 -06:00
|
|
|
if err != nil {
|
2020-04-05 23:18:15 -06:00
|
|
|
event.Error(ctx, "error adding import for literal candidate", err)
|
2019-10-15 15:42:30 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
// If prefix matches the type name, client may want a composite literal.
|
|
|
|
if score := c.matcher.Score(matchName); score >= 0 {
|
2019-12-22 10:58:14 -07:00
|
|
|
if cand.takeAddress {
|
2019-10-15 10:26:11 -06:00
|
|
|
if sel != nil {
|
|
|
|
// If we are in a selector we must place the "&" before the selector.
|
|
|
|
// For example, "foo.B<>" must complete to "&foo.Bar{}", not
|
|
|
|
// "foo.&Bar{}".
|
2019-12-27 09:57:52 -07:00
|
|
|
edits, err := prependEdit(c.snapshot.View().Session().Cache().FileSet(), c.mapper, sel, "&")
|
2019-10-15 10:26:11 -06:00
|
|
|
if err != nil {
|
2020-04-05 23:18:15 -06:00
|
|
|
event.Error(ctx, "error making edit for literal pointer completion", err)
|
2019-10-15 10:26:11 -06:00
|
|
|
return
|
|
|
|
}
|
2019-10-15 15:42:30 -06:00
|
|
|
addlEdits = append(addlEdits, edits...)
|
2019-10-15 10:26:11 -06:00
|
|
|
} else {
|
|
|
|
// Otherwise we can stick the "&" directly before the type name.
|
|
|
|
typeName = "&" + typeName
|
|
|
|
}
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
switch t := literalType.Underlying().(type) {
|
|
|
|
case *types.Struct, *types.Array, *types.Slice, *types.Map:
|
2019-10-15 15:42:30 -06:00
|
|
|
c.compositeLiteral(t, typeName, float64(score), addlEdits)
|
2019-12-13 17:17:40 -07:00
|
|
|
case *types.Signature:
|
|
|
|
// Add a literal completion for a signature type that implements
|
|
|
|
// an interface. For example, offer "http.HandlerFunc()" when
|
|
|
|
// expected type is "http.Handler".
|
|
|
|
if isInterface(expType) {
|
|
|
|
c.basicLiteral(t, typeName, float64(score), addlEdits)
|
|
|
|
}
|
|
|
|
case *types.Basic:
|
2019-09-16 20:07:16 -06:00
|
|
|
// Add a literal completion for basic types that implement our
|
|
|
|
// expected interface (e.g. named string type http.Dir
|
2019-12-06 15:29:09 -07:00
|
|
|
// implements http.FileSystem), or are identical to our expected
|
|
|
|
// type (i.e. yielding a type conversion such as "float64()").
|
|
|
|
if isInterface(expType) || types.Identical(expType, literalType) {
|
2019-10-15 15:42:30 -06:00
|
|
|
c.basicLiteral(t, typeName, float64(score), addlEdits)
|
2019-09-16 20:07:16 -06:00
|
|
|
}
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If prefix matches "make", client may want a "make()"
|
|
|
|
// invocation. We also include the type name to allow for more
|
|
|
|
// flexible fuzzy matching.
|
2019-12-22 10:58:14 -07:00
|
|
|
if score := c.matcher.Score("make." + matchName); !cand.takeAddress && score >= 0 {
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
switch literalType.Underlying().(type) {
|
|
|
|
case *types.Slice:
|
|
|
|
// The second argument to "make()" for slices is required, so default to "0".
|
2019-10-15 15:42:30 -06:00
|
|
|
c.makeCall(typeName, "0", float64(score), addlEdits)
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
case *types.Map, *types.Chan:
|
|
|
|
// Maps and channels don't require the second argument, so omit
|
|
|
|
// to keep things simple for now.
|
2019-10-15 15:42:30 -06:00
|
|
|
c.makeCall(typeName, "", float64(score), addlEdits)
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
}
|
|
|
|
}
|
2019-09-05 13:04:13 -06:00
|
|
|
|
|
|
|
// If prefix matches "func", client may want a function literal.
|
2019-12-22 10:58:14 -07:00
|
|
|
if score := c.matcher.Score("func"); !cand.takeAddress && score >= 0 && !isInterface(expType) {
|
2019-09-05 13:04:13 -06:00
|
|
|
switch t := literalType.Underlying().(type) {
|
|
|
|
case *types.Signature:
|
|
|
|
c.functionLiteral(t, float64(score))
|
|
|
|
}
|
|
|
|
}
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
}
|
|
|
|
|
2019-12-27 09:57:52 -07:00
|
|
|
// prependEdit produces text edits that preprend the specified prefix
|
|
|
|
// to the specified node.
|
|
|
|
func prependEdit(fset *token.FileSet, m *protocol.ColumnMapper, node ast.Node, prefix string) ([]protocol.TextEdit, error) {
|
2019-11-22 13:20:08 -07:00
|
|
|
rng := newMappedRange(fset, m, node.Pos(), node.Pos())
|
2019-10-15 10:26:11 -06:00
|
|
|
spn, err := rng.Span()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return ToProtocolEdits(m, []diff.TextEdit{{
|
|
|
|
Span: spn,
|
2019-12-27 09:57:52 -07:00
|
|
|
NewText: prefix,
|
2019-10-15 10:26:11 -06:00
|
|
|
}})
|
|
|
|
}
|
|
|
|
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
// literalCandidateScore is the base score for literal candidates.
|
|
|
|
// Literal candidates match the expected type so they should be high
|
|
|
|
// scoring, but we want them ranked below lexical objects of the
|
|
|
|
// correct type, so scale down highScore.
|
|
|
|
const literalCandidateScore = highScore / 2
|
|
|
|
|
2019-09-05 13:04:13 -06:00
|
|
|
// functionLiteral adds a function literal completion item for the
|
|
|
|
// given signature.
|
|
|
|
func (c *completer) functionLiteral(sig *types.Signature, matchScore float64) {
|
|
|
|
snip := &snippet.Builder{}
|
|
|
|
snip.WriteText("func(")
|
|
|
|
seenParamNames := make(map[string]bool)
|
|
|
|
for i := 0; i < sig.Params().Len(); i++ {
|
|
|
|
if i > 0 {
|
|
|
|
snip.WriteText(", ")
|
|
|
|
}
|
|
|
|
|
|
|
|
p := sig.Params().At(i)
|
|
|
|
name := p.Name()
|
|
|
|
|
|
|
|
// If the parameter has no name in the signature, we need to try
|
|
|
|
// come up with a parameter name.
|
|
|
|
if name == "" {
|
|
|
|
// Our parameter names are guesses, so they must be placeholders
|
|
|
|
// for easy correction. If placeholders are disabled, don't
|
|
|
|
// offer the completion.
|
2019-12-29 00:22:12 -07:00
|
|
|
if !c.opts.placeholders {
|
2019-09-05 13:04:13 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try abbreviating named types. If the type isn't named, or the
|
|
|
|
// abbreviation duplicates a previous name, give up and use
|
|
|
|
// "_". The user will have to provide a name for this parameter
|
|
|
|
// in order to use it.
|
|
|
|
if named, ok := deref(p.Type()).(*types.Named); ok {
|
|
|
|
name = abbreviateCamel(named.Obj().Name())
|
|
|
|
if seenParamNames[name] {
|
|
|
|
name = "_"
|
|
|
|
} else {
|
|
|
|
seenParamNames[name] = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
name = "_"
|
|
|
|
}
|
|
|
|
snip.WritePlaceholder(func(b *snippet.Builder) {
|
|
|
|
b.WriteText(name)
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
snip.WriteText(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the following param's type is identical to this one, omit
|
|
|
|
// this param's type string. For example, emit "i, j int" instead
|
|
|
|
// of "i int, j int".
|
|
|
|
if i == sig.Params().Len()-1 || !types.Identical(p.Type(), sig.Params().At(i+1).Type()) {
|
|
|
|
snip.WriteText(" ")
|
|
|
|
typeStr := types.TypeString(p.Type(), c.qf)
|
|
|
|
if sig.Variadic() && i == sig.Params().Len()-1 {
|
|
|
|
typeStr = strings.Replace(typeStr, "[]", "...", 1)
|
|
|
|
}
|
|
|
|
snip.WriteText(typeStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
snip.WriteText(")")
|
|
|
|
|
|
|
|
results := sig.Results()
|
|
|
|
if results.Len() > 0 {
|
|
|
|
snip.WriteText(" ")
|
|
|
|
}
|
|
|
|
|
|
|
|
resultsNeedParens := results.Len() > 1 ||
|
|
|
|
results.Len() == 1 && results.At(0).Name() != ""
|
|
|
|
|
|
|
|
if resultsNeedParens {
|
|
|
|
snip.WriteText("(")
|
|
|
|
}
|
|
|
|
for i := 0; i < results.Len(); i++ {
|
|
|
|
if i > 0 {
|
|
|
|
snip.WriteText(", ")
|
|
|
|
}
|
|
|
|
r := results.At(i)
|
|
|
|
if name := r.Name(); name != "" {
|
|
|
|
snip.WriteText(name + " ")
|
|
|
|
}
|
|
|
|
snip.WriteText(types.TypeString(r.Type(), c.qf))
|
|
|
|
}
|
|
|
|
if resultsNeedParens {
|
|
|
|
snip.WriteText(")")
|
|
|
|
}
|
|
|
|
|
|
|
|
snip.WriteText(" {")
|
|
|
|
snip.WriteFinalTabstop()
|
|
|
|
snip.WriteText("}")
|
|
|
|
|
|
|
|
c.items = append(c.items, CompletionItem{
|
|
|
|
Label: "func(...) {}",
|
|
|
|
Score: matchScore * literalCandidateScore,
|
2019-09-24 22:46:57 -06:00
|
|
|
Kind: protocol.VariableCompletion,
|
2019-09-05 13:04:13 -06:00
|
|
|
snippet: snip,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// abbreviateCamel abbreviates camel case identifiers into
|
|
|
|
// abbreviations. For example, "fooBar" is abbreviated "fb".
|
|
|
|
func abbreviateCamel(s string) string {
|
|
|
|
var (
|
|
|
|
b strings.Builder
|
|
|
|
useNextUpper bool
|
|
|
|
)
|
|
|
|
for i, r := range s {
|
|
|
|
if i == 0 {
|
|
|
|
b.WriteRune(unicode.ToLower(r))
|
|
|
|
}
|
|
|
|
|
|
|
|
if unicode.IsUpper(r) {
|
|
|
|
if useNextUpper {
|
|
|
|
b.WriteRune(unicode.ToLower(r))
|
|
|
|
useNextUpper = false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
useNextUpper = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return b.String()
|
|
|
|
}
|
|
|
|
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
// compositeLiteral adds a composite literal completion item for the given typeName.
|
2019-10-15 10:26:11 -06:00
|
|
|
func (c *completer) compositeLiteral(T types.Type, typeName string, matchScore float64, edits []protocol.TextEdit) {
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
snip := &snippet.Builder{}
|
|
|
|
snip.WriteText(typeName + "{")
|
|
|
|
// Don't put the tab stop inside the composite literal curlies "{}"
|
2019-11-15 23:28:29 -07:00
|
|
|
// for structs that have no accessible fields.
|
|
|
|
if strct, ok := T.(*types.Struct); !ok || fieldsAccessible(strct, c.pkg.GetTypes()) {
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
snip.WriteFinalTabstop()
|
|
|
|
}
|
|
|
|
snip.WriteText("}")
|
|
|
|
|
|
|
|
nonSnippet := typeName + "{}"
|
|
|
|
|
|
|
|
c.items = append(c.items, CompletionItem{
|
2019-10-15 10:26:11 -06:00
|
|
|
Label: nonSnippet,
|
|
|
|
InsertText: nonSnippet,
|
|
|
|
Score: matchScore * literalCandidateScore,
|
|
|
|
Kind: protocol.VariableCompletion,
|
|
|
|
AdditionalTextEdits: edits,
|
|
|
|
snippet: snip,
|
2019-09-16 20:07:16 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// basicLiteral adds a literal completion item for the given basic
|
|
|
|
// type name typeName.
|
2019-10-15 10:26:11 -06:00
|
|
|
func (c *completer) basicLiteral(T types.Type, typeName string, matchScore float64, edits []protocol.TextEdit) {
|
2019-09-16 20:07:16 -06:00
|
|
|
snip := &snippet.Builder{}
|
|
|
|
snip.WriteText(typeName + "(")
|
|
|
|
snip.WriteFinalTabstop()
|
|
|
|
snip.WriteText(")")
|
|
|
|
|
|
|
|
nonSnippet := typeName + "()"
|
|
|
|
|
|
|
|
c.items = append(c.items, CompletionItem{
|
2019-10-15 10:26:11 -06:00
|
|
|
Label: nonSnippet,
|
|
|
|
InsertText: nonSnippet,
|
|
|
|
Detail: T.String(),
|
|
|
|
Score: matchScore * literalCandidateScore,
|
|
|
|
Kind: protocol.VariableCompletion,
|
|
|
|
AdditionalTextEdits: edits,
|
|
|
|
snippet: snip,
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// makeCall adds a completion item for a "make()" call given a specific type.
|
2019-10-15 15:42:30 -06:00
|
|
|
func (c *completer) makeCall(typeName string, secondArg string, matchScore float64, edits []protocol.TextEdit) {
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
// Keep it simple and don't add any placeholders for optional "make()" arguments.
|
|
|
|
|
|
|
|
snip := &snippet.Builder{}
|
|
|
|
snip.WriteText("make(" + typeName)
|
|
|
|
if secondArg != "" {
|
|
|
|
snip.WriteText(", ")
|
|
|
|
snip.WritePlaceholder(func(b *snippet.Builder) {
|
2019-12-29 00:22:12 -07:00
|
|
|
if c.opts.placeholders {
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
b.WriteText(secondArg)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
snip.WriteText(")")
|
|
|
|
|
|
|
|
var nonSnippet strings.Builder
|
|
|
|
nonSnippet.WriteString("make(" + typeName)
|
|
|
|
if secondArg != "" {
|
|
|
|
nonSnippet.WriteString(", ")
|
|
|
|
nonSnippet.WriteString(secondArg)
|
|
|
|
}
|
|
|
|
nonSnippet.WriteByte(')')
|
|
|
|
|
|
|
|
c.items = append(c.items, CompletionItem{
|
2019-10-15 15:42:30 -06:00
|
|
|
Label: nonSnippet.String(),
|
|
|
|
InsertText: nonSnippet.String(),
|
|
|
|
Score: matchScore * literalCandidateScore,
|
|
|
|
Kind: protocol.FunctionCompletion,
|
|
|
|
AdditionalTextEdits: edits,
|
|
|
|
snippet: snip,
|
internal/lsp: add literal completion candidates
Add support for literal completion candidates such as "[]int{}" or
"make([]int, 0)". We support both named and unnamed types. I used the
existing type matching logic, so, for example, if the expected type is
an interface, we will suggest literal candidates that implement the
interface.
The literal candidates have a lower score than normal matching
candidates, so they shouldn't be disruptive in cases where you don't
want a literal candidate.
This commit adds support for slice, array, struct, map, and channel
literal candidates since they are pretty similar. Functions will be
supported in a subsequent commit.
I also added support for setting a snippet's final tab stop. This is
useful if you want the cursor to end up somewhere other than the
character after the snippet.
Change-Id: Id3b74260fff4d61703989b422267021b00cec005
Reviewed-on: https://go-review.googlesource.com/c/tools/+/193698
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-09-04 17:12:37 -06:00
|
|
|
})
|
|
|
|
}
|