Skip to content

Commit f9ca2a1

Browse files
authored
Fix completionItem/resolve keyword and hover crashes (#1403)
1 parent 6c17bea commit f9ca2a1

File tree

7 files changed

+105
-8
lines changed

7 files changed

+105
-8
lines changed

internal/fourslash/_scripts/failingTests.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ TestCompletionListAfterStringLiteral1
7373
TestCompletionListAndMemberListOnCommentedDot
7474
TestCompletionListAndMemberListOnCommentedLine
7575
TestCompletionListAndMemberListOnCommentedWhiteSpace
76-
TestCompletionListAtEndOfWordInArrowFunction03
7776
TestCompletionListAtInvalidLocations
7877
TestCompletionListBuilderLocations_VariableDeclarations
7978
TestCompletionListCladule

internal/fourslash/fourslash.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ func (f *FourslashTest) verifyCompletionsItems(t *testing.T, prefix string, actu
660660
t.Fatalf("%sLabel '%s' not found in actual items. Actual items: %s", prefix, item.Label, cmp.Diff(actual, nil))
661661
}
662662
delete(nameToActualItem, item.Label)
663-
f.verifyCompletionItem(t, prefix+"Includes completion item mismatch for label "+item.Label, actualItem, item)
663+
f.verifyCompletionItem(t, prefix+"Includes completion item mismatch for label "+item.Label+": ", actualItem, item)
664664
default:
665665
t.Fatalf("%sExpected completion item to be a string or *lsproto.CompletionItem, got %T", prefix, item)
666666
}
@@ -684,7 +684,7 @@ func (f *FourslashTest) verifyCompletionsItems(t *testing.T, prefix string, actu
684684
if !ok {
685685
t.Fatalf("%sLabel '%s' not found in actual items. Actual items: %s", prefix, item.Label, cmp.Diff(actual, nil))
686686
}
687-
f.verifyCompletionItem(t, prefix+"Includes completion item mismatch for label "+item.Label, actualItem, item)
687+
f.verifyCompletionItem(t, prefix+"Includes completion item mismatch for label "+item.Label+": ", actualItem, item)
688688
default:
689689
t.Fatalf("%sExpected completion item to be a string or *lsproto.CompletionItem, got %T", prefix, item)
690690
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package fourslash_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/microsoft/typescript-go/internal/fourslash"
7+
"github.com/microsoft/typescript-go/internal/ls"
8+
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
9+
"github.com/microsoft/typescript-go/internal/testutil"
10+
)
11+
12+
func TestCompletionDetailSignature(t *testing.T) {
13+
t.Parallel()
14+
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
15+
const content = `
16+
17+
/*a*/
18+
19+
function foo(x: string): string;
20+
function foo(x: number): number;
21+
function foo(x: any): any {
22+
return x;
23+
}`
24+
f := fourslash.NewFourslash(t, nil /*capabilities*/, content)
25+
f.VerifyCompletions(t, "a", &fourslash.CompletionsExpectedList{
26+
IsIncomplete: false,
27+
ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{
28+
CommitCharacters: &defaultCommitCharacters,
29+
},
30+
Items: &fourslash.CompletionsExpectedItems{
31+
Includes: []fourslash.CompletionsExpectedItem{
32+
&lsproto.CompletionItem{
33+
Label: "foo",
34+
Kind: ptrTo(lsproto.CompletionItemKindFunction),
35+
SortText: ptrTo(string(ls.SortTextLocationPriority)),
36+
Detail: ptrTo("function foo(x: string): string\nfunction foo(x: number): number"),
37+
},
38+
},
39+
},
40+
})
41+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package fourslash_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/microsoft/typescript-go/internal/fourslash"
7+
"github.com/microsoft/typescript-go/internal/ls"
8+
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
9+
"github.com/microsoft/typescript-go/internal/testutil"
10+
)
11+
12+
func TestCompletionResolveKeyword(t *testing.T) {
13+
t.Parallel()
14+
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
15+
const content = `class C {
16+
/*a*/
17+
}`
18+
f := fourslash.NewFourslash(t, nil /*capabilities*/, content)
19+
f.VerifyCompletions(t, "a", &fourslash.CompletionsExpectedList{
20+
IsIncomplete: false,
21+
ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{
22+
CommitCharacters: &[]string{},
23+
},
24+
Items: &fourslash.CompletionsExpectedItems{
25+
Includes: []fourslash.CompletionsExpectedItem{
26+
&lsproto.CompletionItem{
27+
Label: "abstract",
28+
Kind: ptrTo(lsproto.CompletionItemKindKeyword),
29+
SortText: ptrTo(string(ls.SortTextGlobalsOrKeywords)),
30+
Detail: ptrTo("abstract"),
31+
},
32+
},
33+
},
34+
})
35+
}

internal/fourslash/tests/gen/completionListAtEndOfWordInArrowFunction03_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111

1212
func TestCompletionListAtEndOfWordInArrowFunction03(t *testing.T) {
1313
t.Parallel()
14-
t.Skip()
14+
1515
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
1616
const content = `(d, defaultIsAnInvalidParameterName) => default/*1*/`
1717
f := fourslash.NewFourslash(t, nil /*capabilities*/, content)

internal/ls/completions.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
func (l *LanguageService) ProvideCompletion(
2929
ctx context.Context,
3030
documentURI lsproto.DocumentUri,
31-
position lsproto.Position,
31+
LSPPosition lsproto.Position,
3232
context *lsproto.CompletionContext,
3333
clientOptions *lsproto.CompletionClientCapabilities,
3434
preferences *UserPreferences,
@@ -38,15 +38,34 @@ func (l *LanguageService) ProvideCompletion(
3838
if context != nil {
3939
triggerCharacter = context.TriggerCharacter
4040
}
41-
return l.getCompletionsAtPosition(
41+
position := int(l.converters.LineAndCharacterToPosition(file, LSPPosition))
42+
completionList := l.getCompletionsAtPosition(
4243
ctx,
4344
program,
4445
file,
45-
int(l.converters.LineAndCharacterToPosition(file, position)),
46+
position,
4647
triggerCharacter,
4748
preferences,
4849
clientOptions,
49-
), nil
50+
)
51+
return ensureItemData(file.FileName(), position, completionList), nil
52+
}
53+
54+
func ensureItemData(fileName string, pos int, list *lsproto.CompletionList) *lsproto.CompletionList {
55+
if list == nil {
56+
return nil
57+
}
58+
for _, item := range list.Items {
59+
if item.Data == nil {
60+
var data any = &itemData{
61+
FileName: fileName,
62+
Position: pos,
63+
Name: item.Label,
64+
}
65+
item.Data = &data
66+
}
67+
}
68+
return list
5069
}
5170

5271
// *completionDataData | *completionDataKeyword

internal/ls/hover.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ func getSignaturesAtLocation(c *checker.Checker, symbol *ast.Symbol, kind checke
277277
}
278278

279279
func getCallOrNewExpression(node *ast.Node) *ast.Node {
280+
if ast.IsSourceFile(node) {
281+
return nil
282+
}
280283
if ast.IsPropertyAccessExpression(node.Parent) && node.Parent.Name() == node {
281284
node = node.Parent
282285
}

0 commit comments

Comments
 (0)