diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 350b9d450b..330ad05518 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1058,11 +1058,11 @@ namespace ts { } function parseIdentifierName(): Identifier { - return createIdentifier(isIdentifierOrKeyword()); + return createIdentifier(tokenIsIdentifierOrKeyword(token)); } function isLiteralPropertyName(): boolean { - return isIdentifierOrKeyword() || + return tokenIsIdentifierOrKeyword(token) || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral; } @@ -1086,7 +1086,7 @@ namespace ts { } function isSimplePropertyName() { - return token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || isIdentifierOrKeyword(); + return token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || tokenIsIdentifierOrKeyword(token); } function parseComputedPropertyName(): ComputedPropertyName { @@ -1213,9 +1213,9 @@ namespace ts { case ParsingContext.HeritageClauses: return isHeritageClause(); case ParsingContext.ImportOrExportSpecifiers: - return isIdentifierOrKeyword(); + return tokenIsIdentifierOrKeyword(token); case ParsingContext.JsxAttributes: - return isIdentifierOrKeyword() || token === SyntaxKind.OpenBraceToken; + return tokenIsIdentifierOrKeyword(token) || token === SyntaxKind.OpenBraceToken; case ParsingContext.JsxChildren: return true; case ParsingContext.JSDocFunctionParameters: @@ -1254,7 +1254,7 @@ namespace ts { function nextTokenIsIdentifierOrKeyword() { nextToken(); - return isIdentifierOrKeyword(); + return tokenIsIdentifierOrKeyword(token); } function isHeritageClauseExtendsOrImplementsKeyword(): boolean { @@ -1824,7 +1824,7 @@ namespace ts { // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". // In the first case though, ASI will not take effect because there is not a // line terminator after the identifier or keyword. - if (scanner.hasPrecedingLineBreak() && isIdentifierOrKeyword()) { + if (scanner.hasPrecedingLineBreak() && tokenIsIdentifierOrKeyword(token)) { let matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); if (matchesPattern) { @@ -2282,7 +2282,7 @@ namespace ts { } } - if (isIdentifierOrKeyword()) { + if (tokenIsIdentifierOrKeyword(token)) { return parsePropertyOrMethodSignature(); } } @@ -4101,13 +4101,9 @@ namespace ts { } } - function isIdentifierOrKeyword() { - return token >= SyntaxKind.Identifier; - } - function nextTokenIsIdentifierOrKeywordOnSameLine() { nextToken(); - return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak(); + return tokenIsIdentifierOrKeyword(token) && !scanner.hasPrecedingLineBreak(); } function nextTokenIsFunctionKeywordOnSameLine() { @@ -4117,7 +4113,7 @@ namespace ts { function nextTokenIsIdentifierOrKeywordOrNumberOnSameLine() { nextToken(); - return (isIdentifierOrKeyword() || token === SyntaxKind.NumericLiteral) && !scanner.hasPrecedingLineBreak(); + return (tokenIsIdentifierOrKeyword(token) || token === SyntaxKind.NumericLiteral) && !scanner.hasPrecedingLineBreak(); } function isDeclaration(): boolean { @@ -4170,7 +4166,7 @@ namespace ts { case SyntaxKind.ImportKeyword: nextToken(); return token === SyntaxKind.StringLiteral || token === SyntaxKind.AsteriskToken || - token === SyntaxKind.OpenBraceToken || isIdentifierOrKeyword(); + token === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token); case SyntaxKind.ExportKeyword: nextToken(); if (token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken || @@ -4777,7 +4773,7 @@ namespace ts { // It is very important that we check this *after* checking indexers because // the [ token can start an index signature or a computed property name - if (isIdentifierOrKeyword() || + if (tokenIsIdentifierOrKeyword(token) || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || token === SyntaxKind.AsteriskToken || @@ -5320,7 +5316,7 @@ namespace ts { return true; } - return isIdentifierOrKeyword(); + return tokenIsIdentifierOrKeyword(token); } export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number) { diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 199e7e9b63..82fbc8c2a5 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -6,6 +6,11 @@ namespace ts { (message: DiagnosticMessage, length: number): void; } + /* @internal */ + export function tokenIsIdentifierOrKeyword(token: SyntaxKind): boolean { + return token >= SyntaxKind.Identifier; + } + export interface Scanner { getStartPos(): number; getToken(): SyntaxKind; @@ -1590,7 +1595,7 @@ namespace ts { // Scans a JSX identifier; these differ from normal identifiers in that // they allow dashes function scanJsxIdentifier(): SyntaxKind { - if (token === SyntaxKind.Identifier) { + if (tokenIsIdentifierOrKeyword(token)) { let firstCharPosition = pos; while (pos < end) { let ch = text.charCodeAt(pos); diff --git a/tests/baselines/reference/keywordInJsxIdentifier.js b/tests/baselines/reference/keywordInJsxIdentifier.js new file mode 100644 index 0000000000..677a79138e --- /dev/null +++ b/tests/baselines/reference/keywordInJsxIdentifier.js @@ -0,0 +1,14 @@ +//// [keywordInJsxIdentifier.tsx] + +declare var React: any; +; +; +; +; + + +//// [keywordInJsxIdentifier.js] +React.createElement("foo", {"class-id": true}); +React.createElement("foo", {"class": true}); +React.createElement("foo", {"class-id": "1"}); +React.createElement("foo", {"class": "1"}); diff --git a/tests/baselines/reference/keywordInJsxIdentifier.symbols b/tests/baselines/reference/keywordInJsxIdentifier.symbols new file mode 100644 index 0000000000..874d7801a7 --- /dev/null +++ b/tests/baselines/reference/keywordInJsxIdentifier.symbols @@ -0,0 +1,17 @@ +=== tests/cases/compiler/keywordInJsxIdentifier.tsx === + +declare var React: any; +>React : Symbol(React, Decl(keywordInJsxIdentifier.tsx, 1, 11)) + +; +>class-id : Symbol(unknown) + +; +>class : Symbol(unknown) + +; +>class-id : Symbol(unknown) + +; +>class : Symbol(unknown) + diff --git a/tests/baselines/reference/keywordInJsxIdentifier.types b/tests/baselines/reference/keywordInJsxIdentifier.types new file mode 100644 index 0000000000..745fa5998b --- /dev/null +++ b/tests/baselines/reference/keywordInJsxIdentifier.types @@ -0,0 +1,25 @@ +=== tests/cases/compiler/keywordInJsxIdentifier.tsx === + +declare var React: any; +>React : any + +; +> : any +>foo : any +>class-id : any + +; +> : any +>foo : any +>class : any + +; +> : any +>foo : any +>class-id : any + +; +> : any +>foo : any +>class : any + diff --git a/tests/cases/compiler/keywordInJsxIdentifier.tsx b/tests/cases/compiler/keywordInJsxIdentifier.tsx new file mode 100644 index 0000000000..ce858edae5 --- /dev/null +++ b/tests/cases/compiler/keywordInJsxIdentifier.tsx @@ -0,0 +1,7 @@ +//@jsx: react + +declare var React: any; +; +; +; +;