Skip to content

Commit 8cf347c

Browse files
committed
Merge pull request #6006 from Microsoft/fix5953_crashJSX
Fix crash inside JSX Closing tag
2 parents 5313928 + 356def9 commit 8cf347c

23 files changed

+229
-6
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ namespace ts {
6565
getTypeCount: () => typeCount,
6666
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
6767
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
68+
isUnknownSymbol: symbol => symbol === unknownSymbol,
6869
getDiagnostics,
6970
getGlobalDiagnostics,
7071

@@ -8112,6 +8113,7 @@ namespace ts {
81128113
if (compilerOptions.noImplicitAny) {
81138114
error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements);
81148115
}
8116+
return unknownSymbol;
81158117
}
81168118
}
81178119

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,6 +1738,7 @@ namespace ts {
17381738
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
17391739
isUndefinedSymbol(symbol: Symbol): boolean;
17401740
isArgumentsSymbol(symbol: Symbol): boolean;
1741+
isUnknownSymbol(symbol: Symbol): boolean;
17411742

17421743
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
17431744
isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;

src/services/services.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3100,6 +3100,7 @@ namespace ts {
31003100
}
31013101
else if (kind === SyntaxKind.SlashToken && contextToken.parent.kind === SyntaxKind.JsxClosingElement) {
31023102
isStartingCloseTag = true;
3103+
location = contextToken;
31033104
}
31043105
}
31053106
}
@@ -3125,8 +3126,11 @@ namespace ts {
31253126
}
31263127
else if (isStartingCloseTag) {
31273128
const tagName = (<JsxElement>contextToken.parent.parent).openingElement.tagName;
3128-
symbols = [typeChecker.getSymbolAtLocation(tagName)];
3129+
const tagSymbol = typeChecker.getSymbolAtLocation(tagName);
31293130

3131+
if (!typeChecker.isUnknownSymbol(tagSymbol)) {
3132+
symbols = [tagSymbol];
3133+
}
31303134
isMemberCompletion = true;
31313135
isNewIdentifierLocation = false;
31323136
}
@@ -3832,7 +3836,23 @@ namespace ts {
38323836
}
38333837
else {
38343838
if (!symbols || symbols.length === 0) {
3835-
return undefined;
3839+
if (sourceFile.languageVariant === LanguageVariant.JSX &&
3840+
location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) {
3841+
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
3842+
// instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
3843+
// For example:
3844+
// var x = <div> </ /*1*/> completion list at "1" will contain "div" with type any
3845+
const tagName = (<JsxElement>location.parent.parent).openingElement.tagName;
3846+
entries.push({
3847+
name: (<Identifier>tagName).text,
3848+
kind: undefined,
3849+
kindModifiers: undefined,
3850+
sortText: "0",
3851+
});
3852+
}
3853+
else {
3854+
return undefined;
3855+
}
38363856
}
38373857

38383858
getCompletionEntriesFromSymbols(symbols, entries);
@@ -4440,7 +4460,7 @@ namespace ts {
44404460
const typeChecker = program.getTypeChecker();
44414461
const symbol = typeChecker.getSymbolAtLocation(node);
44424462

4443-
if (!symbol) {
4463+
if (!symbol || typeChecker.isUnknownSymbol(symbol)) {
44444464
// Try getting just type at this position and show
44454465
switch (node.kind) {
44464466
case SyntaxKind.Identifier:

tests/baselines/reference/jsxEmitAttributeWithPreserve.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ declare var React: any;
44
>React : Symbol(React, Decl(jsxEmitAttributeWithPreserve.tsx, 1, 11))
55

66
<foo data/>
7+
>foo : Symbol(unknown)
78
>data : Symbol(unknown)
89

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,68 @@
11
=== tests/cases/compiler/jsxHash.tsx ===
22
var t02 = <a>{0}#</a>;
33
>t02 : Symbol(t02, Decl(jsxHash.tsx, 0, 3))
4+
>a : Symbol(unknown)
5+
>a : Symbol(unknown)
46

57
var t03 = <a>#{0}</a>;
68
>t03 : Symbol(t03, Decl(jsxHash.tsx, 1, 3))
9+
>a : Symbol(unknown)
10+
>a : Symbol(unknown)
711

812
var t04 = <a>#{0}#</a>;
913
>t04 : Symbol(t04, Decl(jsxHash.tsx, 2, 3))
14+
>a : Symbol(unknown)
15+
>a : Symbol(unknown)
1016

1117
var t05 = <a>#<i></i></a>;
1218
>t05 : Symbol(t05, Decl(jsxHash.tsx, 3, 3))
19+
>a : Symbol(unknown)
20+
>i : Symbol(unknown)
21+
>i : Symbol(unknown)
22+
>a : Symbol(unknown)
1323

1424
var t06 = <a>#<i></i></a>;
1525
>t06 : Symbol(t06, Decl(jsxHash.tsx, 4, 3))
26+
>a : Symbol(unknown)
27+
>i : Symbol(unknown)
28+
>i : Symbol(unknown)
29+
>a : Symbol(unknown)
1630

1731
var t07 = <a>#<i>#</i></a>;
1832
>t07 : Symbol(t07, Decl(jsxHash.tsx, 5, 3))
33+
>a : Symbol(unknown)
34+
>i : Symbol(unknown)
35+
>i : Symbol(unknown)
36+
>a : Symbol(unknown)
1937

2038
var t08 = <a><i></i>#</a>;
2139
>t08 : Symbol(t08, Decl(jsxHash.tsx, 6, 3))
40+
>a : Symbol(unknown)
41+
>i : Symbol(unknown)
42+
>i : Symbol(unknown)
43+
>a : Symbol(unknown)
2244

2345
var t09 = <a>#<i></i>#</a>;
2446
>t09 : Symbol(t09, Decl(jsxHash.tsx, 7, 3))
47+
>a : Symbol(unknown)
48+
>i : Symbol(unknown)
49+
>i : Symbol(unknown)
50+
>a : Symbol(unknown)
2551

2652
var t10 = <a><i/>#</a>;
2753
>t10 : Symbol(t10, Decl(jsxHash.tsx, 8, 3))
54+
>a : Symbol(unknown)
55+
>i : Symbol(unknown)
56+
>a : Symbol(unknown)
2857

2958
var t11 = <a>#<i/></a>;
3059
>t11 : Symbol(t11, Decl(jsxHash.tsx, 9, 3))
60+
>a : Symbol(unknown)
61+
>i : Symbol(unknown)
62+
>a : Symbol(unknown)
3163

3264
var t12 = <a>#</a>;
3365
>t12 : Symbol(t12, Decl(jsxHash.tsx, 10, 3))
66+
>a : Symbol(unknown)
67+
>a : Symbol(unknown)
3468

tests/baselines/reference/jsxImportInAttribute.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ let x = Test; // emit test_1.default
88
>Test : Symbol(Test, Decl(consumer.tsx, 1, 6))
99

1010
<anything attr={Test} />; // ?
11+
>anything : Symbol(unknown)
1112
>attr : Symbol(unknown)
1213
>Test : Symbol(Test, Decl(consumer.tsx, 1, 6))
1314

tests/baselines/reference/jsxReactTestSuite.symbols

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,36 @@ declare var hasOwnProperty:any;
3737
>hasOwnProperty : Symbol(hasOwnProperty, Decl(jsxReactTestSuite.tsx, 12, 11))
3838

3939
<div>text</div>;
40+
>div : Symbol(unknown)
41+
>div : Symbol(unknown)
4042

4143
<div>
44+
>div : Symbol(unknown)
45+
4246
{this.props.children}
4347
</div>;
48+
>div : Symbol(unknown)
4449

4550
<div>
51+
>div : Symbol(unknown)
52+
4653
<div><br /></div>
54+
>div : Symbol(unknown)
55+
>br : Symbol(unknown)
56+
>div : Symbol(unknown)
57+
4758
<Component>{foo}<br />{bar}</Component>
4859
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
4960
>foo : Symbol(foo, Decl(jsxReactTestSuite.tsx, 7, 11))
61+
>br : Symbol(unknown)
5062
>bar : Symbol(bar, Decl(jsxReactTestSuite.tsx, 8, 11))
5163
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
5264

5365
<br />
66+
>br : Symbol(unknown)
67+
5468
</div>;
69+
>div : Symbol(unknown)
5570

5671

5772
<Composite>
@@ -74,6 +89,8 @@ var x =
7489
>x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3))
7590

7691
<div
92+
>div : Symbol(unknown)
93+
7794
attr1={
7895
>attr1 : Symbol(unknown)
7996

@@ -97,41 +114,64 @@ var x =
97114
>attr4 : Symbol(unknown)
98115

99116
</div>;
117+
>div : Symbol(unknown)
100118

101119
(
102120
<div>
121+
>div : Symbol(unknown)
122+
103123
{/* A comment at the beginning */}
104124
{/* A second comment at the beginning */}
105125
<span>
126+
>span : Symbol(unknown)
127+
106128
{/* A nested comment */}
107129
</span>
130+
>span : Symbol(unknown)
131+
108132
{/* A sandwiched comment */}
109133
<br />
134+
>br : Symbol(unknown)
135+
110136
{/* A comment at the end */}
111137
{/* A second comment at the end */}
112138
</div>
139+
>div : Symbol(unknown)
140+
113141
);
114142

115143
(
116144
<div
145+
>div : Symbol(unknown)
146+
117147
/* a multi-line
118148
comment */
119149
attr1="foo">
120150
>attr1 : Symbol(unknown)
121151

122152
<span // a double-slash comment
153+
>span : Symbol(unknown)
154+
123155
attr2="bar"
124156
>attr2 : Symbol(unknown)
125157

126158
/>
127159
</div>
160+
>div : Symbol(unknown)
161+
128162
);
129163

130164
<div>&nbsp;</div>;
165+
>div : Symbol(unknown)
166+
>div : Symbol(unknown)
131167

132168
<div>&nbsp; </div>;
169+
>div : Symbol(unknown)
170+
>div : Symbol(unknown)
133171

134172
<hasOwnProperty>testing</hasOwnProperty>;
173+
>hasOwnProperty : Symbol(unknown)
174+
>hasOwnProperty : Symbol(unknown)
135175

136176
<Component constructor="foo" />;
137177
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
@@ -158,13 +198,15 @@ var x =
158198
>sound : Symbol(unknown)
159199

160200
<font-face />;
201+
>font-face : Symbol(unknown)
161202

162203
<Component x={y} />;
163204
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
164205
>x : Symbol(unknown)
165206
>y : Symbol(y, Decl(jsxReactTestSuite.tsx, 9, 11))
166207

167208
<x-component />;
209+
>x-component : Symbol(unknown)
168210

169211
<Component {...x} />;
170212
>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))

tests/baselines/reference/keywordInJsxIdentifier.symbols

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ declare var React: any;
44
>React : Symbol(React, Decl(keywordInJsxIdentifier.tsx, 1, 11))
55

66
<foo class-id/>;
7+
>foo : Symbol(unknown)
78
>class-id : Symbol(unknown)
89

910
<foo class/>;
11+
>foo : Symbol(unknown)
1012
>class : Symbol(unknown)
1113

1214
<foo class-id="1"/>;
15+
>foo : Symbol(unknown)
1316
>class-id : Symbol(unknown)
1417

1518
<foo class="1"/>;
19+
>foo : Symbol(unknown)
1620
>class : Symbol(unknown)
1721

tests/baselines/reference/reactNamespaceImportPresevation.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ declare var foo: any;
1616
>foo : Symbol(foo, Decl(test.tsx, 1, 11))
1717

1818
<foo data/>;
19+
>foo : Symbol(unknown)
1920
>data : Symbol(unknown)
2021

tests/baselines/reference/reactNamespaceJSXEmit.symbols

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ declare var x: any;
1313
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))
1414

1515
<foo data/>;
16+
>foo : Symbol(unknown)
1617
>data : Symbol(unknown)
1718

1819
<Bar x={x} />;
@@ -21,6 +22,8 @@ declare var x: any;
2122
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))
2223

2324
<x-component />;
25+
>x-component : Symbol(unknown)
26+
2427
<Bar {...x} />;
2528
>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11))
2629
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))

tests/baselines/reference/tsxElementResolution13.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ var obj1: Obj1;
2222
>Obj1 : Symbol(Obj1, Decl(file.tsx, 3, 1))
2323

2424
<obj1 x={10} />; // Error
25+
>obj1 : Symbol(unknown)
2526
>x : Symbol(unknown)
2627

tests/baselines/reference/tsxElementResolution14.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ var obj1: Obj1;
1717
>Obj1 : Symbol(Obj1, Decl(file.tsx, 2, 1))
1818

1919
<obj1 x={10} />; // OK
20+
>obj1 : Symbol(unknown)
2021
>x : Symbol(unknown)
2122

tests/baselines/reference/tsxElementResolution5.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ declare module JSX {
88

99
// OK, but implicit any
1010
<div n='x' />;
11+
>div : Symbol(unknown)
1112
>n : Symbol(unknown)
1213

tests/baselines/reference/tsxExternalModuleEmit1.symbols

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ export class Button extends React.Component<any, any> {
4444
>render : Symbol(render, Decl(button.tsx, 2, 55))
4545

4646
return <button>Some button</button>;
47+
>button : Symbol(unknown)
48+
>button : Symbol(unknown)
4749
}
4850

4951
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
=== tests/cases/conformance/jsx/tsxNoJsx.tsx ===
22

3-
No type information for this code.<nope />;
4-
No type information for this code.
5-
No type information for this code.
3+
<nope />;
4+
>nope : Symbol(unknown)
5+

0 commit comments

Comments
 (0)