From fa44fd218bf88fb5b853a2d9bb51a94c03a6f206 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Wed, 1 Apr 2020 21:59:00 +0300 Subject: [PATCH] fix(37456): omit type arguments from JsxSelfClosingElement, JsxOpeningElement nodes --- src/compiler/binder.ts | 15 ++++- src/compiler/transformers/ts.ts | 22 +++++++ .../tsxTypeArgumentsJsxPreserveOutput.js | 42 +++++++++++++ .../tsxTypeArgumentsJsxPreserveOutput.symbols | 53 ++++++++++++++++ .../tsxTypeArgumentsJsxPreserveOutput.types | 63 +++++++++++++++++++ .../jsx/tsxTypeArgumentsJsxPreserveOutput.tsx | 27 ++++++++ 6 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.js create mode 100644 tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.symbols create mode 100644 tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.types create mode 100644 tests/cases/conformance/jsx/tsxTypeArgumentsJsxPreserveOutput.tsx diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 538d169488059..3cde8be7ea115 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3542,6 +3542,10 @@ namespace ts { case SyntaxKind.ElementAccessExpression: return computeElementAccess(node, subtreeFlags); + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + return computeJsxOpeningLikeElement(node, subtreeFlags); + default: return computeOther(node, kind, subtreeFlags); } @@ -3591,6 +3595,15 @@ namespace ts { return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes; } + function computeJsxOpeningLikeElement(node: JsxOpeningLikeElement, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags | TransformFlags.AssertJsx; + if (node.typeArguments) { + transformFlags |= TransformFlags.AssertTypeScript; + } + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + function computeBinaryExpression(node: BinaryExpression, subtreeFlags: TransformFlags) { let transformFlags = subtreeFlags; const operatorTokenKind = node.operatorToken.kind; @@ -4124,8 +4137,6 @@ namespace ts { break; case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxText: case SyntaxKind.JsxClosingElement: case SyntaxKind.JsxFragment: diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 81599c8828668..a78c77300d2ab 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -540,6 +540,12 @@ namespace ts { // TypeScript namespace or external module import. return visitImportEqualsDeclaration(node); + case SyntaxKind.JsxSelfClosingElement: + return visitJsxSelfClosingElement(node); + + case SyntaxKind.JsxOpeningElement: + return visitJsxJsxOpeningElement(node); + default: // node contains some other TypeScript syntax return visitEachChild(node, visitor, context); @@ -2271,6 +2277,22 @@ namespace ts { visitNode(node.template, visitor, isExpression)); } + function visitJsxSelfClosingElement(node: JsxSelfClosingElement) { + return updateJsxSelfClosingElement( + node, + visitNode(node.tagName, visitor, isJsxTagNameExpression), + /*typeArguments*/ undefined, + visitNode(node.attributes, visitor, isJsxAttributes)); + } + + function visitJsxJsxOpeningElement(node: JsxOpeningElement) { + return updateJsxOpeningElement( + node, + visitNode(node.tagName, visitor, isJsxTagNameExpression), + /*typeArguments*/ undefined, + visitNode(node.attributes, visitor, isJsxAttributes)); + } + /** * Determines whether to emit an enum declaration. * diff --git a/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.js b/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.js new file mode 100644 index 0000000000000..aab5d71021596 --- /dev/null +++ b/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.js @@ -0,0 +1,42 @@ +//// [foo.tsx] +import React = require('react'); + +type TypeProps = { foo?: boolean; }; +interface InterfaceProps { foo?: boolean; } + +function Foo() { + return null; +} + +<> + /> + /> + /> + /> + /> + /> + /> + /> + /> + /> + + +//// [foo.jsx] +"use strict"; +exports.__esModule = true; +var React = require("react"); +function Foo() { + return null; +} +<> + + + + + + + + + + +; diff --git a/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.symbols b/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.symbols new file mode 100644 index 0000000000000..41b6c9ca4dfd0 --- /dev/null +++ b/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.symbols @@ -0,0 +1,53 @@ +=== tests/cases/conformance/jsx/foo.tsx === +import React = require('react'); +>React : Symbol(React, Decl(foo.tsx, 0, 0)) + +type TypeProps = { foo?: boolean; }; +>TypeProps : Symbol(TypeProps, Decl(foo.tsx, 0, 32)) +>foo : Symbol(foo, Decl(foo.tsx, 2, 18)) + +interface InterfaceProps { foo?: boolean; } +>InterfaceProps : Symbol(InterfaceProps, Decl(foo.tsx, 2, 36)) +>foo : Symbol(InterfaceProps.foo, Decl(foo.tsx, 3, 26)) + +function Foo() { +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) +>T : Symbol(T, Decl(foo.tsx, 5, 13)) + + return null; +} + +<> + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) +>TypeProps : Symbol(TypeProps, Decl(foo.tsx, 0, 32)) + + /> +>Foo : Symbol(Foo, Decl(foo.tsx, 3, 43)) +>InterfaceProps : Symbol(InterfaceProps, Decl(foo.tsx, 2, 36)) + + diff --git a/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.types b/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.types new file mode 100644 index 0000000000000..c41a8b7152b18 --- /dev/null +++ b/tests/baselines/reference/tsxTypeArgumentsJsxPreserveOutput.types @@ -0,0 +1,63 @@ +=== tests/cases/conformance/jsx/foo.tsx === +import React = require('react'); +>React : typeof React + +type TypeProps = { foo?: boolean; }; +>TypeProps : TypeProps +>foo : boolean + +interface InterfaceProps { foo?: boolean; } +>foo : boolean + +function Foo() { +>Foo : () => any + + return null; +>null : null +} + +<> +><> /> /> /> /> /> /> /> /> /> /> : JSX.Element + + /> +> /> : JSX.Element +>Foo : () => any + + /> +> /> : JSX.Element +>Foo : () => any + + /> +> /> : JSX.Element +>Foo : () => any + + /> +> /> : JSX.Element +>Foo : () => any + + /> +> /> : JSX.Element +>Foo : () => any +>null : null + + /> +> /> : JSX.Element +>Foo : () => any + + /> +> /> : JSX.Element +>Foo : () => any + + /> +> /> : JSX.Element +>Foo : () => any + + /> +> /> : JSX.Element +>Foo : () => any + + /> +> /> : JSX.Element +>Foo : () => any + + diff --git a/tests/cases/conformance/jsx/tsxTypeArgumentsJsxPreserveOutput.tsx b/tests/cases/conformance/jsx/tsxTypeArgumentsJsxPreserveOutput.tsx new file mode 100644 index 0000000000000..8969b3124e357 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxTypeArgumentsJsxPreserveOutput.tsx @@ -0,0 +1,27 @@ +// @filename: foo.tsx +// @jsx: preserve +// @noLib: true +// @skipLibCheck: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +type TypeProps = { foo?: boolean; }; +interface InterfaceProps { foo?: boolean; } + +function Foo() { + return null; +} + +<> + /> + /> + /> + /> + /> + /> + /> + /> + /> + /> + \ No newline at end of file