fix(44021): reference jsx pragma when JsxFragment is used (#45894)

This commit is contained in:
Hiroshi Ogawa 2021-09-30 03:31:59 +09:00 committed by GitHub
parent 5d0d7ae85d
commit 061f02cd64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 426 additions and 20 deletions

View file

@ -1036,17 +1036,9 @@ namespace ts {
}
}
else {
if (file.localJsxNamespace) {
return file.localJsxNamespace;
}
const jsxPragma = file.pragmas.get("jsx");
if (jsxPragma) {
const chosenPragma = isArray(jsxPragma) ? jsxPragma[0] : jsxPragma;
file.localJsxFactory = parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion);
visitNode(file.localJsxFactory, markAsSynthetic);
if (file.localJsxFactory) {
return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText;
}
const localJsxNamespace = getLocalJsxNamespace(file);
if (localJsxNamespace) {
return file.localJsxNamespace = localJsxNamespace;
}
}
}
@ -1068,11 +1060,26 @@ namespace ts {
_jsxFactoryEntity = factory.createQualifiedName(factory.createIdentifier(unescapeLeadingUnderscores(_jsxNamespace)), "createElement");
}
return _jsxNamespace;
}
function markAsSynthetic(node: Node): VisitResult<Node> {
setTextRangePosEnd(node, -1, -1);
return visitEachChild(node, markAsSynthetic, nullTransformationContext);
function getLocalJsxNamespace(file: SourceFile): __String | undefined {
if (file.localJsxNamespace) {
return file.localJsxNamespace;
}
const jsxPragma = file.pragmas.get("jsx");
if (jsxPragma) {
const chosenPragma = isArray(jsxPragma) ? jsxPragma[0] : jsxPragma;
file.localJsxFactory = parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion);
visitNode(file.localJsxFactory, markAsSynthetic);
if (file.localJsxFactory) {
return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText;
}
}
}
function markAsSynthetic(node: Node): VisitResult<Node> {
setTextRangePosEnd(node, -1, -1);
return visitEachChild(node, markAsSynthetic, nullTransformationContext);
}
function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) {
@ -27598,6 +27605,15 @@ namespace ts {
markAliasSymbolAsReferenced(jsxFactorySym);
}
}
// For JsxFragment, mark jsx pragma as referenced via resolveName
if (isJsxOpeningFragment(node)) {
const file = getSourceFileOfNode(node);
const localJsxNamespace = getLocalJsxNamespace(file);
if (localJsxNamespace) {
resolveName(jsxFactoryLocation, localJsxNamespace, SymbolFlags.Value, jsxFactoryRefErr, localJsxNamespace, /*isUse*/ true);
}
}
}
if (isNodeOpeningLikeElement) {

View file

@ -0,0 +1,87 @@
tests/cases/conformance/jsx/inline/preacty-no-fragment.tsx(5,12): error TS6133: 'Fragment' is declared but its value is never read.
tests/cases/conformance/jsx/inline/preacty-only-fragment-no-jsx.tsx(6,1): error TS2304: Cannot find name 'h'.
tests/cases/conformance/jsx/inline/snabbdomy-only-fragment-no-jsx.tsx(4,1): error TS2304: Cannot find name 'jsx'.
==== tests/cases/conformance/jsx/inline/renderer.d.ts (0 errors) ====
declare global {
namespace JSX {
interface IntrinsicElements {
[e: string]: any;
}
}
}
export function h(): void;
export function jsx(): void;
export function Fragment(): void;
==== tests/cases/conformance/jsx/inline/preacty.tsx (0 errors) ====
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
<><div></div></>
==== tests/cases/conformance/jsx/inline/snabbdomy.tsx (0 errors) ====
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<><span></span></>
==== tests/cases/conformance/jsx/inline/preacty-only-fragment.tsx (0 errors) ====
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
<></>
==== tests/cases/conformance/jsx/inline/snabbdomy-only-fragment.tsx (0 errors) ====
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<></>
==== tests/cases/conformance/jsx/inline/preacty-only-fragment-no-jsx.tsx (1 errors) ====
/**
* @jsx h
* @jsxFrag Fragment
*/
import {Fragment} from "./renderer";
<></>
~~
!!! error TS2304: Cannot find name 'h'.
==== tests/cases/conformance/jsx/inline/snabbdomy-only-fragment-no-jsx.tsx (1 errors) ====
/* @jsx jsx */
/* @jsxfrag null */
import {} from "./renderer";
<></>
~~
!!! error TS2304: Cannot find name 'jsx'.
==== tests/cases/conformance/jsx/inline/preacty-no-fragment.tsx (1 errors) ====
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
~~~~~~~~
!!! error TS6133: 'Fragment' is declared but its value is never read.
<div></div>
==== tests/cases/conformance/jsx/inline/snabbdomy-no-fragment.tsx (0 errors) ====
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<div></div>
==== tests/cases/conformance/jsx/inline/preacty-only-component.tsx (0 errors) ====
/**
* @jsx h
*/
import {h} from "./renderer";
function Component() { return null; }
<Component />

View file

@ -24,7 +24,58 @@ import {h, Fragment} from "./renderer";
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<><span></span></>
<><span></span></>
//// [preacty-only-fragment.tsx]
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
<></>
//// [snabbdomy-only-fragment.tsx]
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<></>
//// [preacty-only-fragment-no-jsx.tsx]
/**
* @jsx h
* @jsxFrag Fragment
*/
import {Fragment} from "./renderer";
<></>
//// [snabbdomy-only-fragment-no-jsx.tsx]
/* @jsx jsx */
/* @jsxfrag null */
import {} from "./renderer";
<></>
//// [preacty-no-fragment.tsx]
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
<div></div>
//// [snabbdomy-no-fragment.tsx]
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<div></div>
//// [preacty-only-component.tsx]
/**
* @jsx h
*/
import {h} from "./renderer";
function Component() { return null; }
<Component />
//// [preacty.js]
"use strict";
@ -44,3 +95,54 @@ exports.__esModule = true;
var renderer_1 = require("./renderer");
(0, renderer_1.jsx)(null, null,
(0, renderer_1.jsx)("span", null));
//// [preacty-only-fragment.js]
"use strict";
exports.__esModule = true;
/**
* @jsx h
* @jsxFrag Fragment
*/
var renderer_1 = require("./renderer");
(0, renderer_1.h)(renderer_1.Fragment, null);
//// [snabbdomy-only-fragment.js]
"use strict";
exports.__esModule = true;
(0, renderer_1.jsx)(null, null);
//// [preacty-only-fragment-no-jsx.js]
"use strict";
exports.__esModule = true;
/**
* @jsx h
* @jsxFrag Fragment
*/
var renderer_1 = require("./renderer");
h(renderer_1.Fragment, null);
//// [snabbdomy-only-fragment-no-jsx.js]
"use strict";
exports.__esModule = true;
jsx(null, null);
//// [preacty-no-fragment.js]
"use strict";
exports.__esModule = true;
/**
* @jsx h
* @jsxFrag Fragment
*/
var renderer_1 = require("./renderer");
(0, renderer_1.h)("div", null);
//// [snabbdomy-no-fragment.js]
"use strict";
exports.__esModule = true;
/* @jsx jsx */
/* @jsxfrag null */
var renderer_1 = require("./renderer");
(0, renderer_1.jsx)("div", null);
//// [preacty-only-component.js]
"use strict";
exports.__esModule = true;
/**
* @jsx h
*/
var renderer_1 = require("./renderer");
function Component() { return null; }
(0, renderer_1.h)(Component, null);

View file

@ -45,3 +45,74 @@ import {jsx} from "./renderer";
>span : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
>span : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
=== tests/cases/conformance/jsx/inline/preacty-only-fragment.tsx ===
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
>h : Symbol(h, Decl(preacty-only-fragment.tsx, 4, 8))
>Fragment : Symbol(Fragment, Decl(preacty-only-fragment.tsx, 4, 10))
<></>
=== tests/cases/conformance/jsx/inline/snabbdomy-only-fragment.tsx ===
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
>jsx : Symbol(jsx, Decl(snabbdomy-only-fragment.tsx, 2, 8))
<></>
=== tests/cases/conformance/jsx/inline/preacty-only-fragment-no-jsx.tsx ===
/**
* @jsx h
* @jsxFrag Fragment
*/
import {Fragment} from "./renderer";
>Fragment : Symbol(Fragment, Decl(preacty-only-fragment-no-jsx.tsx, 4, 8))
<></>
=== tests/cases/conformance/jsx/inline/snabbdomy-only-fragment-no-jsx.tsx ===
/* @jsx jsx */
No type information for this code./* @jsxfrag null */
No type information for this code.import {} from "./renderer";
No type information for this code.<></>
No type information for this code.
No type information for this code.=== tests/cases/conformance/jsx/inline/preacty-no-fragment.tsx ===
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
>h : Symbol(h, Decl(preacty-no-fragment.tsx, 4, 8))
>Fragment : Symbol(Fragment, Decl(preacty-no-fragment.tsx, 4, 10))
<div></div>
>div : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
>div : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
=== tests/cases/conformance/jsx/inline/snabbdomy-no-fragment.tsx ===
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
>jsx : Symbol(jsx, Decl(snabbdomy-no-fragment.tsx, 2, 8))
<div></div>
>div : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
>div : Symbol(JSX.IntrinsicElements, Decl(renderer.d.ts, 1, 19))
=== tests/cases/conformance/jsx/inline/preacty-only-component.tsx ===
/**
* @jsx h
*/
import {h} from "./renderer";
>h : Symbol(h, Decl(preacty-only-component.tsx, 3, 8))
function Component() { return null; }
>Component : Symbol(Component, Decl(preacty-only-component.tsx, 3, 29))
<Component />
>Component : Symbol(Component, Decl(preacty-only-component.tsx, 3, 29))

View file

@ -28,8 +28,8 @@ import {h, Fragment} from "./renderer";
>Fragment : () => void
<><div></div></>
><><div></div></> : error
><div></div> : error
><><div></div></> : any
><div></div> : any
>div : any
>div : any
@ -40,8 +40,87 @@ import {jsx} from "./renderer";
>jsx : () => void
<><span></span></>
><><span></span></> : error
><span></span> : error
><><span></span></> : any
><span></span> : any
>span : any
>span : any
=== tests/cases/conformance/jsx/inline/preacty-only-fragment.tsx ===
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
>h : () => void
>Fragment : () => void
<></>
><></> : any
=== tests/cases/conformance/jsx/inline/snabbdomy-only-fragment.tsx ===
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
>jsx : () => void
<></>
><></> : any
=== tests/cases/conformance/jsx/inline/preacty-only-fragment-no-jsx.tsx ===
/**
* @jsx h
* @jsxFrag Fragment
*/
import {Fragment} from "./renderer";
>Fragment : () => void
<></>
><></> : any
=== tests/cases/conformance/jsx/inline/snabbdomy-only-fragment-no-jsx.tsx ===
/* @jsx jsx */
/* @jsxfrag null */
import {} from "./renderer";
<></>
><></> : any
=== tests/cases/conformance/jsx/inline/preacty-no-fragment.tsx ===
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
>h : () => void
>Fragment : () => void
<div></div>
><div></div> : any
>div : any
>div : any
=== tests/cases/conformance/jsx/inline/snabbdomy-no-fragment.tsx ===
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
>jsx : () => void
<div></div>
><div></div> : any
>div : any
>div : any
=== tests/cases/conformance/jsx/inline/preacty-only-component.tsx ===
/**
* @jsx h
*/
import {h} from "./renderer";
>h : () => void
function Component() { return null; }
>Component : () => any
>null : null
<Component />
><Component /> : any
>Component : () => any

View file

@ -1,4 +1,5 @@
// @jsx: react
// @noUnusedLocals: true
// @filename: renderer.d.ts
declare global {
namespace JSX {
@ -23,4 +24,54 @@ import {h, Fragment} from "./renderer";
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<><span></span></>
<><span></span></>
// @filename: preacty-only-fragment.tsx
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
<></>
// @filename: snabbdomy-only-fragment.tsx
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<></>
// @filename: preacty-only-fragment-no-jsx.tsx
/**
* @jsx h
* @jsxFrag Fragment
*/
import {Fragment} from "./renderer";
<></>
// @filename: snabbdomy-only-fragment-no-jsx.tsx
/* @jsx jsx */
/* @jsxfrag null */
import {} from "./renderer";
<></>
// @filename: preacty-no-fragment.tsx
/**
* @jsx h
* @jsxFrag Fragment
*/
import {h, Fragment} from "./renderer";
<div></div>
// @filename: snabbdomy-no-fragment.tsx
/* @jsx jsx */
/* @jsxfrag null */
import {jsx} from "./renderer";
<div></div>
// @filename: preacty-only-component.tsx
/**
* @jsx h
*/
import {h} from "./renderer";
function Component() { return null; }
<Component />