fix(44021): reference jsx pragma when JsxFragment is used (#45894)
This commit is contained in:
parent
5d0d7ae85d
commit
061f02cd64
|
@ -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) {
|
||||
|
|
|
@ -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 />
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 />
|
||||
|
|
Loading…
Reference in a new issue