Skip to content

Commit 7a79a45

Browse files
author
Andy
authored
JSX closing tag completion: Include '>' if not already present (#25551)
* JSX closing tag completion: Include '>' if not already present * Expand comment
1 parent 527093c commit 7a79a45

7 files changed

+19
-25
lines changed

src/services/completions.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,22 @@ namespace ts.Completions {
111111
function completionInfoFromData(sourceFile: SourceFile, typeChecker: TypeChecker, compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, preferences: UserPreferences): CompletionInfo | undefined {
112112
const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, literals, symbolToOriginInfoMap, recommendedCompletion, isJsxInitializer } = completionData;
113113

114-
if (sourceFile.languageVariant === LanguageVariant.JSX && location && location.parent && isJsxClosingElement(location.parent)) {
114+
if (location && location.parent && isJsxClosingElement(location.parent)) {
115115
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
116116
// instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
117117
// For example:
118-
// var x = <div> </ /*1*/>
119-
// The completion list at "1" will contain "div" with type any
118+
// var x = <div> </ /*1*/
119+
// The completion list at "1" will contain "div>" with type any
120+
// And at `<div> </ /*1*/ >` (with a closing `>`), the completion list will contain "div".
120121
const tagName = location.parent.parent.openingElement.tagName;
121-
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false,
122-
entries: [{
123-
name: tagName.getFullText(),
124-
kind: ScriptElementKind.classElement,
125-
kindModifiers: undefined,
126-
sortText: "0",
127-
}]};
122+
const hasClosingAngleBracket = !!findChildOfKind(location.parent, SyntaxKind.GreaterThanToken, sourceFile);
123+
const entry: CompletionEntry = {
124+
name: tagName.getFullText(sourceFile) + (hasClosingAngleBracket ? "" : ">"),
125+
kind: ScriptElementKind.classElement,
126+
kindModifiers: undefined,
127+
sortText: "0",
128+
};
129+
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, entries: [entry] };
128130
}
129131

130132
const entries: CompletionEntry[] = [];

tests/cases/fourslash/completionsTriggerCharacter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ verify.completions(
4242

4343
{ marker: "openTag", includes: "div", triggerCharacter: "<" },
4444
{ marker: "lessThan", exact: undefined, triggerCharacter: "<" },
45-
{ marker: "closeTag", exact: "div", triggerCharacter: "/" },
45+
{ marker: "closeTag", exact: "div>", triggerCharacter: "/" },
4646
{ marker: "path", exact: "importMe", triggerCharacter: "/", isNewIdentifierLocation: true },
4747
{ marker: "divide", exact: undefined, triggerCharacter: "/" },
4848
);

tests/cases/fourslash/jsxQualifiedTagCompletion.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
//// export var Foo: any = null;
77
//// }
88
//// const j = <NS.Foo>Hello!/**/
9-
////
9+
////
1010

1111
goTo.marker();
1212
edit.insert("</");
13-
verify.completionListContains("NS.Foo");
14-
verify.not.completionListContains("Foo");
15-
verify.completionListCount(1);
13+
verify.completions({ exact: "NS.Foo>" });

tests/cases/fourslash/tsxCompletion10.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,4 @@
99
//// }
1010
//// var x1 = <div><//**/
1111

12-
goTo.marker();
13-
verify.completionListCount(1);
14-
verify.completionListContains('div');
12+
verify.completions({ marker: "", exact: "div>" });

tests/cases/fourslash/tsxCompletionOnClosingTag1.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,4 @@
99
//// }
1010
//// var x1 = <div><//**/
1111

12-
goTo.marker();
13-
verify.completionListCount(1);
14-
verify.completionListContains('div');
12+
verify.completions({ marker: "", exact: "div>" });

tests/cases/fourslash/tsxCompletionOnClosingTagWithoutJSX1.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@
33
//@Filename: file.tsx
44
//// var x1 = <div><//**/
55

6-
goTo.marker();
7-
verify.completionListCount(1);
8-
verify.completionListContains('div');
6+
verify.completions({ marker: "", exact: "div>" });

tests/cases/fourslash/tsxCompletionOnClosingTagWithoutJSX2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
//// <h1> Hello world </ /*2*/>
66
//// </ /*1*/>
77

8-
verify.completions({ marker: "1", exact: ["div"] }, { marker: "2", exact: ["h1"] });
8+
verify.completions({ marker: "1", exact: "div" }, { marker: "2", exact: "h1" });

0 commit comments

Comments
 (0)