diff --git a/src/compiler/core.ts b/src/compiler/core.ts
index ced477eeeec..7b35c5e0d65 100644
--- a/src/compiler/core.ts
+++ b/src/compiler/core.ts
@@ -702,9 +702,9 @@ namespace ts {
/**
* List of supported extensions in order of file resolution precedence.
*/
- export const supportedExtensions = [".ts", ".d.ts"];
+ export const supportedExtensions = [".tsx", ".ts", ".d.ts"];
- const extensionsToRemove = [".d.ts", ".ts", ".js"];
+ const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
export function removeFileExtension(path: string): string {
for (let ext of extensionsToRemove) {
if (fileExtensionIs(path, ext)) {
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index f9a2fa3b7b4..d78d38d5ba7 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -48,6 +48,7 @@ namespace ts {
SemicolonToken,
CommaToken,
LessThanToken,
+ LessThanSlashToken,
GreaterThanToken,
LessThanEqualsToken,
GreaterThanEqualsToken,
@@ -217,6 +218,8 @@ namespace ts {
ClassExpression,
OmittedExpression,
ExpressionWithTypeArguments,
+ AsExpression,
+
// Misc
TemplateSpan,
SemicolonClassElement,
@@ -265,6 +268,16 @@ namespace ts {
// Module references
ExternalModuleReference,
+ //JSX
+ JsxElement,
+ JsxSelfClosingElement,
+ JsxOpeningElement,
+ JsxText,
+ JsxClosingElement,
+ JsxAttribute,
+ JsxSpreadAttribute,
+ JsxExpression,
+
// Clauses
CaseClause,
DefaultClause,
@@ -396,6 +409,17 @@ namespace ts {
HasAggregatedChildData = 1 << 8
}
+ export const enum JsxFlags {
+ None = 0,
+ IntrinsicNamedElement = 1 << 0,
+ IntrinsicIndexedElement = 1 << 1,
+ ClassElement = 1 << 2,
+ UnknownElement = 1 << 3,
+
+ IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement
+ }
+
+
/* @internal */
export const enum RelationComparisonResult {
Succeeded = 1, // Should be truthy
@@ -799,11 +823,66 @@ namespace ts {
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression;
+ export interface AsExpression extends Expression {
+ expression: Expression;
+ type: TypeNode;
+ }
+
export interface TypeAssertion extends UnaryExpression {
type: TypeNode;
expression: UnaryExpression;
}
+ export type AssertionExpression = TypeAssertion | AsExpression;
+
+ /// A JSX expression of the form ...
+ export interface JsxElement extends PrimaryExpression {
+ openingElement: JsxOpeningElement;
+ children: NodeArray;
+ closingElement: JsxClosingElement;
+ }
+
+ /// The opening element of a ... JsxElement
+ export interface JsxOpeningElement extends Expression {
+ _openingElementBrand?: any;
+ tagName: EntityName;
+ attributes: NodeArray;
+ }
+
+ /// A JSX expression of the form
+ export interface JsxSelfClosingElement extends PrimaryExpression, JsxOpeningElement {
+ _selfClosingElementBrand?: any;
+ }
+
+ /// Either the opening tag in a ... pair, or the lone in a self-closing form
+ export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement;
+
+ export interface JsxAttribute extends Node {
+ name: Identifier;
+ /// JSX attribute initializers are optional; is sugar for
+ initializer?: Expression;
+ }
+
+ export interface JsxSpreadAttribute extends Node {
+ expression: Expression;
+ }
+
+ export interface JsxClosingElement extends Node {
+ tagName: EntityName;
+ }
+
+ export interface JsxExpression extends Expression {
+ expression?: Expression;
+ }
+
+ export interface JsxText extends Node {
+ _jsxTextExpressionBrand: any;
+ /// Used by the emitter to avoid recomputation
+ formattedReactText?: string;
+ }
+
+ export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement;
+
export interface Statement extends Node {
_statementBrand: any;
}
@@ -1144,6 +1223,7 @@ namespace ts {
amdDependencies: {path: string; name: string}[];
moduleName: string;
referencedFiles: FileReference[];
+ isTSXFile: boolean;
/**
* lib.d.ts should have a reference comment like
@@ -1323,6 +1403,9 @@ namespace ts {
getAliasedSymbol(symbol: Symbol): Symbol;
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
+ getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type;
+ getJsxIntrinsicTagNames(): Symbol[];
+
// Should not be called directly. Should only be accessed through the Program instance.
/* @internal */ getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
/* @internal */ getGlobalDiagnostics(): Diagnostic[];
@@ -1603,6 +1686,7 @@ namespace ts {
assignmentChecks?: Map; // Cache of assignment checks
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
importOnRightSide?: Symbol; // for import declarations - import that appear on the right side
+ jsxFlags?: JsxFlags; // flags for knowning what kind of element/attributes we're dealing with
}
export const enum TypeFlags {
@@ -1834,6 +1918,7 @@ namespace ts {
help?: boolean;
inlineSourceMap?: boolean;
inlineSources?: boolean;
+ jsx?: JsxEmit;
listFiles?: boolean;
locale?: string;
mapRoot?: string;
@@ -1877,6 +1962,12 @@ namespace ts {
System = 4,
}
+ export const enum JsxEmit {
+ None = 0,
+ Preserve = 1,
+ React = 2
+ }
+
export const enum NewLineKind {
CarriageReturnLineFeed = 0,
LineFeed = 1,
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index ee75454ad93..7ec599babbc 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -169,13 +169,13 @@ namespace ts {
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.decorators.end);
}
- export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node): string {
+ export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node, includeTrivia = false): string {
if (nodeIsMissing(node)) {
return "";
}
let text = sourceFile.text;
- return text.substring(skipTrivia(text, node.pos), node.end);
+ return text.substring(includeTrivia ? node.pos : skipTrivia(text, node.pos), node.end);
}
export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string {
@@ -186,8 +186,8 @@ namespace ts {
return sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
}
- export function getTextOfNode(node: Node): string {
- return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node);
+ export function getTextOfNode(node: Node, includeTrivia = false): string {
+ return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia);
}
// Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__'
@@ -850,6 +850,7 @@ namespace ts {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
+ case SyntaxKind.AsExpression:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.FunctionExpression:
@@ -866,6 +867,8 @@ namespace ts {
case SyntaxKind.TemplateExpression:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.OmittedExpression:
+ case SyntaxKind.JsxElement:
+ case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.YieldExpression:
return true;
case SyntaxKind.QualifiedName:
@@ -912,7 +915,8 @@ namespace ts {
return (forInStatement.initializer === node && forInStatement.initializer.kind !== SyntaxKind.VariableDeclarationList) ||
forInStatement.expression === node;
case SyntaxKind.TypeAssertionExpression:
- return node === (parent).expression;
+ case SyntaxKind.AsExpression:
+ return node === (parent).expression;
case SyntaxKind.TemplateSpan:
return node === (parent).expression;
case SyntaxKind.ComputedPropertyName:
@@ -1886,6 +1890,8 @@ namespace ts {
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression:
+ case SyntaxKind.JsxElement:
+ case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ParenthesizedExpression: