CR feedback

This commit is contained in:
Ryan Cavanaugh
2015-06-26 14:18:51 -07:00
parent b1a05b8d3c
commit 306de4d681
10 changed files with 145 additions and 62 deletions
+15 -18
View File
@@ -165,7 +165,7 @@ namespace ts {
}
};
let JsxNames = {
const JsxNames = {
JSX: "JSX",
IntrinsicElements: "IntrinsicElements",
ElementClass: "ElementClass",
@@ -5578,6 +5578,7 @@ namespace ts {
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxSpreadAttribute:
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxExpression:
return forEachChild(node, isAssignedIn);
}
return false;
@@ -6774,8 +6775,7 @@ namespace ts {
return false;
}
else {
let firstChar = (<Identifier>tagName).text.charAt(0);
return firstChar.toLowerCase() === firstChar;
return isIntrinsicJsxName((<Identifier>tagName).text);
}
}
@@ -6836,10 +6836,7 @@ namespace ts {
/// Returns the type JSX.IntrinsicElements. May return `unknownType` if that type is not present.
function getJsxIntrinsicElementsType() {
if (!jsxIntrinsicElementsType) {
let jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, undefined);
let intrinsicsSymbol = jsxNamespace && getSymbol(jsxNamespace.exports, JsxNames.IntrinsicElements, SymbolFlags.Type);
let intrinsicsType = intrinsicsSymbol && getDeclaredTypeOfSymbol(intrinsicsSymbol);
jsxIntrinsicElementsType = intrinsicsType || unknownType;
jsxIntrinsicElementsType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.IntrinsicElements) || unknownType;
}
return jsxIntrinsicElementsType;
}
@@ -6977,18 +6974,23 @@ namespace ts {
let attribProperties = attribPropType && getPropertiesOfType(attribPropType);
if (attribProperties) {
// Element Attributes has zero properties, so the element attributes type will be the class instance type
if (attribProperties.length === 0) {
return '';
}
// Element Attributes has one property, so the element attributes type will be the type of the corresponding
// property of the class instance type
else if (attribProperties.length === 1) {
return attribProperties[0].name;
}
// More than one property on ElementAttributesProperty is an error
else {
error(attribsPropTypeSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, JsxNames.ElementAttributesPropertyNameContainer);
return undefined;
}
}
else {
// No interface exists, so the element attributes type will be an implicit any
return undefined;
}
}
@@ -7044,7 +7046,7 @@ namespace ts {
return links.resolvedJsxType = getIndexTypeOfSymbol(sym, IndexKind.String);
}
else {
// Resolution failed
// Resolution failed, so we don't know
return links.resolvedJsxType = anyType;
}
}
@@ -7063,16 +7065,12 @@ namespace ts {
return prop || unknownSymbol;
}
let jsxElementClassType: Type = undefined;
function getJsxGlobalElementClassType(): Type {
let jsxNS = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined);
if (jsxNS) {
let sym = getSymbol(jsxNS.exports, JsxNames.ElementClass, SymbolFlags.Type);
let elemClassType = sym && getDeclaredTypeOfSymbol(sym);
return elemClassType;
}
else {
return undefined;
if(!jsxElementClassType) {
jsxElementClassType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.ElementClass);
}
return jsxElementClassType;
}
/// Returns all the properties of the Jsx.IntrinsicElements interface
@@ -7137,8 +7135,7 @@ namespace ts {
return checkExpression(node.expression);
}
else {
/// <Foo enabled /> is shorthand for <Foo enabled={true} />
return booleanType;
return unknownType;
}
}
+31 -29
View File
@@ -1113,20 +1113,12 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
/// Emit a tag name, which is either '"div"' for lower-cased names, or
/// 'Div' for upper-cased or dotted names
function emitTagName(name: Identifier|QualifiedName) {
if (name.kind === SyntaxKind.Identifier) {
var ch = (<Identifier>name).text.charAt(0);
if (ch.toUpperCase() === ch) {
emit(name);
}
else {
write('"');
emit(name);
write('"');
}
return ch.toUpperCase() !== ch;
if (name.kind === SyntaxKind.Identifier && isIntrinsicJsxName((<Identifier>name).text)) {
write('"');
emit(name);
write('"');
}
else {
Debug.assert(name.kind === SyntaxKind.QualifiedName);
emit(name);
}
}
@@ -1234,12 +1226,19 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
// Don't emit empty strings
if (children[i].kind === SyntaxKind.JsxText && !shouldEmitJsxText(<JsxText>children[i])) {
continue;
if (children[i].kind === SyntaxKind.JsxText) {
let text = getTextToEmit(<JsxText>children[i]);
if(text !== undefined) {
write(', "');
write(text);
write('"');
}
}
else {
write(', ');
emit(children[i]);
}
write(', ');
emit(children[i]);
}
}
@@ -5895,12 +5894,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
function trimReactWhitespace(node: JsxText): string {
// Could be empty string, do not use !node.formattedReactText
if (node.formattedReactText !== undefined) {
return node.formattedReactText;
}
let lines: string[] = [];
let result: string = undefined;
let text = getTextOfNode(node);
let firstNonWhitespace = 0;
let lastNonWhitespace = -1;
@@ -5910,9 +5904,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
// on the same line as the closing tag. See examples in tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx
for (let i = 0; i < text.length; i++) {
let c = text.charCodeAt(i);
if (c === CharacterCodes.lineFeed || c === CharacterCodes.carriageReturn) {
if (isLineBreak(c)) {
if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) {
lines.push(text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1));
let part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1);
result = (result ? result + '" + \' \' + "' : '') + part;
}
firstNonWhitespace = -1;
}
@@ -5924,19 +5919,26 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
if (firstNonWhitespace !== -1) {
lines.push(text.substr(firstNonWhitespace));
let part = text.substr(firstNonWhitespace);
result = (result ? result + '" + \' \' + "' : '') + part;
}
return node.formattedReactText = lines.join('" + \' \' + "');
return result;
}
function shouldEmitJsxText(node: JsxText) {
function getTextToEmit(node: JsxText) {
switch (compilerOptions.jsx) {
case JsxEmit.React:
return trimReactWhitespace(node).length > 0;
let text = trimReactWhitespace(node);
if (text.length === 0) {
return undefined;
}
else {
return text;
}
case JsxEmit.Preserve:
default:
return true;
return getTextOfNode(node, true);
}
}
+1 -5
View File
@@ -657,7 +657,7 @@ namespace ts {
sourceFile.languageVersion = languageVersion;
sourceFile.fileName = normalizePath(fileName);
sourceFile.flags = fileExtensionIs(sourceFile.fileName, ".d.ts") ? NodeFlags.DeclarationFile : 0;
sourceFile.languageVariant = fileExtensionIs(sourceFile.fileName, ".tsx") ? LanguageVariant.JSX : LanguageVariant.Standard;
sourceFile.languageVariant = isTsx(sourceFile.fileName) ? LanguageVariant.JSX : LanguageVariant.Standard;
return sourceFile;
}
@@ -1298,7 +1298,6 @@ namespace ts {
case ParsingContext.HeritageClauses:
return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.CloseBraceToken;
case ParsingContext.JsxAttributes:
// REMOVE -> // For error recovery, include } here (otherwise an over-braced {expr}} will close the surrounding statement block and mess up the entire file).
return token === SyntaxKind.GreaterThanToken || token === SyntaxKind.SlashToken;
case ParsingContext.JsxChildren:
return token === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash);
@@ -3377,9 +3376,6 @@ namespace ts {
node.name = parseIdentifierName();
if (parseOptional(SyntaxKind.EqualsToken)) {
switch (token) {
case SyntaxKind.LessThanToken:
node.initializer = parseJsxElementOrSelfClosingElement();
break;
case SyntaxKind.StringLiteral:
node.initializer = parseLiteralNode();
break;
-2
View File
@@ -877,8 +877,6 @@ namespace ts {
export interface JsxText extends Node {
_jsxTextExpressionBrand: any;
/// Used by the emitter to avoid recomputation
formattedReactText?: string;
}
export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement;
+5
View File
@@ -1535,6 +1535,11 @@ namespace ts {
}
}
export function isIntrinsicJsxName(name: string) {
let ch = name.substr(0, 1);
return ch.toLowerCase() === ch;
}
function get16BitUnicodeEscapeSequence(charCode: number): string {
let hexCharCode = charCode.toString(16).toUpperCase();
let paddedHexCode = ("0000" + hexCharCode).slice(-4);
+1 -1
View File
@@ -2934,7 +2934,7 @@ namespace ts {
getTypeScriptMemberSymbols();
}
else if (isRightOfOpenTag) {
let tagSymbols = typeChecker.getJsxIntrinsicTagNames();;
let tagSymbols = typeChecker.getJsxIntrinsicTagNames();
if (tryGetGlobalSymbols()) {
symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & SymbolFlags.Value)));
}
@@ -0,0 +1,81 @@
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,17): error TS1005: '{' expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,23): error TS1005: '}' expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,29): error TS1005: '{' expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,57): error TS1109: Expression expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,58): error TS1109: Expression expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(41,1): error TS1003: Identifier expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(41,6): error TS1109: Expression expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(41,12): error TS1109: Expression expected.
==== tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx (8 errors) ====
declare var React: any;
declare var 日本語;
declare var AbC_def;
declare var LeftRight;
declare var x;
declare var a;
declare var props;
<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;" />;
<a b="&notanentity;" />;
<a
/>;
<日本語></日本語>;
<AbC_def
test="&#x0026;&#38;">
bar
baz
</AbC_def>;
<a b={x ? <c /> : <d />} />;
<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> />;
~
!!! error TS1005: '{' expected.
~~~~~
!!! error TS1005: '}' expected.
~
!!! error TS1005: '{' expected.
~
!!! error TS1109: Expression expected.
~
!!! error TS1109: Expression expected.
<a.b></a.b>;
~
!!! error TS1003: Identifier expected.
~~
!!! error TS1109: Expression expected.
~
!!! error TS1109: Expression expected.
<a.b.c></a.b.c>;
(<div />) < x;
<div {...props} />;
<div {...props} post="attribute" />;
<div pre="leading" pre2="attribute" {...props}></div>;
<a> </a>;
@@ -71,8 +71,9 @@ baz
<a></a>;
<div>@test content</div>;
<div><br />7x invalid-js-identifier</div>;
<LeftRight left=<a /> right=<b>monkeys /> gorillas</b>/>;
<a.b></a.b>;
<LeftRight left={<a />} right={<b>monkeys /> gorillas</b> / > }/>
< a.b > ;
a.b > ;
<a.b.c></a.b.c>;
(<div />) < x;
<div {...props}/>;
@@ -65,12 +65,13 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,10): error TS2304:
tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,28): error TS1005: '>' expected.
tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,29): error TS1109: Expression expected.
tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(32,6): error TS1005: '{' expected.
tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(33,7): error TS1003: Identifier expected.
tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(33,6): error TS1005: '{' expected.
tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(33,7): error TS1109: Expression expected.
tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,4): error TS1003: Identifier expected.
tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002: Expected corresponding JSX closing tag for 'a'.
==== tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx (70 errors) ====
==== tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx (71 errors) ====
declare var React: any;
</>;
@@ -238,8 +239,10 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002
~
!!! error TS1005: '{' expected.
<a b=<}>;
~
!!! error TS1005: '{' expected.
~
!!! error TS1003: Identifier expected.
!!! error TS1109: Expression expected.
<a>}</a>;
<a .../*hai*/asdf/>;
~~~
@@ -76,6 +76,6 @@ var x = <div>one</div> /* intervening comment */ /* intervening comment */ <div>
<a>></a>;
<a> ></a>;
<a b=>;
<a b=< />/>}>;
<a b={ < }>;
<a>}</a>;
<a /> .../*hai*/asdf/>;</></></>;
<a /> .../*hai*/asdf/>;</></></></>;