From fe2d9648e91d91f4019805f9416aa2fdcf12ae85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Wed, 16 Jan 2019 15:24:30 +0800 Subject: [PATCH 1/2] add jsx factory and hold text in jsxtext node --- src/compiler/emitter.ts | 2 +- src/compiler/factory.ts | 22 +++++++++++++++++++ src/compiler/parser.ts | 1 + src/compiler/scanner.ts | 1 + src/compiler/transformers/jsx.ts | 2 +- src/compiler/types.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 6 ++++- tests/baselines/reference/api/typescript.d.ts | 6 ++++- 8 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 395f64488909b..0ed60b3728e6f 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2589,7 +2589,7 @@ namespace ts { } function emitJsxText(node: JsxText) { - writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); + writer.writeLiteral(node.text); } function emitJsxClosingElementOrFragment(node: JsxClosingElement | JsxClosingFragment) { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index ec19d2c906c12..217b317fa67ca 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2299,6 +2299,28 @@ namespace ts { return node; } + export function createJsxText(text: string, containsOnlyWhiteSpaces: boolean) { + const node = createNode(SyntaxKind.JsxText); + node.text = text; + node.containsOnlyWhiteSpaces = containsOnlyWhiteSpaces; + return node; + } + + export function updateJsxText(node: JsxText, text: string, containsOnlyWhiteSpaces: boolean) { + return node.text !== text + || node.containsOnlyWhiteSpaces !== containsOnlyWhiteSpaces + ? updateNode(createJsxText(text, containsOnlyWhiteSpaces), node) + : node; + } + + export function createJsxOpeningFragment() { + return createNode(SyntaxKind.JsxOpeningFragment); + } + + export function createJsxJsxClosingFragment() { + return createNode(SyntaxKind.JsxClosingFragment); + } + export function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment) { return node.openingFragment !== openingFragment || node.children !== children diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 53e455050142b..ef12ab7c39af1 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4250,6 +4250,7 @@ namespace ts { function parseJsxText(): JsxText { const node = createNode(SyntaxKind.JsxText); + node.text = scanner.getTokenValue(); node.containsOnlyWhiteSpaces = currentToken === SyntaxKind.JsxTextAllWhiteSpaces; currentToken = scanner.scanJsxToken(); return finishNode(node); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index d59be9758656c..a0153e4257420 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1994,6 +1994,7 @@ namespace ts { pos++; } + tokenValue = text.substring(startPos, pos); return firstNonWhitespace === -1 ? SyntaxKind.JsxTextAllWhiteSpaces : SyntaxKind.JsxText; } diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index c31cdd17f027c..2fe343da13441 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -182,7 +182,7 @@ namespace ts { } function visitJsxText(node: JsxText): StringLiteral | undefined { - const fixed = fixupWhitespaceAndDecodeEntities(getTextOfNode(node, /*includeTrivia*/ true)); + const fixed = fixupWhitespaceAndDecodeEntities(node.text); return fixed === undefined ? undefined : createLiteral(fixed); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 125c3297863c2..d30bc5e86c080 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1932,7 +1932,7 @@ namespace ts { expression?: Expression; } - export interface JsxText extends Node { + export interface JsxText extends LiteralLikeNode { kind: SyntaxKind.JsxText; containsOnlyWhiteSpaces: boolean; parent: JsxElement; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 30effc9e91a3d..ee55257015511 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1190,7 +1190,7 @@ declare namespace ts { dotDotDotToken?: Token; expression?: Expression; } - interface JsxText extends Node { + interface JsxText extends LiteralLikeNode { kind: SyntaxKind.JsxText; containsOnlyWhiteSpaces: boolean; parent: JsxElement; @@ -3927,6 +3927,10 @@ declare namespace ts { function createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; function createJsxFragment(openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment): JsxFragment; + function createJsxText(text: string, containsOnlyWhiteSpaces: boolean): JsxText; + function updateJsxText(node: JsxText, text: string, containsOnlyWhiteSpaces: boolean): JsxText; + function createJsxOpeningFragment(): JsxOpeningFragment; + function createJsxJsxClosingFragment(): JsxClosingFragment; function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment): JsxFragment; function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index cd6d45a16478a..1a2e511272937 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1190,7 +1190,7 @@ declare namespace ts { dotDotDotToken?: Token; expression?: Expression; } - interface JsxText extends Node { + interface JsxText extends LiteralLikeNode { kind: SyntaxKind.JsxText; containsOnlyWhiteSpaces: boolean; parent: JsxElement; @@ -3927,6 +3927,10 @@ declare namespace ts { function createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; function createJsxFragment(openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment): JsxFragment; + function createJsxText(text: string, containsOnlyWhiteSpaces: boolean): JsxText; + function updateJsxText(node: JsxText, text: string, containsOnlyWhiteSpaces: boolean): JsxText; + function createJsxOpeningFragment(): JsxOpeningFragment; + function createJsxJsxClosingFragment(): JsxClosingFragment; function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment): JsxFragment; function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; From d4d2e523aa9d93507852c84a92bd8000094ea5aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Thu, 17 Jan 2019 11:38:28 +0800 Subject: [PATCH 2/2] update jsxtext prop name and factory --- src/compiler/checker.ts | 6 +++--- src/compiler/factory.ts | 16 ++++++++-------- src/compiler/parser.ts | 2 +- src/compiler/types.ts | 2 +- src/services/utilities.ts | 2 +- .../baselines/reference/api/tsserverlibrary.d.ts | 6 +++--- tests/baselines/reference/api/typescript.d.ts | 6 +++--- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f7cec89fe8078..be5994c10fe65 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11358,7 +11358,7 @@ namespace ts { // child is of the type of the expression return { errorNode: child, innerExpression: child.expression, nameType }; case SyntaxKind.JsxText: - if (child.containsOnlyWhiteSpaces) { + if (child.containsOnlyTriviaWhiteSpaces) { break; // Whitespace only jsx text isn't real jsx text } // child is a string @@ -11382,7 +11382,7 @@ namespace ts { const childrenPropName = childPropName === undefined ? "children" : unescapeLeadingUnderscores(childPropName); const childrenNameType = getLiteralType(childrenPropName); const childrenTargetType = getIndexedAccessType(target, childrenNameType); - const validChildren = filter(containingElement.children, i => !isJsxText(i) || !i.containsOnlyWhiteSpaces); + const validChildren = filter(containingElement.children, i => !isJsxText(i) || !i.containsOnlyTriviaWhiteSpaces); if (!length(validChildren)) { return result; } @@ -18586,7 +18586,7 @@ namespace ts { // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that // because then type of children property will have constituent of string type. if (child.kind === SyntaxKind.JsxText) { - if (!child.containsOnlyWhiteSpaces) { + if (!child.containsOnlyTriviaWhiteSpaces) { childrenTypes.push(stringType); } } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 217b317fa67ca..b193ffb6bf96a 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2299,26 +2299,26 @@ namespace ts { return node; } - export function createJsxText(text: string, containsOnlyWhiteSpaces: boolean) { - const node = createNode(SyntaxKind.JsxText); + export function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) { + const node = createSynthesizedNode(SyntaxKind.JsxText); node.text = text; - node.containsOnlyWhiteSpaces = containsOnlyWhiteSpaces; + node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces; return node; } - export function updateJsxText(node: JsxText, text: string, containsOnlyWhiteSpaces: boolean) { + export function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { return node.text !== text - || node.containsOnlyWhiteSpaces !== containsOnlyWhiteSpaces - ? updateNode(createJsxText(text, containsOnlyWhiteSpaces), node) + || node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces + ? updateNode(createJsxText(text, containsOnlyTriviaWhiteSpaces), node) : node; } export function createJsxOpeningFragment() { - return createNode(SyntaxKind.JsxOpeningFragment); + return createSynthesizedNode(SyntaxKind.JsxOpeningFragment); } export function createJsxJsxClosingFragment() { - return createNode(SyntaxKind.JsxClosingFragment); + return createSynthesizedNode(SyntaxKind.JsxClosingFragment); } export function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ef12ab7c39af1..41e42577e9062 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4251,7 +4251,7 @@ namespace ts { function parseJsxText(): JsxText { const node = createNode(SyntaxKind.JsxText); node.text = scanner.getTokenValue(); - node.containsOnlyWhiteSpaces = currentToken === SyntaxKind.JsxTextAllWhiteSpaces; + node.containsOnlyTriviaWhiteSpaces = currentToken === SyntaxKind.JsxTextAllWhiteSpaces; currentToken = scanner.scanJsxToken(); return finishNode(node); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d30bc5e86c080..837a4a298ba0a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1934,7 +1934,7 @@ namespace ts { export interface JsxText extends LiteralLikeNode { kind: SyntaxKind.JsxText; - containsOnlyWhiteSpaces: boolean; + containsOnlyTriviaWhiteSpaces: boolean; parent: JsxElement; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 2f78ef2324b9a..5d1aaac992f08 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -905,7 +905,7 @@ namespace ts { } function isWhiteSpaceOnlyJsxText(node: Node): boolean { - return isJsxText(node) && node.containsOnlyWhiteSpaces; + return isJsxText(node) && node.containsOnlyTriviaWhiteSpaces; } export function isInTemplateString(sourceFile: SourceFile, position: number) { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ee55257015511..b25fcad1af071 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1192,7 +1192,7 @@ declare namespace ts { } interface JsxText extends LiteralLikeNode { kind: SyntaxKind.JsxText; - containsOnlyWhiteSpaces: boolean; + containsOnlyTriviaWhiteSpaces: boolean; parent: JsxElement; } type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment; @@ -3927,8 +3927,8 @@ declare namespace ts { function createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; function createJsxFragment(openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment): JsxFragment; - function createJsxText(text: string, containsOnlyWhiteSpaces: boolean): JsxText; - function updateJsxText(node: JsxText, text: string, containsOnlyWhiteSpaces: boolean): JsxText; + function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; + function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; function createJsxOpeningFragment(): JsxOpeningFragment; function createJsxJsxClosingFragment(): JsxClosingFragment; function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment): JsxFragment; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1a2e511272937..178d09074fe76 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1192,7 +1192,7 @@ declare namespace ts { } interface JsxText extends LiteralLikeNode { kind: SyntaxKind.JsxText; - containsOnlyWhiteSpaces: boolean; + containsOnlyTriviaWhiteSpaces: boolean; parent: JsxElement; } type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment; @@ -3927,8 +3927,8 @@ declare namespace ts { function createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement; function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; function createJsxFragment(openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment): JsxFragment; - function createJsxText(text: string, containsOnlyWhiteSpaces: boolean): JsxText; - function updateJsxText(node: JsxText, text: string, containsOnlyWhiteSpaces: boolean): JsxText; + function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; + function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean): JsxText; function createJsxOpeningFragment(): JsxOpeningFragment; function createJsxJsxClosingFragment(): JsxClosingFragment; function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment): JsxFragment;