Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lookup JSX namespace within factory function #22207

Merged
merged 2 commits into from
Feb 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 64 additions & 107 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2871,7 +2871,7 @@ namespace ts {
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];

getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
getJsxIntrinsicTagNames(): Symbol[];
getJsxIntrinsicTagNamesAt(location: Node): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];

Expand Down
2 changes: 1 addition & 1 deletion src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,7 @@ namespace ts.Completions {
getTypeScriptMemberSymbols();
}
else if (isRightOfOpenTag) {
const tagSymbols = Debug.assertEachDefined(typeChecker.getJsxIntrinsicTagNames(), "getJsxIntrinsicTagNames() should all be defined");
const tagSymbols = Debug.assertEachDefined(typeChecker.getJsxIntrinsicTagNamesAt(location), "getJsxIntrinsicTagNames() should all be defined");
if (tryGetGlobalSymbols()) {
symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & (SymbolFlags.Value | SymbolFlags.Alias))));
}
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1811,7 +1811,7 @@ declare namespace ts {
getAliasedSymbol(symbol: Symbol): Symbol;
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
getJsxIntrinsicTagNames(): Symbol[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a note about this change in the breaking changes section in https://github.com/Microsoft/TypeScript/wiki/API-Breaking-Changes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. 👍

getJsxIntrinsicTagNamesAt(location: Node): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];
tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1811,7 +1811,7 @@ declare namespace ts {
getAliasedSymbol(symbol: Symbol): Symbol;
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
getJsxIntrinsicTagNames(): Symbol[];
getJsxIntrinsicTagNamesAt(location: Node): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];
tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2322: Type 'dom.JSX.Element' is not assignable to type 'predom.JSX.Element'.
Property '__predomBrand' is missing in type 'Element'.
tests/cases/conformance/jsx/inline/index.tsx(21,21): error TS2605: JSX element type 'Element' is not a constructor function for JSX elements.
Property 'render' is missing in type 'Element'.
tests/cases/conformance/jsx/inline/index.tsx(21,28): error TS2322: Type '{ children: Element[]; x: number; y: number; }' is not assignable to type '{ children?: Element[]; }'.
Types of property 'children' are incompatible.
Type 'dom.JSX.Element[]' is not assignable to type 'predom.JSX.Element[]'.
Type 'dom.JSX.Element' is not assignable to type 'predom.JSX.Element'.
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
Property '__domBrand' is missing in type 'MyClass'.
tests/cases/conformance/jsx/inline/index.tsx(21,63): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
tests/cases/conformance/jsx/inline/index.tsx(24,30): error TS2322: Type '{ children: Element[]; x: number; y: number; }' is not assignable to type '{ x: number; y: number; children?: Element[]; }'.
Types of property 'children' are incompatible.
Type 'predom.JSX.Element[]' is not assignable to type 'dom.JSX.Element[]'.
Type 'predom.JSX.Element' is not assignable to type 'dom.JSX.Element'.
Property '__domBrand' is missing in type 'Element'.


==== tests/cases/conformance/jsx/inline/renderer.d.ts (0 errors) ====
export namespace dom {
namespace JSX {
interface IntrinsicElements {
[e: string]: {};
}
interface Element {
__domBrand: void;
props: {
children?: Element[];
};
}
interface ElementClass extends Element {
render(): Element;
}
interface ElementAttributesProperty { props: any; }
interface ElementChildrenAttribute { children: any; }
}
}
export function dom(): dom.JSX.Element;
==== tests/cases/conformance/jsx/inline/renderer2.d.ts (0 errors) ====
export namespace predom {
namespace JSX {
interface IntrinsicElements {
[e: string]: {};
}
interface Element {
__predomBrand: void;
props: {
children?: Element[];
};
}
interface ElementClass extends Element {
render(): Element;
}
interface ElementAttributesProperty { props: any; }
interface ElementChildrenAttribute { children: any; }
}
}
export function predom(): predom.JSX.Element;
==== tests/cases/conformance/jsx/inline/component.tsx (0 errors) ====
/** @jsx predom */
import { predom } from "./renderer2"

export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{...this.props.children}</p>;

export class MyClass implements predom.JSX.Element {
__predomBrand!: void;
constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
render() {
return <p>
{this.props.x} + {this.props.y} = {this.props.x + this.props.y}
{...this.props.children}
</p>;
}
}
export const tree = <MySFC x={1} y={2}><MyClass x={3} y={4} /><MyClass x={5} y={6} /></MySFC>

export default <h></h>

==== tests/cases/conformance/jsx/inline/index.tsx (7 errors) ====
/** @jsx dom */
import { dom } from "./renderer"
import prerendered, {MySFC, MyClass, tree} from "./component";
let elem = prerendered;
elem = <h></h>; // Expect assignability error here
~~~~
!!! error TS2322: Type 'dom.JSX.Element' is not assignable to type 'predom.JSX.Element'.
!!! error TS2322: Property '__predomBrand' is missing in type 'Element'.

const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{props.children}</p>;

class DOMClass implements dom.JSX.Element {
__domBrand!: void;
constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
render() {
return <p>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}</p>;
}
}

// Should work, everything is a DOM element
const _tree = <DOMSFC x={1} y={2}><DOMClass x={3} y={4} /><DOMClass x={5} y={6} /></DOMSFC>

// Should fail, no dom elements
const _brokenTree = <MySFC x={1} y={2}><MyClass x={3} y={4} /><MyClass x={5} y={6} /></MySFC>
~~~~~~~~~~~~~~~~~~~
!!! error TS2605: JSX element type 'Element' is not a constructor function for JSX elements.
!!! error TS2605: Property 'render' is missing in type 'Element'.
~~~~~~~~~~~
!!! error TS2322: Type '{ children: Element[]; x: number; y: number; }' is not assignable to type '{ children?: Element[]; }'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type 'dom.JSX.Element[]' is not assignable to type 'predom.JSX.Element[]'.
!!! error TS2322: Type 'dom.JSX.Element' is not assignable to type 'predom.JSX.Element'.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
!!! error TS2605: Property '__domBrand' is missing in type 'MyClass'.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.

// Should fail, nondom isn't allowed as children of dom
const _brokenTree2 = <DOMSFC x={1} y={2}>{tree}{tree}</DOMSFC>
~~~~~~~~~~~
!!! error TS2322: Type '{ children: Element[]; x: number; y: number; }' is not assignable to type '{ x: number; y: number; children?: Element[]; }'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type 'predom.JSX.Element[]' is not assignable to type 'dom.JSX.Element[]'.
!!! error TS2322: Type 'predom.JSX.Element' is not assignable to type 'dom.JSX.Element'.
!!! error TS2322: Property '__domBrand' is missing in type 'Element'.

164 changes: 164 additions & 0 deletions tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
//// [tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx] ////

//// [renderer.d.ts]
export namespace dom {
namespace JSX {
interface IntrinsicElements {
[e: string]: {};
}
interface Element {
__domBrand: void;
props: {
children?: Element[];
};
}
interface ElementClass extends Element {
render(): Element;
}
interface ElementAttributesProperty { props: any; }
interface ElementChildrenAttribute { children: any; }
}
}
export function dom(): dom.JSX.Element;
//// [renderer2.d.ts]
export namespace predom {
namespace JSX {
interface IntrinsicElements {
[e: string]: {};
}
interface Element {
__predomBrand: void;
props: {
children?: Element[];
};
}
interface ElementClass extends Element {
render(): Element;
}
interface ElementAttributesProperty { props: any; }
interface ElementChildrenAttribute { children: any; }
}
}
export function predom(): predom.JSX.Element;
//// [component.tsx]
/** @jsx predom */
import { predom } from "./renderer2"

export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{...this.props.children}</p>;

export class MyClass implements predom.JSX.Element {
__predomBrand!: void;
constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
render() {
return <p>
{this.props.x} + {this.props.y} = {this.props.x + this.props.y}
{...this.props.children}
</p>;
}
}
export const tree = <MySFC x={1} y={2}><MyClass x={3} y={4} /><MyClass x={5} y={6} /></MySFC>

export default <h></h>

//// [index.tsx]
/** @jsx dom */
import { dom } from "./renderer"
import prerendered, {MySFC, MyClass, tree} from "./component";
let elem = prerendered;
elem = <h></h>; // Expect assignability error here

const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{props.children}</p>;

class DOMClass implements dom.JSX.Element {
__domBrand!: void;
constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
render() {
return <p>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}</p>;
}
}

// Should work, everything is a DOM element
const _tree = <DOMSFC x={1} y={2}><DOMClass x={3} y={4} /><DOMClass x={5} y={6} /></DOMSFC>

// Should fail, no dom elements
const _brokenTree = <MySFC x={1} y={2}><MyClass x={3} y={4} /><MyClass x={5} y={6} /></MySFC>

// Should fail, nondom isn't allowed as children of dom
const _brokenTree2 = <DOMSFC x={1} y={2}>{tree}{tree}</DOMSFC>


//// [component.js]
"use strict";
var _this = this;
exports.__esModule = true;
/** @jsx predom */
var renderer2_1 = require("./renderer2");
exports.MySFC = function (props) { return renderer2_1.predom("p", null,
props.x,
" + ",
props.y,
" = ",
props.x + props.y,
_this.props.children); };
var MyClass = /** @class */ (function () {
function MyClass(props) {
this.props = props;
}
MyClass.prototype.render = function () {
return renderer2_1.predom("p", null,
this.props.x,
" + ",
this.props.y,
" = ",
this.props.x + this.props.y,
this.props.children);
};
return MyClass;
}());
exports.MyClass = MyClass;
exports.tree = renderer2_1.predom(exports.MySFC, { x: 1, y: 2 },
renderer2_1.predom(MyClass, { x: 3, y: 4 }),
renderer2_1.predom(MyClass, { x: 5, y: 6 }));
exports["default"] = renderer2_1.predom("h", null);
//// [index.js]
"use strict";
exports.__esModule = true;
/** @jsx dom */
var renderer_1 = require("./renderer");
var component_1 = require("./component");
var elem = component_1["default"];
elem = renderer_1.dom("h", null); // Expect assignability error here
var DOMSFC = function (props) { return renderer_1.dom("p", null,
props.x,
" + ",
props.y,
" = ",
props.x + props.y,
props.children); };
var DOMClass = /** @class */ (function () {
function DOMClass(props) {
this.props = props;
}
DOMClass.prototype.render = function () {
return renderer_1.dom("p", null,
this.props.x,
" + ",
this.props.y,
" = ",
this.props.x + this.props.y,
this.props.children);
};
return DOMClass;
}());
// Should work, everything is a DOM element
var _tree = renderer_1.dom(DOMSFC, { x: 1, y: 2 },
renderer_1.dom(DOMClass, { x: 3, y: 4 }),
renderer_1.dom(DOMClass, { x: 5, y: 6 }));
// Should fail, no dom elements
var _brokenTree = renderer_1.dom(component_1.MySFC, { x: 1, y: 2 },
renderer_1.dom(component_1.MyClass, { x: 3, y: 4 }),
renderer_1.dom(component_1.MyClass, { x: 5, y: 6 }));
// Should fail, nondom isn't allowed as children of dom
var _brokenTree2 = renderer_1.dom(DOMSFC, { x: 1, y: 2 },
component_1.tree,
component_1.tree);
Loading