Merge branch 'rwyborn-react-factory-option'

This commit is contained in:
Mohamed Hegazy 2016-01-07 15:01:31 -08:00
commit 26d0fd0bdb
22 changed files with 266 additions and 11 deletions

View file

@ -8360,10 +8360,11 @@ namespace ts {
checkGrammarJsxElement(node);
checkJsxPreconditions(node);
// The symbol 'React' should be marked as 'used' so we don't incorrectly elide its import. And if there
// is no 'React' symbol in scope when targeting React emit, we should issue an error.
// The reactNamespace symbol should be marked as 'used' so we don't incorrectly elide its import. And if there
// is no reactNamespace symbol in scope when targeting React emit, we should issue an error.
const reactRefErr = compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined;
const reactSym = resolveName(node.tagName, "React", SymbolFlags.Value, reactRefErr, "React");
const reactNamespace = compilerOptions.reactNamespace ? compilerOptions.reactNamespace : "React";
const reactSym = resolveName(node.tagName, reactNamespace, SymbolFlags.Value, reactRefErr, reactNamespace);
if (reactSym) {
getSymbolLinks(reactSym).referenced = true;
}

View file

@ -54,6 +54,11 @@ namespace ts {
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,
error: Diagnostics.Argument_for_jsx_must_be_preserve_or_react
},
{
name: "reactNamespace",
type: "string",
description: Diagnostics.Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit
},
{
name: "listFiles",
type: "boolean",

View file

@ -2123,6 +2123,10 @@
"category": "Error",
"code": 5058
},
"Invalide value for '--reactNamespace'. '{0}' is not a valid identifier.": {
"category": "Error",
"code": 5059
},
"Concatenate and emit output to single file.": {
"category": "Message",
@ -2393,6 +2397,10 @@
"category": "Message",
"code": 6083
},
"Specifies the object invoked for createElement and __spread when targeting 'react' JSX emit": {
"category": "Message",
"code": 6084
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",

View file

@ -1186,7 +1186,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitJsxElement(openingNode: JsxOpeningLikeElement, children?: JsxChild[]) {
const syntheticReactRef = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
syntheticReactRef.text = "React";
syntheticReactRef.text = compilerOptions.reactNamespace ? compilerOptions.reactNamespace : "React";
syntheticReactRef.parent = openingNode;
// Call React.createElement(tag, ...

View file

@ -1305,6 +1305,10 @@ namespace ts {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"));
}
if (options.reactNamespace && !isIdentifier(options.reactNamespace, languageVersion)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Invalide_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace));
}
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
if (!options.noEmit) {
const emitHost = getEmitHost();

View file

@ -688,6 +688,21 @@ namespace ts {
ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion);
}
/* @internal */
export function isIdentifier(name: string, languageVersion: ScriptTarget): boolean {
if (!isIdentifierStart(name.charCodeAt(0), languageVersion)) {
return false;
}
for (let i = 1, n = name.length; i < n; i++) {
if (!isIdentifierPart(name.charCodeAt(i), languageVersion)) {
return false;
}
}
return true;
}
// Creates a scanner over a (possibly unspecified) range of a piece of text.
export function createScanner(languageVersion: ScriptTarget,
skipTrivia: boolean,

View file

@ -2382,6 +2382,7 @@ namespace ts {
inlineSourceMap?: boolean;
inlineSources?: boolean;
jsx?: JsxEmit;
reactNamespace?: string;
listFiles?: boolean;
locale?: string;
mapRoot?: string;

View file

@ -2979,15 +2979,9 @@ namespace ts {
// e.g "b a" is valid quoted name but when we strip off the quotes, it is invalid.
// We, thus, need to check if whatever was inside the quotes is actually a valid identifier name.
if (performCharacterChecks) {
if (!isIdentifierStart(name.charCodeAt(0), target)) {
if (!isIdentifier(name, target)) {
return undefined;
}
for (let i = 1, n = name.length; i < n; i++) {
if (!isIdentifierPart(name.charCodeAt(i), target)) {
return undefined;
}
}
}
return name;

View file

@ -0,0 +1,20 @@
//// [tests/cases/compiler/reactNamespaceImportPresevation.tsx] ////
//// [modules.d.ts]
declare module "my-React-Lib" {
var a: any;
export = a;
}
//// [test.tsx]
import * as myReactLib from "my-React-Lib"; // should not be elided
declare var foo: any;
<foo data/>;
//// [test.jsx]
"use strict";
var myReactLib = require("my-React-Lib"); // should not be elided
<foo data/>;

View file

@ -0,0 +1,20 @@
=== tests/cases/compiler/modules.d.ts ===
declare module "my-React-Lib" {
var a: any;
>a : Symbol(a, Decl(modules.d.ts, 2, 7))
export = a;
>a : Symbol(a, Decl(modules.d.ts, 2, 7))
}
=== tests/cases/compiler/test.tsx ===
import * as myReactLib from "my-React-Lib"; // should not be elided
>myReactLib : Symbol(myReactLib, Decl(test.tsx, 0, 6))
declare var foo: any;
>foo : Symbol(foo, Decl(test.tsx, 1, 11))
<foo data/>;
>data : Symbol(unknown)

View file

@ -0,0 +1,22 @@
=== tests/cases/compiler/modules.d.ts ===
declare module "my-React-Lib" {
var a: any;
>a : any
export = a;
>a : any
}
=== tests/cases/compiler/test.tsx ===
import * as myReactLib from "my-React-Lib"; // should not be elided
>myReactLib : any
declare var foo: any;
>foo : any
<foo data/>;
><foo data/> : any
>foo : any
>data : any

View file

@ -0,0 +1,11 @@
error TS5059: Invalide value for '--reactNamespace'. 'my-React-Lib' is not a valid identifier.
tests/cases/compiler/reactNamespaceInvalidInput.tsx(2,2): error TS2304: Cannot find name 'my-React-Lib'.
!!! error TS5059: Invalide value for '--reactNamespace'. 'my-React-Lib' is not a valid identifier.
==== tests/cases/compiler/reactNamespaceInvalidInput.tsx (1 errors) ====
<foo data/>;
~~~
!!! error TS2304: Cannot find name 'my-React-Lib'.

View file

@ -0,0 +1,7 @@
//// [reactNamespaceInvalidInput.tsx]
<foo data/>;
//// [reactNamespaceInvalidInput.js]
my-React-Lib.createElement("foo", {data: true});

View file

@ -0,0 +1,20 @@
//// [reactNamespaceJSXEmit.tsx]
declare var myReactLib: any;
declare var foo: any;
declare var Bar: any;
declare var x: any;
<foo data/>;
<Bar x={x} />;
<x-component />;
<Bar {...x} />;
<Bar { ...x } y={2} />;
//// [reactNamespaceJSXEmit.js]
myReactLib.createElement("foo", {data: true});
myReactLib.createElement(Bar, {x: x});
myReactLib.createElement("x-component", null);
myReactLib.createElement(Bar, myReactLib.__spread({}, x));
myReactLib.createElement(Bar, myReactLib.__spread({}, x, {y: 2}));

View file

@ -0,0 +1,32 @@
=== tests/cases/compiler/reactNamespaceJSXEmit.tsx ===
declare var myReactLib: any;
>myReactLib : Symbol(myReactLib, Decl(reactNamespaceJSXEmit.tsx, 1, 11))
declare var foo: any;
>foo : Symbol(foo, Decl(reactNamespaceJSXEmit.tsx, 2, 11))
declare var Bar: any;
>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11))
declare var x: any;
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))
<foo data/>;
>data : Symbol(unknown)
<Bar x={x} />;
>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11))
>x : Symbol(unknown)
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))
<x-component />;
<Bar {...x} />;
>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11))
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))
<Bar { ...x } y={2} />;
>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11))
>x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11))
>y : Symbol(unknown)

View file

@ -0,0 +1,41 @@
=== tests/cases/compiler/reactNamespaceJSXEmit.tsx ===
declare var myReactLib: any;
>myReactLib : any
declare var foo: any;
>foo : any
declare var Bar: any;
>Bar : any
declare var x: any;
>x : any
<foo data/>;
><foo data/> : any
>foo : any
>data : any
<Bar x={x} />;
><Bar x={x} /> : any
>Bar : any
>x : any
>x : any
<x-component />;
><x-component /> : any
>x-component : any
<Bar {...x} />;
><Bar {...x} /> : any
>Bar : any
>x : any
<Bar { ...x } y={2} />;
><Bar { ...x } y={2} /> : any
>Bar : any
>x : any
>y : any
>2 : number

View file

@ -0,0 +1,9 @@
tests/cases/compiler/reactNamespaceMissingDeclaration.tsx(3,2): error TS2304: Cannot find name 'myReactLib'.
==== tests/cases/compiler/reactNamespaceMissingDeclaration.tsx (1 errors) ====
// Error myReactLib not declared
<foo data/>
~~~
!!! error TS2304: Cannot find name 'myReactLib'.

View file

@ -0,0 +1,8 @@
//// [reactNamespaceMissingDeclaration.tsx]
// Error myReactLib not declared
<foo data/>
//// [reactNamespaceMissingDeclaration.js]
// Error myReactLib not declared
myReactLib.createElement("foo", {data: true});

View file

@ -0,0 +1,15 @@
//@jsx: preserve
//@module: commonjs
//@reactNamespace: myReactLib
//@filename: modules.d.ts
declare module "my-React-Lib" {
var a: any;
export = a;
}
//@filename: test.tsx
import * as myReactLib from "my-React-Lib"; // should not be elided
declare var foo: any;
<foo data/>;

View file

@ -0,0 +1,4 @@
//@jsx: react
//@reactNamespace: my-React-Lib
<foo data/>;

View file

@ -0,0 +1,13 @@
//@jsx: react
//@reactNamespace: myReactLib
declare var myReactLib: any;
declare var foo: any;
declare var Bar: any;
declare var x: any;
<foo data/>;
<Bar x={x} />;
<x-component />;
<Bar {...x} />;
<Bar { ...x } y={2} />;

View file

@ -0,0 +1,5 @@
//@jsx: react
//@reactNamespace: myReactLib
// Error myReactLib not declared
<foo data/>