Merge pull request #3675 from RyanCavanaugh/fix3674

Correctly flag JSX elements as being used for the purposes of module imports
This commit is contained in:
Ryan Cavanaugh 2015-06-30 14:38:06 -07:00
commit 5208bded90
9 changed files with 218 additions and 294 deletions

View File

@ -7088,7 +7088,7 @@ namespace ts {
let jsxElementClassType: Type = undefined;
function getJsxGlobalElementClassType(): Type {
if(!jsxElementClassType) {
if (!jsxElementClassType) {
jsxElementClassType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.ElementClass);
}
return jsxElementClassType;
@ -7107,7 +7107,7 @@ namespace ts {
}
if (jsxElementType === undefined) {
if(compilerOptions.noImplicitAny) {
if (compilerOptions.noImplicitAny) {
error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist);
}
}
@ -7119,6 +7119,15 @@ namespace ts {
let targetAttributesType = getJsxElementAttributesType(node);
if (getNodeLinks(node).jsxFlags & JsxFlags.ClassElement) {
if (node.tagName.kind === SyntaxKind.Identifier) {
checkIdentifier(<Identifier>node.tagName);
}
else {
checkQualifiedName(<QualifiedName>node.tagName);
}
}
let nameTable: Map<boolean> = {};
// Process this array in right-to-left order so we know which
// attributes (mostly from spreads) are being overwritten and
@ -7131,7 +7140,7 @@ namespace ts {
else {
Debug.assert(node.attributes[i].kind === SyntaxKind.JsxSpreadAttribute);
let spreadType = checkJsxSpreadAttribute(<JsxSpreadAttribute>(node.attributes[i]), targetAttributesType, nameTable);
if(isTypeAny(spreadType)) {
if (isTypeAny(spreadType)) {
sawSpreadedAny = true;
}
}
@ -12336,7 +12345,7 @@ namespace ts {
}
function checkTypePredicate(node: TypePredicateNode) {
if(!isInLegalTypePredicatePosition(node)) {
if (!isInLegalTypePredicatePosition(node)) {
error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
}
}

View File

@ -1,92 +0,0 @@
=== tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx ===
declare var React: any;
>React : Symbol(React, Decl(jsxEsprimaFbTestSuite.tsx, 0, 11))
declare var 日本語;
>日本語 : Symbol(日本語, Decl(jsxEsprimaFbTestSuite.tsx, 1, 11))
declare var AbC_def;
>AbC_def : Symbol(AbC_def, Decl(jsxEsprimaFbTestSuite.tsx, 2, 11))
declare var LeftRight;
>LeftRight : Symbol(LeftRight, Decl(jsxEsprimaFbTestSuite.tsx, 3, 11))
declare var x;
>x : Symbol(x, Decl(jsxEsprimaFbTestSuite.tsx, 4, 11))
declare var a;
>a : Symbol(a, Decl(jsxEsprimaFbTestSuite.tsx, 5, 11))
declare var props;
>props : Symbol(props, Decl(jsxEsprimaFbTestSuite.tsx, 6, 11))
<a />;
//<n:a n:v />; Namespace unsuported
//<a n:foo="bar"> {value} <b><c /></b></a>; Namespace unsuported
<a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;" />;
>b : Symbol(unknown)
>c : Symbol(unknown)
>d : Symbol(unknown)
>e : Symbol(unknown)
>f : Symbol(unknown)
>g : Symbol(unknown)
>h : Symbol(unknown)
<a b="&notanentity;" />;
>b : Symbol(unknown)
<a
/>;
<日本語></日本語>;
<AbC_def
>AbC_def : Symbol(AbC_def, Decl(jsxEsprimaFbTestSuite.tsx, 2, 11))
test="&#x0026;&#38;">
>test : Symbol(unknown)
bar
baz
</AbC_def>;
<a b={x ? <c /> : <d />} />;
>b : Symbol(unknown)
>x : Symbol(x, Decl(jsxEsprimaFbTestSuite.tsx, 4, 11))
<a>{}</a>;
<a>{/* this is a comment */}</a>;
<div>@test content</div>;
<div><br />7x invalid-js-identifier</div>;
<LeftRight left=<a /> right=<b>monkeys /> gorillas</b> />;
>LeftRight : Symbol(LeftRight, Decl(jsxEsprimaFbTestSuite.tsx, 3, 11))
>left : Symbol(unknown)
>right : Symbol(unknown)
<a.b></a.b>;
>b : Symbol(unknown)
<a.b.c></a.b.c>;
>c : Symbol(unknown)
(<div />) < x;
>x : Symbol(x, Decl(jsxEsprimaFbTestSuite.tsx, 4, 11))
<div {...props} />;
<div {...props} post="attribute" />;
>post : Symbol(unknown)
<div pre="leading" pre2="attribute" {...props}></div>;
>pre : Symbol(unknown)
>pre2 : Symbol(unknown)
<a> </a>;

View File

@ -1,160 +0,0 @@
=== tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx ===
declare var React: any;
>React : any
declare var 日本語;
>日本語 : any
declare var AbC_def;
>AbC_def : any
declare var LeftRight;
>LeftRight : any
declare var x;
>x : any
declare var a;
>a : any
declare var props;
>props : any
<a />;
><a /> : any
>a : any
//<n:a n:v />; Namespace unsuported
//<a n:foo="bar"> {value} <b><c /></b></a>; Namespace unsuported
<a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;" />;
><a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;" /> : any
>a : any
>b : any
>c : any
>d : any
>e : any
>f : any
>g : any
>h : any
<a b="&notanentity;" />;
><a b="&notanentity;" /> : any
>a : any
>b : any
<a
><a/> : any
>a : any
/>;
<日本語></日本語>;
><日本語></日本語> : any
>日本語 : any
>日本語 : any
<AbC_def
><AbC_def test="&#x0026;&#38;">barbaz</AbC_def> : any
>AbC_def : any
test="&#x0026;&#38;">
>test : any
bar
baz
</AbC_def>;
>AbC_def : any
<a b={x ? <c /> : <d />} />;
><a b={x ? <c /> : <d />} /> : any
>a : any
>b : any
>x ? <c /> : <d /> : any
>x : any
><c /> : any
>c : any
><d /> : any
>d : any
<a>{}</a>;
><a>{}</a> : any
>a : any
>a : any
<a>{/* this is a comment */}</a>;
><a>{/* this is a comment */}</a> : any
>a : any
>a : any
<div>@test content</div>;
><div>@test content</div> : any
>div : any
>div : any
<div><br />7x invalid-js-identifier</div>;
><div><br />7x invalid-js-identifier</div> : any
>div : any
><br /> : any
>br : any
>div : any
<LeftRight left=<a /> right=<b>monkeys /> gorillas</b> />;
><LeftRight left=<a /> right=<b>monkeys /> gorillas</b> /> : any
>LeftRight : any
>left : any
><a /> : any
>a : any
>right : any
><b>monkeys /> gorillas</b> : any
>b : any
>b : any
<a.b></a.b>;
><a.b></a.b> : any
>a : any
>b : any
>a : any
>b : any
<a.b.c></a.b.c>;
><a.b.c></a.b.c> : any
>a : any
>b : any
>c : any
>a : any
>b : any
>c : any
(<div />) < x;
>(<div />) < x : boolean
>(<div />) : any
><div /> : any
>div : any
>x : any
<div {...props} />;
><div {...props} /> : any
>div : any
>props : any
<div {...props} post="attribute" />;
><div {...props} post="attribute" /> : any
>div : any
>props : any
>post : any
<div pre="leading" pre2="attribute" {...props}></div>;
><div pre="leading" pre2="attribute" {...props}></div> : any
>div : any
>pre : any
>pre2 : any
>props : any
>div : any
<a> </a>;
><a> </a> : any
>a : any
>a : any

View File

@ -1,18 +0,0 @@
=== tests/cases/conformance/jsx/tsxElementResolution16.tsx ===
declare module JSX {
>JSX : Symbol(JSX, Decl(tsxElementResolution16.tsx, 0, 0))
}
interface Obj1 {
>Obj1 : Symbol(Obj1, Decl(tsxElementResolution16.tsx, 1, 1))
new(n: string): {};
>n : Symbol(n, Decl(tsxElementResolution16.tsx, 4, 5))
}
var obj1: Obj1;
>obj1 : Symbol(obj1, Decl(tsxElementResolution16.tsx, 6, 3))
>Obj1 : Symbol(Obj1, Decl(tsxElementResolution16.tsx, 1, 1))
<obj1 x={10} />; // Error (JSX.Element is missing)
>x : Symbol(unknown)

View File

@ -1,20 +0,0 @@
=== tests/cases/conformance/jsx/tsxElementResolution16.tsx ===
declare module JSX {
>JSX : any
}
interface Obj1 {
>Obj1 : Obj1
new(n: string): {};
>n : string
}
var obj1: Obj1;
>obj1 : Obj1
>Obj1 : Obj1
<obj1 x={10} />; // Error (JSX.Element is missing)
><obj1 x={10} /> : any
>obj1 : Obj1
>x : any

View File

@ -0,0 +1,71 @@
//// [tests/cases/conformance/jsx/tsxExternalModuleEmit1.tsx] ////
//// [react.d.ts]
declare module 'react' {
class Component<T, U> { }
}
//// [app.tsx]
import * as React from 'react';
// Should see var button_1 = require('./button') here
import { Button } from './button';
export class App extends React.Component<any, any> {
render() {
return <Button />;
}
}
//// [button.tsx]
import * as React from 'react';
export class Button extends React.Component<any, any> {
render() {
return <button>Some button</button>;
}
}
//// [button.jsx]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var React = require('react');
var Button = (function (_super) {
__extends(Button, _super);
function Button() {
_super.apply(this, arguments);
}
Button.prototype.render = function () {
return <button>Some button</button>;
};
return Button;
})(React.Component);
exports.Button = Button;
//// [app.jsx]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var React = require('react');
// Should see var button_1 = require('./button') here
var button_1 = require('./button');
var App = (function (_super) {
__extends(App, _super);
function App() {
_super.apply(this, arguments);
}
App.prototype.render = function () {
return <button_1.Button />;
};
return App;
})(React.Component);
exports.App = App;

View File

@ -0,0 +1,49 @@
=== tests/cases/conformance/jsx/react.d.ts ===
declare module 'react' {
class Component<T, U> { }
>Component : Symbol(Component, Decl(react.d.ts, 1, 24))
>T : Symbol(T, Decl(react.d.ts, 2, 17))
>U : Symbol(U, Decl(react.d.ts, 2, 19))
}
=== tests/cases/conformance/jsx/app.tsx ===
import * as React from 'react';
>React : Symbol(React, Decl(app.tsx, 0, 6))
// Should see var button_1 = require('./button') here
import { Button } from './button';
>Button : Symbol(Button, Decl(app.tsx, 3, 8))
export class App extends React.Component<any, any> {
>App : Symbol(App, Decl(app.tsx, 3, 34))
>React.Component : Symbol(React.Component, Decl(react.d.ts, 1, 24))
>React : Symbol(React, Decl(app.tsx, 0, 6))
>Component : Symbol(React.Component, Decl(react.d.ts, 1, 24))
render() {
>render : Symbol(render, Decl(app.tsx, 5, 52))
return <Button />;
>Button : Symbol(Button, Decl(app.tsx, 3, 8))
}
}
=== tests/cases/conformance/jsx/button.tsx ===
import * as React from 'react';
>React : Symbol(React, Decl(button.tsx, 0, 6))
export class Button extends React.Component<any, any> {
>Button : Symbol(Button, Decl(button.tsx, 0, 31))
>React.Component : Symbol(React.Component, Decl(react.d.ts, 1, 24))
>React : Symbol(React, Decl(button.tsx, 0, 6))
>Component : Symbol(React.Component, Decl(react.d.ts, 1, 24))
render() {
>render : Symbol(render, Decl(button.tsx, 2, 55))
return <button>Some button</button>;
}
}

View File

@ -0,0 +1,53 @@
=== tests/cases/conformance/jsx/react.d.ts ===
declare module 'react' {
class Component<T, U> { }
>Component : Component<T, U>
>T : T
>U : U
}
=== tests/cases/conformance/jsx/app.tsx ===
import * as React from 'react';
>React : typeof React
// Should see var button_1 = require('./button') here
import { Button } from './button';
>Button : typeof Button
export class App extends React.Component<any, any> {
>App : App
>React.Component : React.Component<any, any>
>React : typeof React
>Component : typeof React.Component
render() {
>render : () => any
return <Button />;
><Button /> : any
>Button : typeof Button
}
}
=== tests/cases/conformance/jsx/button.tsx ===
import * as React from 'react';
>React : typeof React
export class Button extends React.Component<any, any> {
>Button : Button
>React.Component : React.Component<any, any>
>React : typeof React
>Component : typeof React.Component
render() {
>render : () => any
return <button>Some button</button>;
><button>Some button</button> : any
>button : any
>button : any
}
}

View File

@ -0,0 +1,32 @@
//@jsx: preserve
//@module: commonjs
//@filename: react.d.ts
declare module 'react' {
class Component<T, U> { }
}
//@filename: app.tsx
import * as React from 'react';
// Should see var button_1 = require('./button') here
import { Button } from './button';
export class App extends React.Component<any, any> {
render() {
return <Button />;
}
}
//@filename: button.tsx
import * as React from 'react';
export class Button extends React.Component<any, any> {
render() {
return <button>Some button</button>;
}
}