diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5619d3db66d..36b3db49fe0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4119,32 +4119,9 @@ namespace ts { return finishNode(node); } - function parseJsxChild(): JsxChild { - switch (token()) { - case SyntaxKind.JsxText: - case SyntaxKind.JsxTextAllWhiteSpaces: - return parseJsxText(); - case SyntaxKind.OpenBraceToken: - return parseJsxExpression(/*inExpressionContext*/ false)!; - case SyntaxKind.LessThanToken: - return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false); - } - Debug.fail("Unknown JSX child kind " + token()); - } - - function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray { - const list = []; - const listPos = getNodePos(); - const saveParsingContext = parsingContext; - parsingContext |= 1 << ParsingContext.JsxChildren; - - while (true) { - currentToken = scanner.reScanJsxToken(); - if (token() === SyntaxKind.LessThanSlashToken) { - // Closing tag - break; - } - else if (token() === SyntaxKind.EndOfFileToken) { + function parseJsxChild(openingTag: JsxOpeningElement | JsxOpeningFragment, token: JsxTokenSyntaxKind): JsxChild | undefined { + switch (token) { + case SyntaxKind.EndOfFileToken: // If we hit EOF, issue the error at the tag that lacks the closing element // rather than at the end of the file (which is useless) if (isJsxOpeningFragment(openingTag)) { @@ -4154,19 +4131,35 @@ namespace ts { const openingTagName = openingTag.tagName; parseErrorAtPosition(openingTagName.pos, openingTagName.end - openingTagName.pos, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTagName)); } - break; - } - else if (token() === SyntaxKind.ConflictMarkerTrivia) { - break; - } - const child = parseJsxChild(); - if (child) { - list.push(child); - } + return undefined; + case SyntaxKind.LessThanSlashToken: + case SyntaxKind.ConflictMarkerTrivia: + return undefined; + case SyntaxKind.JsxText: + case SyntaxKind.JsxTextAllWhiteSpaces: + return parseJsxText(); + case SyntaxKind.OpenBraceToken: + return parseJsxExpression(/*inExpressionContext*/ false); + case SyntaxKind.LessThanToken: + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false); + default: + return Debug.assertNever(token); + } + } + + function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray { + const list = []; + const listPos = getNodePos(); + const saveParsingContext = parsingContext; + parsingContext |= 1 << ParsingContext.JsxChildren; + + while (true) { + const child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken()); + if (!child) break; + list.push(child); } parsingContext = saveParsingContext; - return createNodeArray(list, listPos); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index cdb055bb732..55dfe9be5ea 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -33,8 +33,8 @@ namespace ts { reScanTemplateToken(): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; - reScanJsxToken(): SyntaxKind; - scanJsxToken(): SyntaxKind; + reScanJsxToken(): JsxTokenSyntaxKind; + scanJsxToken(): JsxTokenSyntaxKind; scanJSDocToken(): JsDocSyntaxKind; scan(): SyntaxKind; getText(): string; @@ -1836,12 +1836,12 @@ namespace ts { return token = scanTemplateAndSetTokenValue(); } - function reScanJsxToken(): SyntaxKind { + function reScanJsxToken(): JsxTokenSyntaxKind { pos = tokenPos = startPos; return token = scanJsxToken(); } - function scanJsxToken(): SyntaxKind { + function scanJsxToken(): JsxTokenSyntaxKind { startPos = tokenPos = pos; if (pos >= end) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 42d8462cecd..235f5cab674 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -75,6 +75,15 @@ namespace ts { | SyntaxKind.Identifier | SyntaxKind.Unknown; + export type JsxTokenSyntaxKind = + | SyntaxKind.LessThanSlashToken + | SyntaxKind.EndOfFileToken + | SyntaxKind.ConflictMarkerTrivia + | SyntaxKind.JsxText + | SyntaxKind.JsxTextAllWhiteSpaces + | SyntaxKind.OpenBraceToken + | SyntaxKind.LessThanToken; + // token > SyntaxKind.Identifer => token is a keyword // Also, If you add a new SyntaxKind be sure to keep the `Markers` section at the bottom in sync export const enum SyntaxKind { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 1048f338d92..7034909f6db 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -60,6 +60,7 @@ declare namespace ts { end: number; } type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.Unknown; + type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; enum SyntaxKind { Unknown = 0, EndOfFileToken = 1, @@ -3260,8 +3261,8 @@ declare namespace ts { reScanTemplateToken(): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; - reScanJsxToken(): SyntaxKind; - scanJsxToken(): SyntaxKind; + reScanJsxToken(): JsxTokenSyntaxKind; + scanJsxToken(): JsxTokenSyntaxKind; scanJSDocToken(): JsDocSyntaxKind; scan(): SyntaxKind; getText(): string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 99a9bd99a60..1908eb1114a 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -60,6 +60,7 @@ declare namespace ts { end: number; } type JsDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.Unknown; + type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken; enum SyntaxKind { Unknown = 0, EndOfFileToken = 1, @@ -2916,8 +2917,8 @@ declare namespace ts { reScanTemplateToken(): SyntaxKind; scanJsxIdentifier(): SyntaxKind; scanJsxAttributeValue(): SyntaxKind; - reScanJsxToken(): SyntaxKind; - scanJsxToken(): SyntaxKind; + reScanJsxToken(): JsxTokenSyntaxKind; + scanJsxToken(): JsxTokenSyntaxKind; scanJSDocToken(): JsDocSyntaxKind; scan(): SyntaxKind; getText(): string;