Merge pull request #6411 from Microsoft/classifyJsx2

add support for classifying jsx text and string literals in jsx attributes
This commit is contained in:
Vladimir Matveev 2016-01-11 10:54:35 -08:00
commit d267d645d2
4 changed files with 100 additions and 7 deletions

View file

@ -3285,6 +3285,30 @@ namespace FourSlashInterface {
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 {
classificationType: type,

View file

@ -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 {
@ -1640,7 +1643,9 @@ namespace ts {
jsxOpenTagName = 19,
jsxCloseTagName = 20,
jsxSelfClosingTagName = 21,
jsxAttribute = 22
jsxAttribute = 22,
jsxText = 23,
jsxAttributeStringLiteralValue = 24,
}
/// Language Service
@ -6595,6 +6600,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;
}
}
@ -6803,12 +6811,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);
@ -6844,7 +6852,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;
}
}
@ -6863,7 +6872,7 @@ namespace ts {
return ClassificationType.numericLiteral;
}
else if (tokenKind === SyntaxKind.StringLiteral || tokenKind === SyntaxKind.StringLiteralType) {
return 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.
@ -6873,6 +6882,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) {
@ -6946,8 +6958,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.

View file

@ -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;

View file

@ -0,0 +1,27 @@
/// <reference path="fourslash.ts"/>
// @Filename: file1.tsx
////let x = <div a = "some-value" b = {1}>
//// some jsx text
////</div>;
////
////let y = <element attr="123"/>
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(">")
)