Skip to content

Commit 1e14d99

Browse files
committed
internal/lsp: add inlay hints for composite literal types
Add inlay hints for composite literal types. This will show type information for composite literals with no explicit types. Example: <struct {in, want string}>{"hello", "goodbye"} For golang/go#52343 Change-Id: Ia1f03b82669387c864353b8033940759fa1128e7 Reviewed-on: https://go-review.googlesource.com/c/tools/+/411905 gopls-CI: kokoro <[email protected]> Run-TryBot: Suzy Mueller <[email protected]> Reviewed-by: Jamal Carvalho <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent e987015 commit 1e14d99

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

internal/lsp/source/inlay_hint.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func InlayHint(ctx context.Context, snapshot Snapshot, fh FileHandle, _ protocol
4747
case *ast.GenDecl:
4848
hints = append(hints, constantValues(n, tmap, info)...)
4949
case *ast.CompositeLit:
50-
hints = append(hints, compositeLiterals(n, tmap, info)...)
50+
hints = append(hints, compositeLiterals(n, tmap, info, &q)...)
5151
}
5252
return true
5353
})
@@ -181,17 +181,35 @@ func constantValues(node *ast.GenDecl, tmap *lsppos.TokenMapper, info *types.Inf
181181
return hints
182182
}
183183

184-
func compositeLiterals(node *ast.CompositeLit, tmap *lsppos.TokenMapper, info *types.Info) []protocol.InlayHint {
184+
func compositeLiterals(node *ast.CompositeLit, tmap *lsppos.TokenMapper, info *types.Info, q *types.Qualifier) []protocol.InlayHint {
185185
typ := info.TypeOf(node)
186186
if typ == nil {
187187
return nil
188188
}
189+
190+
prefix := ""
191+
if t, ok := typ.(*types.Pointer); ok {
192+
typ = t.Elem()
193+
prefix = "&"
194+
}
195+
189196
strct, ok := typ.Underlying().(*types.Struct)
190197
if !ok {
191198
return nil
192199
}
193200

194201
var hints []protocol.InlayHint
202+
if node.Type == nil {
203+
// The type for this struct is implicit, add an inlay hint.
204+
if start, ok := tmap.Position(node.Lbrace); ok {
205+
hints = append(hints, protocol.InlayHint{
206+
Position: &start,
207+
Label: buildLabel(fmt.Sprintf("%s%s", prefix, types.TypeString(typ, *q))),
208+
Kind: protocol.Type,
209+
})
210+
}
211+
}
212+
195213
for i, v := range node.Elts {
196214
if _, ok := v.(*ast.KeyValueExpr); !ok {
197215
start, ok := tmap.Position(v.Pos())
@@ -216,7 +234,7 @@ func buildLabel(s string) []protocol.InlayHintLabelPart {
216234
label := protocol.InlayHintLabelPart{
217235
Value: s,
218236
}
219-
if len(s) > maxLabelLength {
237+
if len(s) > maxLabelLength+len("...") {
220238
label.Value = s[:maxLabelLength] + "..."
221239
label.Tooltip = s
222240
}

internal/lsp/testdata/inlay_hint/composite_literals.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,19 @@ func fieldNames() {
66
for _, c := range []struct {
77
in, want string
88
}{
9-
{"Hello, world", "dlrow ,olleH"},
9+
struct{ in, want string }{"Hello, world", "dlrow ,olleH"},
10+
{"Hello, 世界", "界世 ,olleH"},
11+
{"", ""},
12+
} {
13+
fmt.Println(c.in == c.want)
14+
}
15+
}
16+
17+
func fieldNamesPointers() {
18+
for _, c := range []*struct {
19+
in, want string
20+
}{
21+
&struct{ in, want string }{"Hello, world", "dlrow ,olleH"},
1022
{"Hello, 世界", "界世 ,olleH"},
1123
{"", ""},
1224
} {

internal/lsp/testdata/inlay_hint/composite_literals.go.golden

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,24 @@ package inlayHint //@inlayHint("package")
44
import "fmt"
55

66
func fieldNames() {
7-
for _< int>, c< struct{in string; want strin...> := range []struct {
7+
for _< int>, c< struct{in string; want string}> := range []struct {
88
in, want string
99
}{
10-
{<in: >"Hello, world", <want: >"dlrow ,olleH"},
11-
{<in: >"Hello, 世界", <want: >"界世 ,olleH"},
12-
{<in: >"", <want: >""},
10+
struct{ in, want string }{<in: >"Hello, world", <want: >"dlrow ,olleH"},
11+
<struct{in string; want string}>{<in: >"Hello, 世界", <want: >"界世 ,olleH"},
12+
<struct{in string; want string}>{<in: >"", <want: >""},
13+
} {
14+
fmt.Println(<a...: >c.in == c.want)
15+
}
16+
}
17+
18+
func fieldNamesPointers() {
19+
for _< int>, c< *struct{in string; want string}> := range []*struct {
20+
in, want string
21+
}{
22+
&struct{ in, want string }{<in: >"Hello, world", <want: >"dlrow ,olleH"},
23+
<&struct{in string; want string}>{<in: >"Hello, 世界", <want: >"界世 ,olleH"},
24+
<&struct{in string; want string}>{<in: >"", <want: >""},
1325
} {
1426
fmt.Println(<a...: >c.in == c.want)
1527
}

0 commit comments

Comments
 (0)