Skip to content

Adds the JSX transformer #7192

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

Merged
merged 47 commits into from
Mar 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6c0551f
Adds initial jsx transformer
rbuckton Feb 17, 2016
1ceb02a
Added initial ES7 transformer
rbuckton Feb 17, 2016
dd2dc78
Enables source maps for exceptions thrown in the compiler (when avail…
rbuckton Feb 20, 2016
c759b63
Adds ES6 transformer
rbuckton Feb 20, 2016
39628d7
Added CommonJS/AMD/UMD module transformer
rbuckton Feb 20, 2016
5564537
Added initial SystemJS transformer.
rbuckton Feb 22, 2016
3d8cb51
Merge branch 'transforms-transformer-ts' into transforms-transformer-jsx
rbuckton Feb 23, 2016
0145009
Merge branch 'transforms-transformer-jsx' into transforms-transformer…
rbuckton Feb 23, 2016
dc0b043
Merge branch 'transforms-transformer-es7' into transforms-transformer…
rbuckton Feb 23, 2016
0b64048
Merge branch 'transforms-transformer-es6' into transforms-transformer…
rbuckton Feb 23, 2016
c166a2d
Merge branch 'transforms-transformer-ts' into transforms-transformer-jsx
rbuckton Feb 23, 2016
5b7bd63
Merge branch 'transforms-transformer-jsx' into transforms-transformer…
rbuckton Feb 23, 2016
6d111e3
Merge branch 'transforms-transformer-es7' into transforms-transformer…
rbuckton Feb 23, 2016
608822d
Merge branch 'transforms-transformer-ts' into transforms-transformer-jsx
rbuckton Feb 24, 2016
c9f5253
Fixed linter warnings
rbuckton Feb 24, 2016
cde3b34
Merge branch 'transforms-transformer-ts' into transforms-transformer-jsx
rbuckton Feb 24, 2016
5a9b131
Merge branch 'transforms-transformer-jsx' into transforms-transformer…
rbuckton Feb 24, 2016
78dfab8
Merge branch 'transforms-transformer-es7' into transforms-transformer…
rbuckton Feb 24, 2016
0d8e152
Merge branch 'transforms-transformer-es6' into transforms-transformer…
rbuckton Feb 24, 2016
72bfd2f
Fixed linter warnings.
rbuckton Feb 24, 2016
a7f9cda
Merge branch 'transforms-transformer-ts' into transforms-transformer-jsx
rbuckton Mar 1, 2016
7d05ba2
Fixed visitJsxText, plus PR Feedback
rbuckton Mar 1, 2016
186f5c8
PR Feedback
rbuckton Mar 1, 2016
2c9cd2e
Merge branch 'transforms-transformer-jsx' into transforms-transformer…
rbuckton Mar 1, 2016
88e1772
Merge branch 'transforms-transformer-es7' into transforms-transformer…
rbuckton Mar 1, 2016
30433c2
ES6 cleanup
rbuckton Mar 2, 2016
2d2709f
Fixed typo in visitCallExpression
rbuckton Mar 2, 2016
70cbb9b
Merge branch 'transforms-transformer-es6' into transforms-transformer…
rbuckton Mar 2, 2016
1fdaf74
Merge branch 'transforms-transformer-ts' into transforms-transformer-jsx
rbuckton Mar 2, 2016
593fbd4
Merge branch 'transforms-transformer-jsx' into transforms-transformer…
rbuckton Mar 2, 2016
7b28b48
Merge branch 'transforms-transformer-es7' into transforms-transformer…
rbuckton Mar 2, 2016
1c73818
Switched to onEmitNode
rbuckton Mar 2, 2016
c4a75ba
Merge branch 'transforms-transformer-es6' into transforms-transformer…
rbuckton Mar 2, 2016
72eebdb
Switched to onEmitNode
rbuckton Mar 2, 2016
1cf183b
Fixed invalid assertion in ts transformer
rbuckton Mar 4, 2016
d89e21a
General fixes and cleanup
rbuckton Mar 8, 2016
5b8cf96
Moved modifier related flags to separate enum
rbuckton Mar 10, 2016
99e6ad8
Removed ModifiersArray
rbuckton Mar 10, 2016
47cdfbe
Add support for array return values from visitors
rbuckton Mar 10, 2016
2699bf9
Removed NodeArrayNode in favor of arrays
rbuckton Mar 10, 2016
94018a1
cleaned up assertions and removed flattenNodes.
rbuckton Mar 10, 2016
ad0dd4e
Fixed perf issue in binder, plus PR feedback
rbuckton Mar 18, 2016
44ca7d4
Updated baselines
rbuckton Mar 18, 2016
ae7843d
PR Feedback
rbuckton Mar 18, 2016
3c5f170
Merge pull request #7206 from Microsoft/transforms-transformer-module
rbuckton Mar 18, 2016
07a3d18
Merge pull request #7194 from Microsoft/transforms-transformer-es6
rbuckton Mar 18, 2016
cc00f4c
Merge pull request #7193 from Microsoft/transforms-transformer-es7
rbuckton Mar 18, 2016
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
529 changes: 316 additions & 213 deletions src/compiler/binder.ts

Large diffs are not rendered by default.

255 changes: 130 additions & 125 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

130 changes: 120 additions & 10 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,23 +171,116 @@ namespace ts {
return result;
}

/**
* Flattens an array containing a mix of array or non-array elements.
*
* @param array The array to flatten.
*/
export function flatten<T>(array: (T | T[])[]): T[] {
let result: T[];
if (array) {
result = [];
for (const v of array) {
if (v) {
if (isArray(v)) {
addRange(result, v);
}
else {
result.push(v);
}
}
}
}

return result;
}

/**
* Maps an array. If the mapped value is an array, it is spread into the result.
*
* @param array The array to map.
* @param mapfn The callback used to map the result into one or more values.
*/
export function flatMap<T, U>(array: T[], f: (x: T, i: number) => U | U[]): U[] {
export function flatMap<T, U>(array: T[], mapfn: (x: T, i: number) => U | U[]): U[] {
let result: U[];
if (array) {
result = [];
for (let i = 0; i < array.length; i++) {
const v = array[i];
const ar = f(v, i);
if (ar) {
// We cast to <U> here to leverage the behavior of Array#concat
// which will append a single value here.
result = result.concat(<U[]>ar);
const v = mapfn(array[i], i);
if (v) {
if (isArray(v)) {
addRange(result, v);
}
else {
result.push(v);
}
}
}
}
return result;
}

/**
* Computes the first matching span of elements and returns a tuple of the first span
* and the remaining elements.
*/
export function span<T>(array: T[], f: (x: T, i: number) => boolean): [T[], T[]] {
if (array) {
for (let i = 0; i < array.length; i++) {
if (!f(array[i], i)) {
return [array.slice(0, i), array.slice(i)];
}
}
return [array.slice(0), []];
}

return undefined;
}

/**
* Maps contiguous spans of values with the same key.
*
* @param array The array to map.
* @param keyfn A callback used to select the key for an element.
* @param mapfn A callback used to map a contiguous chunk of values to a single value.
*/
export function spanMap<T, K, U>(array: T[], keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K) => U): U[] {
let result: U[];
if (array) {
result = [];
const len = array.length;
let previousKey: K;
let key: K;
let start = 0;
let pos = 0;
while (start < len) {
while (pos < len) {
const value = array[pos];
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this temp is needed for readability or efficiency.

key = keyfn(value, pos);
if (pos === 0) {
previousKey = key;
}
else if (key !== previousKey) {
break;
}

pos++;
}

if (start < pos) {
const v = mapfn(array.slice(start, pos), previousKey);
if (v) {
result.push(v);
}

start = pos;
}

previousKey = key;
pos++;
}
}

return result;
}

Expand Down Expand Up @@ -920,8 +1013,9 @@ namespace ts {
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.transformFlags = undefined;
this.excludeTransformFlags = undefined;
this.modifierFlagsCache = ModifierFlags.None;
this.transformFlags = TransformFlags.None;
this.excludeTransformFlags = TransformFlags.None;
this.parent = undefined;
this.original = undefined;
}
Expand All @@ -942,7 +1036,12 @@ namespace ts {
}

export namespace Debug {
const currentAssertionLevel = AssertionLevel.None;
declare var process: any;
declare var require: any;

const currentAssertionLevel = getDevelopmentMode() === "development"
? AssertionLevel.Normal
: AssertionLevel.None;

export function shouldAssert(level: AssertionLevel): boolean {
return currentAssertionLevel >= level;
Expand All @@ -962,6 +1061,17 @@ namespace ts {
export function fail(message?: string): void {
Debug.assert(/*expression*/ false, message);
}

function getDevelopmentMode() {
return typeof require !== "undefined"
&& typeof process !== "undefined"
&& !process.browser
&& process.nextTick
&& process.env
&& process.env.NODE_ENV
? String(process.env.NODE_ENV).toLowerCase()
: undefined;
}
}

export function copyListRemovingItem<T>(item: T, list: T[]) {
Expand Down
57 changes: 29 additions & 28 deletions src/compiler/declarationEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,12 +623,13 @@ namespace ts {
function emitModuleElementDeclarationFlags(node: Node) {
// If the node is parented in the current source file we need to emit export declare or just export
if (node.parent.kind === SyntaxKind.SourceFile) {
const modifiers = getModifierFlags(node);
// If the node is exported
if (node.flags & NodeFlags.Export) {
if (modifiers & ModifierFlags.Export) {
write("export ");
}

if (node.flags & NodeFlags.Default) {
if (modifiers & ModifierFlags.Default) {
write("default ");
}
else if (node.kind !== SyntaxKind.InterfaceDeclaration && !noDeclare) {
Expand All @@ -637,21 +638,21 @@ namespace ts {
}
}

function emitClassMemberDeclarationFlags(flags: NodeFlags) {
if (flags & NodeFlags.Private) {
function emitClassMemberDeclarationFlags(flags: ModifierFlags) {
if (flags & ModifierFlags.Private) {
write("private ");
}
else if (flags & NodeFlags.Protected) {
else if (flags & ModifierFlags.Protected) {
write("protected ");
}

if (flags & NodeFlags.Static) {
if (flags & ModifierFlags.Static) {
write("static ");
}
if (flags & NodeFlags.Readonly) {
if (flags & ModifierFlags.Readonly) {
write("readonly ");
}
if (flags & NodeFlags.Abstract) {
if (flags & ModifierFlags.Abstract) {
write("abstract ");
}
}
Expand All @@ -660,7 +661,7 @@ namespace ts {
// note usage of writer. methods instead of aliases created, just to make sure we are using
// correct writer especially to handle asynchronous alias writing
emitJsDocComments(node);
if (node.flags & NodeFlags.Export) {
if (hasModifier(node, ModifierFlags.Export)) {
write("export ");
}
write("import ");
Expand Down Expand Up @@ -698,12 +699,12 @@ namespace ts {
}

function writeImportDeclaration(node: ImportDeclaration) {
if (!node.importClause && !(node.flags & NodeFlags.Export)) {
if (!node.importClause && !hasModifier(node, ModifierFlags.Export)) {
// do not write non-exported import declarations that don't have import clauses
return;
}
emitJsDocComments(node);
if (node.flags & NodeFlags.Export) {
if (hasModifier(node, ModifierFlags.Export)) {
write("export ");
}
write("import ");
Expand Down Expand Up @@ -893,7 +894,7 @@ namespace ts {
}

function isPrivateMethodTypeParameter(node: TypeParameterDeclaration) {
return node.parent.kind === SyntaxKind.MethodDeclaration && (node.parent.flags & NodeFlags.Private);
return node.parent.kind === SyntaxKind.MethodDeclaration && hasModifier(node.parent, ModifierFlags.Private);
}

function emitTypeParameters(typeParameters: TypeParameterDeclaration[]) {
Expand Down Expand Up @@ -943,7 +944,7 @@ namespace ts {

case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
if (node.parent.flags & NodeFlags.Static) {
if (hasModifier(node.parent, ModifierFlags.Static)) {
diagnosticMessage = Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
}
else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
Expand Down Expand Up @@ -1018,7 +1019,7 @@ namespace ts {
function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) {
if (constructorDeclaration) {
forEach(constructorDeclaration.parameters, param => {
if (param.flags & NodeFlags.AccessibilityModifier) {
if (hasModifier(param, ModifierFlags.AccessibilityModifier)) {
emitPropertyDeclaration(param);
}
});
Expand All @@ -1027,7 +1028,7 @@ namespace ts {

emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
if (node.flags & NodeFlags.Abstract) {
if (hasModifier(node, ModifierFlags.Abstract)) {
write("abstract ");
}

Expand Down Expand Up @@ -1077,7 +1078,7 @@ namespace ts {
}

emitJsDocComments(node);
emitClassMemberDeclarationFlags(node.flags);
emitClassMemberDeclarationFlags(getModifierFlags(node));
emitVariableDeclaration(<VariableDeclaration>node);
write(";");
writeLine();
Expand All @@ -1102,7 +1103,7 @@ namespace ts {
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) {
emitTypeOfVariableDeclarationFromTypeLiteral(node);
}
else if (!(node.flags & NodeFlags.Private)) {
else if (!hasModifier(node, ModifierFlags.Private)) {
writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError);
}
}
Expand All @@ -1119,7 +1120,7 @@ namespace ts {
// This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit
else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) {
// TODO(jfreeman): Deal with computed properties in error reporting.
if (node.flags & NodeFlags.Static) {
if (hasModifier(node, ModifierFlags.Static)) {
return symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
Expand Down Expand Up @@ -1230,9 +1231,9 @@ namespace ts {
if (node === accessors.firstAccessor) {
emitJsDocComments(accessors.getAccessor);
emitJsDocComments(accessors.setAccessor);
emitClassMemberDeclarationFlags(node.flags | (accessors.setAccessor ? 0 : NodeFlags.Readonly));
emitClassMemberDeclarationFlags(getModifierFlags(node) | (accessors.setAccessor ? 0 : ModifierFlags.Readonly));
writeTextOfNode(currentText, node.name);
if (!(node.flags & NodeFlags.Private)) {
if (!hasModifier(node, ModifierFlags.Private)) {
accessorWithTypeAnnotation = node;
let type = getTypeAnnotationFromAccessor(node);
if (!type) {
Expand Down Expand Up @@ -1263,7 +1264,7 @@ namespace ts {
let diagnosticMessage: DiagnosticMessage;
if (accessorWithTypeAnnotation.kind === SyntaxKind.SetAccessor) {
// Setters have to have type named and cannot infer it so, the type should always be named
if (accessorWithTypeAnnotation.parent.flags & NodeFlags.Static) {
if (hasModifier(accessorWithTypeAnnotation.parent, ModifierFlags.Static)) {
diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1;
Expand All @@ -1281,7 +1282,7 @@ namespace ts {
};
}
else {
if (accessorWithTypeAnnotation.flags & NodeFlags.Static) {
if (hasModifier(accessorWithTypeAnnotation, ModifierFlags.Static)) {
diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
Expand Down Expand Up @@ -1317,7 +1318,7 @@ namespace ts {
emitModuleElementDeclarationFlags(node);
}
else if (node.kind === SyntaxKind.MethodDeclaration) {
emitClassMemberDeclarationFlags(node.flags);
emitClassMemberDeclarationFlags(getModifierFlags(node));
}
if (node.kind === SyntaxKind.FunctionDeclaration) {
write("function ");
Expand Down Expand Up @@ -1347,7 +1348,7 @@ namespace ts {

if (node.kind === SyntaxKind.IndexSignature) {
// Index signature can have readonly modifier
emitClassMemberDeclarationFlags(node.flags);
emitClassMemberDeclarationFlags(getModifierFlags(node));
write("[");
}
else {
Expand Down Expand Up @@ -1378,7 +1379,7 @@ namespace ts {
emitType(node.type);
}
}
else if (node.kind !== SyntaxKind.Constructor && !(node.flags & NodeFlags.Private)) {
else if (node.kind !== SyntaxKind.Constructor && !hasModifier(node, ModifierFlags.Private)) {
writeReturnTypeAtSignature(node, getReturnTypeVisibilityError);
}

Expand Down Expand Up @@ -1415,7 +1416,7 @@ namespace ts {

case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
if (node.flags & NodeFlags.Static) {
if (hasModifier(node, ModifierFlags.Static)) {
diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
Expand Down Expand Up @@ -1481,7 +1482,7 @@ namespace ts {
node.parent.parent.kind === SyntaxKind.TypeLiteral) {
emitTypeOfVariableDeclarationFromTypeLiteral(node);
}
else if (!(node.parent.flags & NodeFlags.Private)) {
else if (!hasModifier(node.parent, ModifierFlags.Private)) {
writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError);
}

Expand Down Expand Up @@ -1517,7 +1518,7 @@ namespace ts {

case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
if (node.parent.flags & NodeFlags.Static) {
if (hasModifier(node.parent, ModifierFlags.Static)) {
return symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
Expand Down
Loading