Skip to content

Commit d267d64

Browse files
committed
Merge pull request #6411 from Microsoft/classifyJsx2
add support for classifying jsx text and string literals in jsx attributes
2 parents c73772c + c1b031a commit d267d64

File tree

4 files changed

+100
-7
lines changed

4 files changed

+100
-7
lines changed

src/harness/fourslash.ts

+24
Original file line numberDiff line numberDiff line change
@@ -3285,6 +3285,30 @@ namespace FourSlashInterface {
32853285
return getClassification("typeAliasName", text, position);
32863286
}
32873287

3288+
export function jsxOpenTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
3289+
return getClassification("jsxOpenTagName", text, position);
3290+
}
3291+
3292+
export function jsxCloseTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
3293+
return getClassification("jsxCloseTagName", text, position);
3294+
}
3295+
3296+
export function jsxSelfClosingTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
3297+
return getClassification("jsxSelfClosingTagName", text, position);
3298+
}
3299+
3300+
export function jsxAttribute(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
3301+
return getClassification("jsxAttribute", text, position);
3302+
}
3303+
3304+
export function jsxText(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
3305+
return getClassification("jsxText", text, position);
3306+
}
3307+
3308+
export function jsxAttributeStringLiteralValue(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } {
3309+
return getClassification("jsxAttributeStringLiteralValue", text, position);
3310+
}
3311+
32883312
function getClassification(type: string, text: string, position?: number) {
32893313
return {
32903314
classificationType: type,

src/services/services.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,9 @@ namespace ts {
16161616
public static jsxOpenTagName = "jsx open tag name";
16171617
public static jsxCloseTagName = "jsx close tag name";
16181618
public static jsxSelfClosingTagName = "jsx self closing tag name";
1619+
public static jsxAttribute = "jsx attribute";
1620+
public static jsxText = "jsx text";
1621+
public static jsxAttributeStringLiteralValue = "jsx attribute string literal value";
16191622
}
16201623

16211624
export const enum ClassificationType {
@@ -1640,7 +1643,9 @@ namespace ts {
16401643
jsxOpenTagName = 19,
16411644
jsxCloseTagName = 20,
16421645
jsxSelfClosingTagName = 21,
1643-
jsxAttribute = 22
1646+
jsxAttribute = 22,
1647+
jsxText = 23,
1648+
jsxAttributeStringLiteralValue = 24,
16441649
}
16451650

16461651
/// Language Service
@@ -6595,6 +6600,9 @@ namespace ts {
65956600
case ClassificationType.jsxOpenTagName: return ClassificationTypeNames.jsxOpenTagName;
65966601
case ClassificationType.jsxCloseTagName: return ClassificationTypeNames.jsxCloseTagName;
65976602
case ClassificationType.jsxSelfClosingTagName: return ClassificationTypeNames.jsxSelfClosingTagName;
6603+
case ClassificationType.jsxAttribute: return ClassificationTypeNames.jsxAttribute;
6604+
case ClassificationType.jsxText: return ClassificationTypeNames.jsxText;
6605+
case ClassificationType.jsxAttributeStringLiteralValue: return ClassificationTypeNames.jsxAttributeStringLiteralValue;
65986606
}
65996607
}
66006608

@@ -6803,12 +6811,12 @@ namespace ts {
68036811
}
68046812
}
68056813

6806-
function classifyToken(token: Node): void {
6814+
function classifyTokenOrJsxText(token: Node): void {
68076815
if (nodeIsMissing(token)) {
68086816
return;
68096817
}
68106818

6811-
const tokenStart = classifyLeadingTriviaAndGetTokenStart(token);
6819+
const tokenStart = token.kind === SyntaxKind.JsxText ? token.pos : classifyLeadingTriviaAndGetTokenStart(token);
68126820

68136821
const tokenWidth = token.end - tokenStart;
68146822
Debug.assert(tokenWidth >= 0);
@@ -6844,7 +6852,8 @@ namespace ts {
68446852
// the '=' in a variable declaration is special cased here.
68456853
if (token.parent.kind === SyntaxKind.VariableDeclaration ||
68466854
token.parent.kind === SyntaxKind.PropertyDeclaration ||
6847-
token.parent.kind === SyntaxKind.Parameter) {
6855+
token.parent.kind === SyntaxKind.Parameter ||
6856+
token.parent.kind === SyntaxKind.JsxAttribute) {
68486857
return ClassificationType.operator;
68496858
}
68506859
}
@@ -6863,7 +6872,7 @@ namespace ts {
68636872
return ClassificationType.numericLiteral;
68646873
}
68656874
else if (tokenKind === SyntaxKind.StringLiteral || tokenKind === SyntaxKind.StringLiteralType) {
6866-
return ClassificationType.stringLiteral;
6875+
return token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral;
68676876
}
68686877
else if (tokenKind === SyntaxKind.RegularExpressionLiteral) {
68696878
// TODO: we should get another classification type for these literals.
@@ -6873,6 +6882,9 @@ namespace ts {
68736882
// TODO (drosen): we should *also* get another classification type for these literals.
68746883
return ClassificationType.stringLiteral;
68756884
}
6885+
else if (tokenKind === SyntaxKind.JsxText) {
6886+
return ClassificationType.jsxText;
6887+
}
68766888
else if (tokenKind === SyntaxKind.Identifier) {
68776889
if (token) {
68786890
switch (token.parent.kind) {
@@ -6946,8 +6958,8 @@ namespace ts {
69466958
const children = element.getChildren(sourceFile);
69476959
for (let i = 0, n = children.length; i < n; i++) {
69486960
const child = children[i];
6949-
if (isToken(child)) {
6950-
classifyToken(child);
6961+
if (isToken(child) || child.kind === SyntaxKind.JsxText) {
6962+
classifyTokenOrJsxText(child);
69516963
}
69526964
else {
69536965
// Recurse into our child nodes.

tests/cases/fourslash/fourslash.ts

+30
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,36 @@ declare namespace FourSlashInterface {
338338
text: string;
339339
textSpan?: TextSpan;
340340
};
341+
function jsxOpenTagName(text: string, position?: number): {
342+
classificationType: string;
343+
text: string;
344+
textSpan?: TextSpan;
345+
};
346+
function jsxCloseTagName(text: string, position?: number): {
347+
classificationType: string;
348+
text: string;
349+
textSpan?: TextSpan;
350+
};
351+
function jsxSelfClosingTagName(text: string, position?: number): {
352+
classificationType: string;
353+
text: string;
354+
textSpan?: TextSpan;
355+
};
356+
function jsxAttribute(text: string, position?: number): {
357+
classificationType: string;
358+
text: string;
359+
textSpan?: TextSpan;
360+
};
361+
function jsxText(text: string, position?: number): {
362+
classificationType: string;
363+
text: string;
364+
textSpan?: TextSpan;
365+
};
366+
function jsxAttributeStringLiteralValue(text: string, position?: number): {
367+
classificationType: string;
368+
text: string;
369+
textSpan?: TextSpan;
370+
};
341371
}
342372
}
343373
declare function verifyOperationIsCancelled(f: any): void;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
// @Filename: file1.tsx
4+
////let x = <div a = "some-value" b = {1}>
5+
//// some jsx text
6+
////</div>;
7+
////
8+
////let y = <element attr="123"/>
9+
10+
const c = classification;
11+
verify.syntacticClassificationsAre(
12+
c.keyword("let"), c.identifier("x"), c.operator("="),
13+
c.punctuation("<"),
14+
c.jsxOpenTagName("div"),
15+
c.jsxAttribute("a"), c.operator("="), c.jsxAttributeStringLiteralValue(`"some-value"`),
16+
c.jsxAttribute("b"), c.operator("="), c.punctuation("{"), c.numericLiteral("1"), c.punctuation("}"),
17+
c.punctuation(">"),
18+
c.jsxText(`
19+
some jsx text
20+
`),
21+
c.punctuation("<"), c.punctuation("/"), c.jsxCloseTagName("div"), c.punctuation(">"), c.punctuation(";"),
22+
c.keyword("let"), c.identifier("y"), c.operator("="),
23+
c.punctuation("<"),
24+
c.jsxSelfClosingTagName("element"),
25+
c.jsxAttribute("attr"), c.operator("="), c.jsxAttributeStringLiteralValue(`"123"`),
26+
c.punctuation("/"), c.punctuation(">")
27+
)

0 commit comments

Comments
 (0)