Skip to content

Commit 4b8a557

Browse files
committed
Add support for taking in jsxFactory option and report errors for invalid combinations
1 parent 28cc938 commit 4b8a557

File tree

7 files changed

+204
-1
lines changed

7 files changed

+204
-1
lines changed

src/compiler/commandLineParser.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ namespace ts {
7777
type: "string",
7878
description: Diagnostics.Specify_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit
7979
},
80+
{
81+
name: "jsxFactory",
82+
type: "string",
83+
description: Diagnostics.Specify_the_JSX_factory_function_to_use_when_targeting_react_JSX_emit_e_g_React_createElement_or_h
84+
},
8085
{
8186
name: "listFiles",
8287
type: "boolean",

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,6 +2897,10 @@
28972897
"category": "Message",
28982898
"code": 6145
28992899
},
2900+
"Specify the JSX factory function to use when targeting 'react' JSX emit, e.g. 'React.createElement' or 'h'.": {
2901+
"category": "Message",
2902+
"code": 6146
2903+
},
29002904
"Variable '{0}' implicitly has an '{1}' type.": {
29012905
"category": "Error",
29022906
"code": 7005

src/compiler/program.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,12 @@ namespace ts {
16701670
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"));
16711671
}
16721672

1673-
if (options.reactNamespace && !isIdentifierText(options.reactNamespace, languageVersion)) {
1673+
if (options.jsxFactory) {
1674+
if (options.reactNamespace) {
1675+
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory"));
1676+
}
1677+
}
1678+
else if (options.reactNamespace && !isIdentifierText(options.reactNamespace, languageVersion)) {
16741679
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace));
16751680
}
16761681

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3081,6 +3081,7 @@ namespace ts {
30813081
project?: string;
30823082
/* @internal */ pretty?: DiagnosticStyle;
30833083
reactNamespace?: string;
3084+
jsxFactory?: string;
30843085
removeComments?: boolean;
30853086
rootDir?: string;
30863087
rootDirs?: string[];
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
error TS5053: Option 'reactNamespace' cannot be specified with option 'jsxFactory'.
2+
3+
4+
!!! error TS5053: Option 'reactNamespace' cannot be specified with option 'jsxFactory'.
5+
==== tests/cases/compiler/Element.ts (0 errors) ====
6+
7+
declare namespace JSX {
8+
interface Element {
9+
name: string;
10+
isIntrinsic: boolean;
11+
isCustomElement: boolean;
12+
toString(renderId?: number): string;
13+
bindDOM(renderId?: number): number;
14+
resetComponent(): void;
15+
instantiateComponents(renderId?: number): number;
16+
props: any;
17+
}
18+
}
19+
export namespace Element {
20+
export function isElement(el: any): el is JSX.Element {
21+
return el.markAsChildOfRootElement !== undefined;
22+
}
23+
24+
export function createElement(args: any[]) {
25+
26+
return {
27+
}
28+
}
29+
}
30+
31+
export let createElement = Element.createElement;
32+
33+
function toCamelCase(text: string): string {
34+
return text[0].toLowerCase() + text.substring(1);
35+
}
36+
37+
==== tests/cases/compiler/test.tsx (0 errors) ====
38+
import { Element} from './Element';
39+
40+
let c: {
41+
a?: {
42+
b: string
43+
}
44+
};
45+
46+
class A {
47+
view() {
48+
return [
49+
<meta content="helloworld"></meta>,
50+
<meta content={c.a!.b}></meta>
51+
];
52+
}
53+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//// [tests/cases/compiler/jsxFactoryAndReactNamespace.ts] ////
2+
3+
//// [Element.ts]
4+
5+
declare namespace JSX {
6+
interface Element {
7+
name: string;
8+
isIntrinsic: boolean;
9+
isCustomElement: boolean;
10+
toString(renderId?: number): string;
11+
bindDOM(renderId?: number): number;
12+
resetComponent(): void;
13+
instantiateComponents(renderId?: number): number;
14+
props: any;
15+
}
16+
}
17+
export namespace Element {
18+
export function isElement(el: any): el is JSX.Element {
19+
return el.markAsChildOfRootElement !== undefined;
20+
}
21+
22+
export function createElement(args: any[]) {
23+
24+
return {
25+
}
26+
}
27+
}
28+
29+
export let createElement = Element.createElement;
30+
31+
function toCamelCase(text: string): string {
32+
return text[0].toLowerCase() + text.substring(1);
33+
}
34+
35+
//// [test.tsx]
36+
import { Element} from './Element';
37+
38+
let c: {
39+
a?: {
40+
b: string
41+
}
42+
};
43+
44+
class A {
45+
view() {
46+
return [
47+
<meta content="helloworld"></meta>,
48+
<meta content={c.a!.b}></meta>
49+
];
50+
}
51+
}
52+
53+
//// [Element.js]
54+
"use strict";
55+
var Element;
56+
(function (Element) {
57+
function isElement(el) {
58+
return el.markAsChildOfRootElement !== undefined;
59+
}
60+
Element.isElement = isElement;
61+
function createElement(args) {
62+
return {};
63+
}
64+
Element.createElement = createElement;
65+
})(Element = exports.Element || (exports.Element = {}));
66+
exports.createElement = Element.createElement;
67+
function toCamelCase(text) {
68+
return text[0].toLowerCase() + text.substring(1);
69+
}
70+
//// [test.js]
71+
"use strict";
72+
const Element_1 = require("./Element");
73+
let c;
74+
class A {
75+
view() {
76+
return [
77+
Element_1.Element.createElement("meta", { content: "helloworld" }),
78+
Element_1.Element.createElement("meta", { content: c.a.b })
79+
];
80+
}
81+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//@jsx: react
2+
//@target: es6
3+
//@module: commonjs
4+
//@reactNamespace: Element
5+
//@jsxFactory: Element.createElement
6+
7+
// @filename: Element.ts
8+
declare namespace JSX {
9+
interface Element {
10+
name: string;
11+
isIntrinsic: boolean;
12+
isCustomElement: boolean;
13+
toString(renderId?: number): string;
14+
bindDOM(renderId?: number): number;
15+
resetComponent(): void;
16+
instantiateComponents(renderId?: number): number;
17+
props: any;
18+
}
19+
}
20+
export namespace Element {
21+
export function isElement(el: any): el is JSX.Element {
22+
return el.markAsChildOfRootElement !== undefined;
23+
}
24+
25+
export function createElement(args: any[]) {
26+
27+
return {
28+
}
29+
}
30+
}
31+
32+
export let createElement = Element.createElement;
33+
34+
function toCamelCase(text: string): string {
35+
return text[0].toLowerCase() + text.substring(1);
36+
}
37+
38+
// @filename: test.tsx
39+
import { Element} from './Element';
40+
41+
let c: {
42+
a?: {
43+
b: string
44+
}
45+
};
46+
47+
class A {
48+
view() {
49+
return [
50+
<meta content="helloworld"></meta>,
51+
<meta content={c.a!.b}></meta>
52+
];
53+
}
54+
}

0 commit comments

Comments
 (0)