Skip to content

Commit

Permalink
Add emit support for jsx/jsxs experimental jsx runtime api
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham committed Jun 22, 2020
1 parent 0ae5cb6 commit 330af8d
Show file tree
Hide file tree
Showing 42 changed files with 885 additions and 21 deletions.
5 changes: 4 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23769,7 +23769,7 @@ namespace ts {
// by default, jsx:'react' will use jsxFactory = React.createElement and jsxFragmentFactory = React.Fragment
// if jsxFactory compiler option is provided, ensure jsxFragmentFactory compiler option or @jsxFrag pragma is provided too
const nodeSourceFile = getSourceFileOfNode(node);
if (compilerOptions.jsx === JsxEmit.React && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx"))
if (getJSXTransformEnabled(compilerOptions) && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx"))
&& !compilerOptions.jsxFragmentFactory && !nodeSourceFile.pragmas.has("jsxfrag")) {
error(node, compilerOptions.jsxFactory
? Diagnostics.The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option
Expand Down Expand Up @@ -36360,6 +36360,9 @@ namespace ts {
// When resolved as an expression identifier, if the given node references an import, return the declaration of
// that import. Otherwise, return undefined.
function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined {
if (nodeIn.generatedImportReference) {
return nodeIn.generatedImportReference;
}
const node = getParseTreeNode(nodeIn, isIdentifier);
if (node) {
const symbol = getReferencedValueSymbol(node);
Expand Down
23 changes: 18 additions & 5 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ namespace ts {
/* @internal */
export const compileOnSaveCommandLineOption: CommandLineOption = { name: "compileOnSave", type: "boolean" };

const jsxOptionMap = createMapFromTemplate({
"preserve": JsxEmit.Preserve,
"react-native": JsxEmit.ReactNative,
"react": JsxEmit.React,
"react-jsx": JsxEmit.ReactJSX,
"react-jsxdev": JsxEmit.ReactJSXDev,
});

/* @internal */
export const inverseJsxOptionMap = mapMap(jsxOptionMap, (value, key) => ["" + value, key]);

// NOTE: The order here is important to default lib ordering as entries will have the same
// order in the generated program (see `getDefaultLibPriority` in program.ts). This
// order also affects overload resolution when a type declared in one lib is
Expand Down Expand Up @@ -356,11 +367,7 @@ namespace ts {
},
{
name: "jsx",
type: createMapFromTemplate({
"preserve": JsxEmit.Preserve,
"react-native": JsxEmit.ReactNative,
"react": JsxEmit.React
}),
type: jsxOptionMap,
affectsSourceFile: true,
paramType: Diagnostics.KIND,
showInSimplifiedHelpView: true,
Expand Down Expand Up @@ -771,6 +778,12 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Specify_the_JSX_fragment_factory_function_to_use_when_targeting_react_JSX_emit_with_jsxFactory_compiler_option_is_specified_e_g_Fragment
},
{
name: "jsxImportSource",
type: "string",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Specify_the_module_specifier_to_be_used_to_import_the_jsx_and_jsxs_factory_functions_from_eg_react
},
{
name: "resolveJsonModule",
type: "boolean",
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3542,6 +3542,10 @@
"category": "Error",
"code": 5088
},
"Option '{0}' cannot be specified when option 'jsx' is '{1}'.": {
"category": "Error",
"code": 5089
},

"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
Expand Down Expand Up @@ -4429,6 +4433,10 @@
"category": "Error",
"code": 6234
},
"Specify the module specifier to be used to import the `jsx` and `jsxs` factory functions from. eg, react": {
"category": "Error",
"code": 6235
},

"Projects to reference": {
"category": "Message",
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8763,6 +8763,8 @@ namespace ts {
}
case "jsx":
case "jsxfrag":
case "jsximportsource":
case "jsxruntime":
return; // Accessed directly
default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future?
}
Expand Down
18 changes: 18 additions & 0 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3184,6 +3184,9 @@ namespace ts {
if (options.reactNamespace) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory");
}
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFactory", inverseJsxOptionMap.get("" + options.jsx));
}
if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) {
createOptionValueDiagnostic("jsxFactory", Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory);
}
Expand All @@ -3196,11 +3199,26 @@ namespace ts {
if (!options.jsxFactory) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "jsxFragmentFactory", "jsxFactory");
}
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFragmentFactory", inverseJsxOptionMap.get("" + options.jsx));
}
if (!parseIsolatedEntityName(options.jsxFragmentFactory, languageVersion)) {
createOptionValueDiagnostic("jsxFragmentFactory", Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFragmentFactory);
}
}

if (options.reactNamespace) {
if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "reactNamespace", inverseJsxOptionMap.get("" + options.jsx));
}
}

if (options.jsxImportSource) {
if (options.jsx === JsxEmit.React) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxImportSource", inverseJsxOptionMap.get("" + options.jsx));
}
}

// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
if (!options.noEmit && !options.suppressOutputPathCheck) {
const emitHost = getEmitHost();
Expand Down
3 changes: 1 addition & 2 deletions src/compiler/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ namespace ts {
function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean) {
if (emitOnlyDtsFiles) return emptyArray;

const jsx = compilerOptions.jsx;
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const transformers: TransformerFactory<SourceFile | Bundle>[] = [];
Expand All @@ -47,7 +46,7 @@ namespace ts {
transformers.push(transformTypeScript);
transformers.push(transformClassFields);

if (jsx === JsxEmit.React) {
if (getJSXTransformEnabled(compilerOptions)) {
transformers.push(transformJsx);
}

Expand Down
Loading

0 comments on commit 330af8d

Please sign in to comment.