From 946cf63a38743d23bab9e7616a9dbe160a6f5f37 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 8 Jan 2016 17:18:02 -0800 Subject: [PATCH 1/3] classify jsx text and jsx attribute values --- src/services/services.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 2c8982f10e..cf59e127a5 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1640,7 +1640,9 @@ namespace ts { jsxOpenTagName = 19, jsxCloseTagName = 20, jsxSelfClosingTagName = 21, - jsxAttribute = 22 + jsxAttribute = 22, + jsxText = 23, + jsxAttributeStringValue = 24, } /// Language Service @@ -6783,12 +6785,12 @@ namespace ts { } } - function classifyToken(token: Node): void { + function classifyTokenOrJsxText(token: Node): void { if (nodeIsMissing(token)) { return; } - const tokenStart = classifyLeadingTriviaAndGetTokenStart(token); + const tokenStart = token.kind === SyntaxKind.JsxText ? token.pos : classifyLeadingTriviaAndGetTokenStart(token); const tokenWidth = token.end - tokenStart; Debug.assert(tokenWidth >= 0); @@ -6843,7 +6845,7 @@ namespace ts { return ClassificationType.numericLiteral; } else if (tokenKind === SyntaxKind.StringLiteral || tokenKind === SyntaxKind.StringLiteralType) { - return ClassificationType.stringLiteral; + return token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringValue : ClassificationType.stringLiteral; } else if (tokenKind === SyntaxKind.RegularExpressionLiteral) { // TODO: we should get another classification type for these literals. @@ -6853,6 +6855,9 @@ namespace ts { // TODO (drosen): we should *also* get another classification type for these literals. return ClassificationType.stringLiteral; } + else if (tokenKind === SyntaxKind.JsxText) { + return ClassificationType.jsxText; + } else if (tokenKind === SyntaxKind.Identifier) { if (token) { switch (token.parent.kind) { @@ -6926,8 +6931,8 @@ namespace ts { const children = element.getChildren(sourceFile); for (let i = 0, n = children.length; i < n; i++) { const child = children[i]; - if (isToken(child)) { - classifyToken(child); + if (isToken(child) || child.kind === SyntaxKind.JsxText) { + classifyTokenOrJsxText(child); } else { // Recurse into our child nodes. From 5c0d1a8afa7ab656535288b763d0b41e91598c7b Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 8 Jan 2016 22:30:26 -0800 Subject: [PATCH 2/3] added jsx classification support to fourslash and tests --- src/harness/fourslash.ts | 24 +++++++++++++++ src/services/services.ts | 13 ++++++-- tests/cases/fourslash/fourslash.ts | 30 +++++++++++++++++++ .../fourslash/syntacticClassificationsJsx1.ts | 27 +++++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/syntacticClassificationsJsx1.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 30626a83d6..ca0a5ad278 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3284,6 +3284,30 @@ namespace FourSlashInterface { export function typeAliasName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { return getClassification("typeAliasName", text, position); } + + export function jsxOpenTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("jsxOpenTagName", text, position); + } + + export function jsxCloseTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("jsxCloseTagName", text, position); + } + + export function jsxSelfClosingTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("jsxSelfClosingTagName", text, position); + } + + export function jsxAttribute(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("jsxAttribute", text, position); + } + + export function jsxText(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("jsxText", text, position); + } + + export function jsxAttributeStringLiteralValue(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("jsxAttributeStringLiteralValue", text, position); + } function getClassification(type: string, text: string, position?: number) { return { diff --git a/src/services/services.ts b/src/services/services.ts index cf59e127a5..248965b240 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1616,6 +1616,9 @@ namespace ts { public static jsxOpenTagName = "jsx open tag name"; public static jsxCloseTagName = "jsx close tag name"; public static jsxSelfClosingTagName = "jsx self closing tag name"; + public static jsxAttribute = "jsx attribute"; + public static jsxText = "jsx text"; + public static jsxAttributeStringLiteralValue = "jsx attribute string literal value"; } export const enum ClassificationType { @@ -1642,7 +1645,7 @@ namespace ts { jsxSelfClosingTagName = 21, jsxAttribute = 22, jsxText = 23, - jsxAttributeStringValue = 24, + jsxAttributeStringLiteralValue = 24, } /// Language Service @@ -6577,6 +6580,9 @@ namespace ts { case ClassificationType.jsxOpenTagName: return ClassificationTypeNames.jsxOpenTagName; case ClassificationType.jsxCloseTagName: return ClassificationTypeNames.jsxCloseTagName; case ClassificationType.jsxSelfClosingTagName: return ClassificationTypeNames.jsxSelfClosingTagName; + case ClassificationType.jsxAttribute: return ClassificationTypeNames.jsxAttribute; + case ClassificationType.jsxText: return ClassificationTypeNames.jsxText; + case ClassificationType.jsxAttributeStringLiteralValue: return ClassificationTypeNames.jsxAttributeStringLiteralValue; } } @@ -6826,7 +6832,8 @@ namespace ts { // the '=' in a variable declaration is special cased here. if (token.parent.kind === SyntaxKind.VariableDeclaration || token.parent.kind === SyntaxKind.PropertyDeclaration || - token.parent.kind === SyntaxKind.Parameter) { + token.parent.kind === SyntaxKind.Parameter || + token.parent.kind === SyntaxKind.JsxAttribute) { return ClassificationType.operator; } } @@ -6845,7 +6852,7 @@ namespace ts { return ClassificationType.numericLiteral; } else if (tokenKind === SyntaxKind.StringLiteral || tokenKind === SyntaxKind.StringLiteralType) { - return token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringValue : ClassificationType.stringLiteral; + return token.parent.kind === SyntaxKind.JsxAttribute ? ClassificationType.jsxAttributeStringLiteralValue : ClassificationType.stringLiteral; } else if (tokenKind === SyntaxKind.RegularExpressionLiteral) { // TODO: we should get another classification type for these literals. diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 0e83189dd8..b69a757f01 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -338,6 +338,36 @@ declare namespace FourSlashInterface { text: string; textSpan?: TextSpan; }; + function jsxOpenTagName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function jsxCloseTagName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function jsxSelfClosingTagName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function jsxAttribute(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function jsxText(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function jsxAttributeStringLiteralValue(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; } } declare function verifyOperationIsCancelled(f: any): void; diff --git a/tests/cases/fourslash/syntacticClassificationsJsx1.ts b/tests/cases/fourslash/syntacticClassificationsJsx1.ts new file mode 100644 index 0000000000..a26e7f9c8f --- /dev/null +++ b/tests/cases/fourslash/syntacticClassificationsJsx1.ts @@ -0,0 +1,27 @@ +/// + +// @Filename: file1.tsx +////let x =
+//// some jsx text +////
; +//// +////let y = + +const c = classification; +verify.syntacticClassificationsAre( + c.keyword("let"), c.identifier("x"), c.operator("="), + c.punctuation("<"), + c.jsxOpenTagName("div"), + c.jsxAttribute("a"), c.operator("="), c.jsxAttributeStringLiteralValue(`"some-value"`), + c.jsxAttribute("b"), c.operator("="), c.punctuation("{"), c.numericLiteral("1"), c.punctuation("}"), + c.punctuation(">"), + c.jsxText(` + some jsx text +`), + c.punctuation("<"), c.punctuation("/"), c.jsxCloseTagName("div"), c.punctuation(">"), c.punctuation(";"), + c.keyword("let"), c.identifier("y"), c.operator("="), + c.punctuation("<"), + c.jsxSelfClosingTagName("element"), + c.jsxAttribute("attr"), c.operator("="), c.jsxAttributeStringLiteralValue(`"123"`), + c.punctuation("/"), c.punctuation(">") +) \ No newline at end of file From c1b031aa739ae88dff4d19c2517e8547b4ba9208 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 8 Jan 2016 22:43:21 -0800 Subject: [PATCH 3/3] fix linter issues --- src/harness/fourslash.ts | 2 +- src/services/services.ts | 2 +- tests/cases/fourslash/syntacticClassificationsJsx1.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ca0a5ad278..435acf548b 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3284,7 +3284,7 @@ namespace FourSlashInterface { export function typeAliasName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { return getClassification("typeAliasName", text, position); } - + export function jsxOpenTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { return getClassification("jsxOpenTagName", text, position); } diff --git a/src/services/services.ts b/src/services/services.ts index 248965b240..61b504a25c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6864,7 +6864,7 @@ namespace ts { } else if (tokenKind === SyntaxKind.JsxText) { return ClassificationType.jsxText; - } + } else if (tokenKind === SyntaxKind.Identifier) { if (token) { switch (token.parent.kind) { diff --git a/tests/cases/fourslash/syntacticClassificationsJsx1.ts b/tests/cases/fourslash/syntacticClassificationsJsx1.ts index a26e7f9c8f..e9de07c759 100644 --- a/tests/cases/fourslash/syntacticClassificationsJsx1.ts +++ b/tests/cases/fourslash/syntacticClassificationsJsx1.ts @@ -7,7 +7,7 @@ //// ////let y = -const c = classification; +const c = classification; verify.syntacticClassificationsAre( c.keyword("let"), c.identifier("x"), c.operator("="), c.punctuation("<"),