Skip to content

Commit 9a256a1

Browse files
authored
Adjust scanning of keywordy jsx namespace names, add grammar error for jsx dotted names containing namespace names (microsoft#43104)
1 parent 865cec3 commit 9a256a1

9 files changed

+159
-1
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40728,6 +40728,7 @@ namespace ts {
4072840728
}
4072940729

4073040730
function checkGrammarJsxElement(node: JsxOpeningLikeElement) {
40731+
checkGrammarJsxName(node.tagName);
4073140732
checkGrammarTypeArguments(node, node.typeArguments);
4073240733
const seen = new Map<__String, boolean>();
4073340734

@@ -40750,6 +40751,29 @@ namespace ts {
4075040751
}
4075140752
}
4075240753

40754+
function checkGrammarJsxName(node: JsxTagNameExpression) {
40755+
if (isPropertyAccessExpression(node)) {
40756+
let propName: JsxTagNameExpression = node;
40757+
do {
40758+
const check = checkGrammarJsxNestedIdentifier(propName.name);
40759+
if (check) {
40760+
return check;
40761+
}
40762+
propName = propName.expression;
40763+
} while (isPropertyAccessExpression(propName));
40764+
const check = checkGrammarJsxNestedIdentifier(propName);
40765+
if (check) {
40766+
return check;
40767+
}
40768+
}
40769+
40770+
function checkGrammarJsxNestedIdentifier(name: MemberName | ThisExpression) {
40771+
if (isIdentifier(name) && idText(name).indexOf(":") !== -1) {
40772+
return grammarErrorOnNode(name, Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names);
40773+
}
40774+
}
40775+
}
40776+
4075340777
function checkGrammarJsxExpression(node: JsxExpression) {
4075440778
if (node.expression && isCommaSequence(node.expression)) {
4075540779
return grammarErrorOnNode(node.expression, Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array);

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,6 +2674,10 @@
26742674
"category": "Error",
26752675
"code": 2632
26762676
},
2677+
"JSX property access expressions cannot include JSX namespace names": {
2678+
"category": "Error",
2679+
"code": 2633
2680+
},
26772681

26782682
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
26792683
"category": "Error",

src/compiler/scanner.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,7 @@ namespace ts {
23352335
tokenValue += ":";
23362336
pos++;
23372337
namespaceSeparator = true;
2338+
token = SyntaxKind.Identifier; // swap from keyword kind to identifier kind
23382339
continue;
23392340
}
23402341
const oldPos = pos;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,2): error TS2304: Cannot find name 'b:c'.
2+
tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,2): error TS2633: JSX property access expressions cannot include JSX namespace names
3+
tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,10): error TS2304: Cannot find name 'b:c'.
4+
5+
6+
==== tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx (3 errors) ====
7+
declare namespace JSX {
8+
interface IntrinsicElements {
9+
'this:b': any;
10+
'b:c': {
11+
x: any
12+
};
13+
'a:b': any;
14+
}
15+
}
16+
17+
<a:b></a:b>;
18+
<b:c.x></b:c.x>;
19+
~~~
20+
!!! error TS2304: Cannot find name 'b:c'.
21+
~~~
22+
!!! error TS2633: JSX property access expressions cannot include JSX namespace names
23+
~~~
24+
!!! error TS2304: Cannot find name 'b:c'.
25+
<this:b></this:b>;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//// [checkJsxNamespaceNamesQuestionableForms.tsx]
2+
declare namespace JSX {
3+
interface IntrinsicElements {
4+
'this:b': any;
5+
'b:c': {
6+
x: any
7+
};
8+
'a:b': any;
9+
}
10+
}
11+
12+
<a:b></a:b>;
13+
<b:c.x></b:c.x>;
14+
<this:b></this:b>;
15+
16+
//// [checkJsxNamespaceNamesQuestionableForms.jsx]
17+
<a:b></a:b>;
18+
<b:c.x></b:c.x>;
19+
<this:b></this:b>;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
=== tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx ===
2+
declare namespace JSX {
3+
>JSX : Symbol(JSX, Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 0, 0))
4+
5+
interface IntrinsicElements {
6+
>IntrinsicElements : Symbol(IntrinsicElements, Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 0, 23))
7+
8+
'this:b': any;
9+
>'this:b' : Symbol(IntrinsicElements['this:b'], Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 1, 33))
10+
11+
'b:c': {
12+
>'b:c' : Symbol(IntrinsicElements['b:c'], Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 2, 22))
13+
14+
x: any
15+
>x : Symbol(x, Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 3, 16))
16+
17+
};
18+
'a:b': any;
19+
>'a:b' : Symbol(IntrinsicElements['a:b'], Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 5, 10))
20+
}
21+
}
22+
23+
<a:b></a:b>;
24+
>a:b : Symbol(JSX.IntrinsicElements['a:b'], Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 5, 10))
25+
>a:b : Symbol(JSX.IntrinsicElements['a:b'], Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 5, 10))
26+
27+
<b:c.x></b:c.x>;
28+
<this:b></this:b>;
29+
>this:b : Symbol(JSX.IntrinsicElements['this:b'], Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 1, 33))
30+
>this:b : Symbol(JSX.IntrinsicElements['this:b'], Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 1, 33))
31+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
=== tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx ===
2+
declare namespace JSX {
3+
interface IntrinsicElements {
4+
'this:b': any;
5+
>'this:b' : any
6+
7+
'b:c': {
8+
>'b:c' : { x: any; }
9+
10+
x: any
11+
>x : any
12+
13+
};
14+
'a:b': any;
15+
>'a:b' : any
16+
}
17+
}
18+
19+
<a:b></a:b>;
20+
><a:b></a:b> : any
21+
>a:b : any
22+
>a:b : any
23+
24+
<b:c.x></b:c.x>;
25+
><b:c.x></b:c.x> : any
26+
>b:c.x : any
27+
>b:c : any
28+
>x : any
29+
>b:c.x : any
30+
>b:c : any
31+
>x : any
32+
33+
<this:b></this:b>;
34+
><this:b></this:b> : any
35+
>this:b : any
36+
>this:b : any
37+

tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ tests/cases/conformance/jsx/6.tsx(1,4): error TS17002: Expected corresponding JS
7777
tests/cases/conformance/jsx/7.tsx(1,13): error TS1002: Unterminated string literal.
7878
tests/cases/conformance/jsx/8.tsx(1,6): error TS17002: Expected corresponding JSX closing tag for 'a:b'.
7979
tests/cases/conformance/jsx/9.tsx(1,2): error TS2304: Cannot find name 'a:b'.
80+
tests/cases/conformance/jsx/9.tsx(1,2): error TS2633: JSX property access expressions cannot include JSX namespace names
8081
tests/cases/conformance/jsx/9.tsx(1,10): error TS2304: Cannot find name 'a:b'.
8182

8283

@@ -128,10 +129,12 @@ tests/cases/conformance/jsx/9.tsx(1,10): error TS2304: Cannot find name 'a:b'.
128129
<a:b></b>;
129130
~~~~
130131
!!! error TS17002: Expected corresponding JSX closing tag for 'a:b'.
131-
==== tests/cases/conformance/jsx/9.tsx (2 errors) ====
132+
==== tests/cases/conformance/jsx/9.tsx (3 errors) ====
132133
<a:b.c></a:b.c>;
133134
~~~
134135
!!! error TS2304: Cannot find name 'a:b'.
136+
~~~
137+
!!! error TS2633: JSX property access expressions cannot include JSX namespace names
135138
~~~
136139
!!! error TS2304: Cannot find name 'a:b'.
137140
==== tests/cases/conformance/jsx/10.tsx (6 errors) ====
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// @jsx: preserve
2+
declare namespace JSX {
3+
interface IntrinsicElements {
4+
'this:b': any;
5+
'b:c': {
6+
x: any
7+
};
8+
'a:b': any;
9+
}
10+
}
11+
12+
<a:b></a:b>;
13+
<b:c.x></b:c.x>;
14+
<this:b></this:b>;

0 commit comments

Comments
 (0)