cleanup(build): remove traceur-based Dart transpiler
This commit is contained in:
parent
3d62546314
commit
4c1e978536
|
@ -1,55 +0,0 @@
|
||||||
import {describe, it, expect} from 'angular2/test_lib';
|
|
||||||
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
|
||||||
import {IterableList} from './fixtures/facade';
|
|
||||||
|
|
||||||
export function main() {
|
|
||||||
// TODO(tbosch): For ... of is not supported by our Dart transpiler right now.
|
|
||||||
// Vojta had a traceur branch that reverted https://github.com/google/traceur-compiler/commit/2d12b2f9cea86e4f234c90dcc188b4c7a2881359
|
|
||||||
// to make it work, but we should first implement this in a proper way before we start using it!
|
|
||||||
|
|
||||||
// describe('for..of', function() {
|
|
||||||
// it('should iterate iterable', function() {
|
|
||||||
// var values = ['a', 'b', 'c'];
|
|
||||||
// var result = ListWrapper.create();
|
|
||||||
// for (var value of new IterableList(values)) {
|
|
||||||
// ListWrapper.push(result, value);
|
|
||||||
// }
|
|
||||||
// expect(result).toEqual(values);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should iterate iterable without var declaration list', function() {
|
|
||||||
// var values = ['a', 'b', 'c'];
|
|
||||||
// var result = ListWrapper.create();
|
|
||||||
// var value;
|
|
||||||
// for (value of new IterableList(values)) {
|
|
||||||
// ListWrapper.push(result, value);
|
|
||||||
// }
|
|
||||||
// expect(value).toEqual('c');
|
|
||||||
// expect(result).toEqual(values);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should iterate maps', function() {
|
|
||||||
// var values = [['a', 1], ['b', 2], ['c', 3]];
|
|
||||||
// var result = ListWrapper.create();
|
|
||||||
// var map = MapWrapper.createFromPairs(values);
|
|
||||||
// for (var [key, value] of MapWrapper.iterable(map)) {
|
|
||||||
// ListWrapper.push(result, [key, value]);
|
|
||||||
// }
|
|
||||||
// expect(result).toEqual(values);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should iterate maps without var declaration list', function() {
|
|
||||||
// var values = [['a', 1], ['b', 2], ['c', 3]];
|
|
||||||
// var result = ListWrapper.create();
|
|
||||||
// var map = MapWrapper.createFromPairs(values);
|
|
||||||
// var key, value;
|
|
||||||
// for ([key, value] of MapWrapper.iterable(map)) {
|
|
||||||
// ListWrapper.push(result, [key, value]);
|
|
||||||
// }
|
|
||||||
// expect(key).toEqual('c');
|
|
||||||
// expect(value).toEqual(3);
|
|
||||||
// expect(result).toEqual(values);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
import {describe, it, expect, IS_DARTIUM} from 'angular2/test_lib';
|
|
||||||
|
|
||||||
import {Foo, Bar} from './foo';
|
|
||||||
// TODO: Does not work, as dart does not support renaming imports
|
|
||||||
// import {Foo as F} from './fixtures/foo';
|
|
||||||
import * as fooModule from './foo';
|
|
||||||
|
|
||||||
import * as exportModule from './export';
|
|
||||||
|
|
||||||
import {Type} from 'angular2/src/facade/lang';
|
|
||||||
|
|
||||||
import {Baz} from './reexport';
|
|
||||||
|
|
||||||
export function main() {
|
|
||||||
describe('imports', function() {
|
|
||||||
it('should re-export imported vars', function() {
|
|
||||||
expect(Baz).toBe('BAZ');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work', function() {
|
|
||||||
expect(Foo).toBe('FOO');
|
|
||||||
expect(Bar).toBe('BAR');
|
|
||||||
// TODO: Does not work
|
|
||||||
// assert(F == 'FOO');
|
|
||||||
expect(fooModule.Foo).toBe('FOO');
|
|
||||||
expect(fooModule.Bar).toBe('BAR');
|
|
||||||
|
|
||||||
expect(exportModule.Foo).toBe('FOO');
|
|
||||||
expect(exportModule.Bar).toBe('BAR');
|
|
||||||
expect(exportModule.Bar1).toBe('BAR1');
|
|
||||||
expect(exportModule.Bar2).toBe('BAR2');
|
|
||||||
|
|
||||||
// Make sure Bar3 is not re-exported.
|
|
||||||
expect(function() {
|
|
||||||
exportModule.Bar3();
|
|
||||||
}).toThrowError(IS_DARTIUM ?
|
|
||||||
// Dart
|
|
||||||
"No top-level method 'exportModule.Bar3' declared.":
|
|
||||||
// JavaScript
|
|
||||||
new RegExp('.*is not a function')
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(Type).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -71,10 +71,7 @@ export function main() {
|
||||||
|
|
||||||
expect(function() {
|
expect(function() {
|
||||||
wf.name = true;
|
wf.name = true;
|
||||||
}).toThrowError(IS_DARTIUM ?
|
}).toThrowError(
|
||||||
// Dart
|
|
||||||
"type 'bool' is not a subtype of type 'String' of 'value'" :
|
|
||||||
// JavaScript
|
|
||||||
// TODO(vojta): Better error, it's not first argument, it's setting a field.
|
// TODO(vojta): Better error, it's not first argument, it's setting a field.
|
||||||
'Invalid arguments given!\n' +
|
'Invalid arguments given!\n' +
|
||||||
' - 1st argument has to be an instance of string, got true'
|
' - 1st argument has to be an instance of string, got true'
|
||||||
|
@ -86,10 +83,7 @@ export function main() {
|
||||||
it('should fail when setting wrong type value', function() {
|
it('should fail when setting wrong type value', function() {
|
||||||
expect(function() {
|
expect(function() {
|
||||||
WithFields.id = true;
|
WithFields.id = true;
|
||||||
}).toThrowError(IS_DARTIUM ?
|
}).toThrowError(
|
||||||
// Dart
|
|
||||||
"type 'bool' is not a subtype of type 'num' of 'id'" :
|
|
||||||
// JavaScript
|
|
||||||
// TODO(vojta): Better error, it's not first argument, it's setting a field.
|
// TODO(vojta): Better error, it's not first argument, it's setting a field.
|
||||||
'Invalid arguments given!\n' +
|
'Invalid arguments given!\n' +
|
||||||
' - 1st argument has to be an instance of number, got true'
|
' - 1st argument has to be an instance of number, got true'
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
import {FunctionExpression} from 'traceur/src/syntax/trees/ParseTrees';
|
|
||||||
import {ParseTreeTransformer} from 'traceur/src/codegeneration/ParseTreeTransformer';
|
|
||||||
import {FUNCTION_BODY} from 'traceur/src/syntax/trees/ParseTreeType';
|
|
||||||
import alphaRenameThisAndArguments from 'traceur/src/codegeneration/alphaRenameThisAndArguments';
|
|
||||||
import {
|
|
||||||
createFunctionBody,
|
|
||||||
createReturnStatement
|
|
||||||
} from 'traceur/src/codegeneration/ParseTreeFactory';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms an arrow function expression into a function declaration by adding a function
|
|
||||||
* body and return statement if needed.
|
|
||||||
*/
|
|
||||||
export class ArrowFunctionTransformer extends ParseTreeTransformer {
|
|
||||||
transformArrowFunctionExpression(tree) {
|
|
||||||
var body = this.transformAny(tree.body);
|
|
||||||
var parameterList = this.transformAny(tree.parameterList);
|
|
||||||
|
|
||||||
if (body.type !== FUNCTION_BODY) {
|
|
||||||
body = createFunctionBody([createReturnStatement(body)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FunctionExpression(tree.location, null, tree.functionKind, parameterList, null, [],
|
|
||||||
body);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,245 +0,0 @@
|
||||||
import {ParseTreeTransformer} from './ParseTreeTransformer';
|
|
||||||
|
|
||||||
import {
|
|
||||||
BINARY_EXPRESSION,
|
|
||||||
CALL_EXPRESSION,
|
|
||||||
IDENTIFIER_EXPRESSION,
|
|
||||||
MEMBER_EXPRESSION,
|
|
||||||
PROPERTY_METHOD_ASSIGNMENT,
|
|
||||||
SUPER_EXPRESSION,
|
|
||||||
THIS_EXPRESSION
|
|
||||||
} from 'traceur/src/syntax/trees/ParseTreeType';
|
|
||||||
|
|
||||||
import {EQUAL} from 'traceur/src/syntax/TokenType';
|
|
||||||
|
|
||||||
import {CONSTRUCTOR} from 'traceur/src/syntax/PredefinedName';
|
|
||||||
|
|
||||||
import {propName} from 'traceur/src/staticsemantics/PropName';
|
|
||||||
|
|
||||||
import {
|
|
||||||
BinaryExpression,
|
|
||||||
BindingIdentifier,
|
|
||||||
FormalParameterList,
|
|
||||||
FunctionBody,
|
|
||||||
IdentifierExpression
|
|
||||||
} from 'traceur/src/syntax/trees/ParseTrees';
|
|
||||||
|
|
||||||
import {
|
|
||||||
PropertyConstructorAssignment,
|
|
||||||
ImplementsDeclaration
|
|
||||||
} from '../syntax/trees/ParseTrees';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms class declaration:
|
|
||||||
* - rename constructor to the name of the class (default Dart constructor),
|
|
||||||
* - class fields are extracted from `this.field = expression;` in the ctor body,
|
|
||||||
* - `@CONST` annotations on the ctor result in a const constructor & final fields in Dart,
|
|
||||||
* - const constructor body is converted to an initializerList
|
|
||||||
*/
|
|
||||||
export class ClassTransformer extends ParseTreeTransformer {
|
|
||||||
constructor(idGenerator, reporter) {
|
|
||||||
super(idGenerator);
|
|
||||||
this.reporter_ = reporter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ClassDeclaration} tree
|
|
||||||
* @returns {ParseTree}
|
|
||||||
*/
|
|
||||||
transformClassDeclaration(tree) {
|
|
||||||
var className = tree.name.identifierToken.toString();
|
|
||||||
var argumentTypesMap = {};
|
|
||||||
var fields = [];
|
|
||||||
var isConst;
|
|
||||||
var hasConstructor = false;
|
|
||||||
var that = this;
|
|
||||||
|
|
||||||
tree.elements.forEach(function(elementTree, index) {
|
|
||||||
if (elementTree.type === PROPERTY_METHOD_ASSIGNMENT &&
|
|
||||||
!elementTree.isStatic &&
|
|
||||||
propName(elementTree) === CONSTRUCTOR) {
|
|
||||||
|
|
||||||
hasConstructor = true;
|
|
||||||
isConst = elementTree.annotations.some(that._isConstAnnotation);
|
|
||||||
|
|
||||||
// Store constructor argument types,
|
|
||||||
// so that we can use them to set the types of simple-assigned fields.
|
|
||||||
elementTree.parameterList.parameters.forEach(function(p) {
|
|
||||||
var binding = p.parameter.binding;
|
|
||||||
if (binding && binding.identifierToken) {
|
|
||||||
argumentTypesMap[binding.identifierToken.value] = p.typeAnnotation;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Rename "constructor" to the class name.
|
|
||||||
elementTree.name.literalToken.value = className;
|
|
||||||
|
|
||||||
// Compute the initializer list
|
|
||||||
var initializerList = [];
|
|
||||||
var superCall = that._extractSuperCall(elementTree.body);
|
|
||||||
if (isConst) {
|
|
||||||
initializerList = that._extractFieldInitializers(elementTree.body);
|
|
||||||
if (elementTree.body.statements.length > 0) {
|
|
||||||
that.reporter_.reportError(
|
|
||||||
elementTree.location,
|
|
||||||
'Const constructor body can only contain field initialization & super call');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (superCall) initializerList.push(superCall);
|
|
||||||
|
|
||||||
// Replace the `PROPERTY_METHOD_ASSIGNMENT` with a Dart specific
|
|
||||||
// `PROPERTY_CONSTRUCTOR_ASSIGNMENT`
|
|
||||||
tree.elements[index] = new PropertyConstructorAssignment(
|
|
||||||
elementTree.location,
|
|
||||||
elementTree.isStatic,
|
|
||||||
elementTree.functionKind,
|
|
||||||
elementTree.name,
|
|
||||||
elementTree.parameterList,
|
|
||||||
elementTree.typeAnnotation,
|
|
||||||
elementTree.annotations,
|
|
||||||
elementTree.body,
|
|
||||||
isConst,
|
|
||||||
initializerList
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// If no constructor exists then look to see if we should create a const constructor
|
|
||||||
// when the class is annotated with @CONST.
|
|
||||||
if (!hasConstructor) {
|
|
||||||
let constClassAnnotation = this._extractConstAnnotation(tree);
|
|
||||||
if (constClassAnnotation !== null) {
|
|
||||||
tree.elements = [(new PropertyConstructorAssignment(
|
|
||||||
constClassAnnotation.location,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
tree.name,
|
|
||||||
new FormalParameterList(constClassAnnotation.location, []),
|
|
||||||
null,
|
|
||||||
[constClassAnnotation],
|
|
||||||
new FunctionBody(constClassAnnotation.location, []),
|
|
||||||
true,
|
|
||||||
[]
|
|
||||||
))].concat(tree.elements);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let implementsAnnotation = this._extractImplementsAnnotation(tree);
|
|
||||||
if (implementsAnnotation !== null) {
|
|
||||||
tree.implements = new ImplementsDeclaration(
|
|
||||||
implementsAnnotation.location,
|
|
||||||
implementsAnnotation.args.args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the field definitions to the beginning of the class.
|
|
||||||
tree.elements = fields.concat(tree.elements);
|
|
||||||
if (isConst) {
|
|
||||||
tree.elements.forEach(function(element) {
|
|
||||||
element.isFinal = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.transformClassDeclaration(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract field initialization (`this.field = <expression>;`) from the body of the constructor.
|
|
||||||
* The init statements are removed from the body statements and returned as an array.
|
|
||||||
*/
|
|
||||||
_extractFieldInitializers(body) {
|
|
||||||
var statements = [];
|
|
||||||
var fieldInitializers = [];
|
|
||||||
body.statements.forEach(function(statement) {
|
|
||||||
var exp = statement.expression;
|
|
||||||
if (exp.type === BINARY_EXPRESSION &&
|
|
||||||
exp.operator.type === EQUAL &&
|
|
||||||
exp.left.type === MEMBER_EXPRESSION &&
|
|
||||||
exp.left.operand.type === THIS_EXPRESSION) {
|
|
||||||
// `this.field = exp` -> `field = exp`
|
|
||||||
// todo(vicb): check for `this.` on rhs, not allowed in Dart
|
|
||||||
// -> remove if possible (arguments), throw otherwise.
|
|
||||||
var fieldName = exp.left.memberName.value;
|
|
||||||
fieldInitializers.push(new BinaryExpression(
|
|
||||||
statement.location,
|
|
||||||
new IdentifierExpression(statement.location, fieldName),
|
|
||||||
EQUAL,
|
|
||||||
exp.right
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
statements.push(statement);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
body.statements = statements;
|
|
||||||
return fieldInitializers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the super call (`super(<arg list>)`) from the body of the constructor.
|
|
||||||
* When found the super call statement is removed from the body statements and returned.
|
|
||||||
*/
|
|
||||||
_extractSuperCall(body) {
|
|
||||||
var statements = [];
|
|
||||||
var superCall = null;
|
|
||||||
|
|
||||||
body.statements.forEach(function (statement) {
|
|
||||||
if (statement.expression &&
|
|
||||||
statement.expression.type === CALL_EXPRESSION &&
|
|
||||||
statement.expression.operand.type === SUPER_EXPRESSION) {
|
|
||||||
superCall = statement.expression;
|
|
||||||
} else {
|
|
||||||
statements.push(statement);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
body.statements = statements;
|
|
||||||
return superCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the @IMPLEMENTS annotation from the class annotations.
|
|
||||||
* When found the annotation is removed from the class annotations and returned.
|
|
||||||
*/
|
|
||||||
_extractImplementsAnnotation(tree) {
|
|
||||||
return this._extractAnnotation(tree, this._isImplementsAnnotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the @CONST annotation from the class annotations.
|
|
||||||
* When found the annotation is removed from the class annotations and returned.
|
|
||||||
*/
|
|
||||||
_extractConstAnnotation(tree) {
|
|
||||||
return this._extractAnnotation(tree, this._isConstAnnotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
_extractAnnotation(tree, predicate) {
|
|
||||||
var annotations = [];
|
|
||||||
var extractedAnnotation = null;
|
|
||||||
|
|
||||||
tree.annotations.forEach((annotation) => {
|
|
||||||
if (predicate(annotation)) {
|
|
||||||
extractedAnnotation = annotation;
|
|
||||||
} else {
|
|
||||||
annotations.push(annotation);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tree.annotations = annotations;
|
|
||||||
return extractedAnnotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the annotation is @CONST
|
|
||||||
*/
|
|
||||||
_isConstAnnotation(annotation) {
|
|
||||||
return annotation.name.identifierToken.value === 'CONST';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the annotation is @IMPLEMENTS
|
|
||||||
*/
|
|
||||||
_isImplementsAnnotation(annotation) {
|
|
||||||
return annotation.name.identifierToken.value === 'IMPLEMENTS';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
import {MultiTransformer} from 'traceur/src/codegeneration/MultiTransformer';
|
|
||||||
import {UniqueIdentifierGenerator} from 'traceur/src/codegeneration/UniqueIdentifierGenerator';
|
|
||||||
import {options} from 'traceur/src/Options';
|
|
||||||
|
|
||||||
import {ArrowFunctionTransformer} from './ArrowFunctionTransformer';
|
|
||||||
import {ClassTransformer} from './ClassTransformer';
|
|
||||||
import {InstanceOfTransformer} from './InstanceOfTransformer';
|
|
||||||
import {MultiVarTransformer} from './MultiVarTransformer';
|
|
||||||
import {StrictEqualityTransformer} from './StrictEqualityTransformer';
|
|
||||||
import {NamedParamsTransformer} from './NamedParamsTransformer';
|
|
||||||
import {ExportTransformer} from './ExportTransformer';
|
|
||||||
import {ForOfTransformer} from './ForOfTransformer';
|
|
||||||
import {DestructuringTransformer} from './DestructuringTransformer';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms ES6 + annotations to Dart code.
|
|
||||||
*/
|
|
||||||
export class DartTransformer extends MultiTransformer {
|
|
||||||
constructor(reporter, options) {
|
|
||||||
super(reporter, options.validate);
|
|
||||||
let idGenerator = new UniqueIdentifierGenerator();
|
|
||||||
|
|
||||||
var append = (transformer) => {
|
|
||||||
this.append((tree) => {
|
|
||||||
return new transformer(idGenerator, reporter).transformAny(tree);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
append(ArrowFunctionTransformer);
|
|
||||||
append(NamedParamsTransformer);
|
|
||||||
append(MultiVarTransformer);
|
|
||||||
append(InstanceOfTransformer);
|
|
||||||
append(StrictEqualityTransformer);
|
|
||||||
append(ClassTransformer);
|
|
||||||
append(ExportTransformer);
|
|
||||||
append(ForOfTransformer);
|
|
||||||
append(DestructuringTransformer);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
import {
|
|
||||||
COMMA_EXPRESSION,
|
|
||||||
EXPRESSION_STATEMENT
|
|
||||||
} from 'traceur/src/syntax/trees/ParseTreeType';
|
|
||||||
|
|
||||||
import {
|
|
||||||
DestructuringTransformer as TraceurDestructuringTransformer
|
|
||||||
} from 'traceur/src/codegeneration/DestructuringTransformer';
|
|
||||||
|
|
||||||
import {
|
|
||||||
createExpressionStatement
|
|
||||||
} from 'traceur/src/codegeneration/ParseTreeFactory';
|
|
||||||
|
|
||||||
export class DestructuringTransformer extends TraceurDestructuringTransformer {
|
|
||||||
/**
|
|
||||||
* Overrides formal parameters to skip processing since they are already handled
|
|
||||||
* by the NamedParamsTransformer.
|
|
||||||
*/
|
|
||||||
transformFormalParameter(tree) {
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the comma expressions created by Traceur into multiple statements.
|
|
||||||
*/
|
|
||||||
desugarBinding_(bindingTree, statements, declarationType) {
|
|
||||||
var binding = super.desugarBinding_(bindingTree, statements, declarationType);
|
|
||||||
for (var i = 0; i < statements.length; i++) {
|
|
||||||
if (statements[i].type === EXPRESSION_STATEMENT &&
|
|
||||||
statements[i].expression.type === COMMA_EXPRESSION) {
|
|
||||||
let expression = statements[i].expression;
|
|
||||||
let expressionStatements = expression.expressions.map(e => {
|
|
||||||
return createExpressionStatement(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
statements.splice(i, 1, ...expressionStatements);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return binding;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
import {ParseTreeTransformer} from './ParseTreeTransformer';
|
|
||||||
import {Map} from 'traceur/src/runtime/polyfills/Map';
|
|
||||||
import {
|
|
||||||
ExportDeclaration,
|
|
||||||
ExportSpecifierSet,
|
|
||||||
NamedExport,
|
|
||||||
EmptyStatement
|
|
||||||
} from 'traceur/src/syntax/trees/ParseTrees';
|
|
||||||
import {
|
|
||||||
IMPORT_DECLARATION,
|
|
||||||
NAMED_EXPORT
|
|
||||||
} from 'traceur/src/syntax/trees/ParseTreeType';
|
|
||||||
|
|
||||||
|
|
||||||
// Return the index of the first item that is not of IMPORT_DECLARATION type.
|
|
||||||
function getIndexOfFirstNonImportStatement(items) {
|
|
||||||
var index = 0;
|
|
||||||
|
|
||||||
while (index < items.length && items[index].type === IMPORT_DECLARATION) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms re-exports:
|
|
||||||
* ```
|
|
||||||
* import {Foo} from './foo';
|
|
||||||
* import {Bar} from './bar';
|
|
||||||
* var localVar = true;
|
|
||||||
*
|
|
||||||
* export {Foo, Bar, localVar}
|
|
||||||
*
|
|
||||||
* ===>
|
|
||||||
*
|
|
||||||
* import {Foo} from './foo';
|
|
||||||
* import {Bar} from './bar';
|
|
||||||
* var localVar = true;
|
|
||||||
*
|
|
||||||
* export {Foo} from './foo';
|
|
||||||
* export {Bar} from './bar';
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* In Dart, all variables defined in the root context of a module that don't start with
|
|
||||||
* an underscore are exported. Thus we just drop the "export" keyword for the locally defined vars.
|
|
||||||
* Variables imported from other modules need to be exported with `export './foo' show Foo`.
|
|
||||||
* This transformer drops the local exports and add the information about module path for the
|
|
||||||
* imported variables.
|
|
||||||
*/
|
|
||||||
export class ExportTransformer extends ParseTreeTransformer {
|
|
||||||
constructor(idGenerator, reporter) {
|
|
||||||
super(idGenerator);
|
|
||||||
this.reporter_ = reporter;
|
|
||||||
this.importedVars_ = null;
|
|
||||||
this.collectedExports_ = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
transformModule(tree) {
|
|
||||||
// New context for each file (module).
|
|
||||||
this.importedVars_ = new Map();
|
|
||||||
this.collectedExports_ = [];
|
|
||||||
|
|
||||||
tree = super.transformModule(tree);
|
|
||||||
|
|
||||||
// In Dart, imports and exports have to be at the top, before any other statement.
|
|
||||||
// Insert the collected exports before the first non-import statement (after all imports).
|
|
||||||
var items = tree.scriptItemList;
|
|
||||||
var index = getIndexOfFirstNonImportStatement(items);
|
|
||||||
tree.scriptItemList = items.slice(0, index).concat(this.collectedExports_, items.slice(index));
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each imported variable, store the module path where it comes from.
|
|
||||||
// For instance, `import {Foo} from './foo'` will map 'Foo' -> './foo'.
|
|
||||||
// TODO(vojta): deal with `import * as m from './foo'`.
|
|
||||||
transformImportDeclaration(tree) {
|
|
||||||
tree.importClause.specifiers.forEach((specifier) => {
|
|
||||||
this.importedVars_.set(specifier.binding.binding.identifierToken.value, tree.moduleSpecifier);
|
|
||||||
});
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
transformExportDeclaration(tree) {
|
|
||||||
if (tree.declaration.type === NAMED_EXPORT && tree.declaration.moduleSpecifier === null) {
|
|
||||||
// export {...}
|
|
||||||
tree.declaration.specifierSet.specifiers.forEach((specifier) => {
|
|
||||||
// Filter out local variables, keep only imported ones.
|
|
||||||
if (!this.importedVars_.has(specifier.lhs.value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each specifier, create a new ExportDeclaration and attach the module path (collected
|
|
||||||
// in `transformImportDeclaration`) to it.
|
|
||||||
this.collectedExports_.push(new ExportDeclaration(tree.location,
|
|
||||||
new NamedExport(tree.declaration.location, this.importedVars_.get(specifier.lhs.value),
|
|
||||||
new ExportSpecifierSet(tree.declaration.specifierSet.location, [specifier])),
|
|
||||||
tree.annotations));
|
|
||||||
});
|
|
||||||
|
|
||||||
return new EmptyStatement(tree.location);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
import {ParseTreeTransformer} from 'traceur/src/codegeneration/ParseTreeTransformer';
|
|
||||||
import {ForInStatement} from 'traceur/src/syntax/trees/ParseTrees';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms for-of into for-in.
|
|
||||||
*/
|
|
||||||
export class ForOfTransformer extends ParseTreeTransformer {
|
|
||||||
/**
|
|
||||||
* @param {ForOfStatement} tree
|
|
||||||
* @return {ParseTree}
|
|
||||||
*/
|
|
||||||
transformForOfStatement(original) {
|
|
||||||
var tree = super.transformForOfStatement(original);
|
|
||||||
return new ForInStatement(tree.location, tree.initializer, tree.collection, tree.body);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
import {INSTANCEOF} from 'traceur/src/syntax/TokenType';
|
|
||||||
import {ParseTreeTransformer} from './ParseTreeTransformer';
|
|
||||||
import {
|
|
||||||
createBinaryExpression,
|
|
||||||
createOperatorToken
|
|
||||||
} from 'traceur/src/codegeneration/ParseTreeFactory';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms `a instanceof b` to `a is b`,
|
|
||||||
*/
|
|
||||||
export class InstanceOfTransformer extends ParseTreeTransformer {
|
|
||||||
/**
|
|
||||||
* @param {BinaryExpression} tree
|
|
||||||
* @return {ParseTree}
|
|
||||||
*/
|
|
||||||
transformBinaryExpression(tree) {
|
|
||||||
tree = super.transformBinaryExpression(tree);
|
|
||||||
|
|
||||||
if (tree.operator.type === INSTANCEOF) {
|
|
||||||
return createBinaryExpression(tree.left, createOperatorToken('is'), tree.right);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
import {VariableStatement, VariableDeclarationList} from 'traceur/src/syntax/trees/ParseTrees';
|
|
||||||
|
|
||||||
import {ParseTreeTransformer} from './ParseTreeTransformer';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms `var a, b;` to `var a; var b;`
|
|
||||||
*/
|
|
||||||
export class MultiVarTransformer extends ParseTreeTransformer {
|
|
||||||
// Individual item transformer can return an array of items.
|
|
||||||
// This is used in `transformVariableStatement`.
|
|
||||||
// Otherwise this is copy/pasted from `ParseTreeTransformer`.
|
|
||||||
transformList(list) {
|
|
||||||
var transformedList = [];
|
|
||||||
var transformedItem = null;
|
|
||||||
|
|
||||||
for (var i = 0, ii = list.length; i < ii; i++) {
|
|
||||||
transformedItem = this.transformAny(list[i]);
|
|
||||||
if (Array.isArray(transformedItem)) {
|
|
||||||
transformedList = transformedList.concat(transformedItem);
|
|
||||||
} else {
|
|
||||||
transformedList.push(transformedItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return transformedList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {VariableStatement} tree
|
|
||||||
* @returns {ParseTree}
|
|
||||||
*/
|
|
||||||
transformVariableStatement(tree) {
|
|
||||||
var declarations = tree.declarations.declarations;
|
|
||||||
|
|
||||||
if (declarations.length === 1 || declarations.length === 0) {
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiple var declaration, we will split it into multiple statements.
|
|
||||||
// TODO(vojta): We can leave the multi-definition as long as they are all the same type/untyped.
|
|
||||||
return declarations.map(function(declaration) {
|
|
||||||
return new VariableStatement(tree.location, new VariableDeclarationList(tree.location,
|
|
||||||
tree.declarations.declarationType, [declaration]));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,133 +0,0 @@
|
||||||
import {ParseTreeTransformer} from './ParseTreeTransformer';
|
|
||||||
|
|
||||||
import {
|
|
||||||
BINDING_ELEMENT,
|
|
||||||
OBJECT_PATTERN,
|
|
||||||
OBJECT_LITERAL_EXPRESSION
|
|
||||||
} from 'traceur/src/syntax/trees/ParseTreeType';
|
|
||||||
|
|
||||||
import {
|
|
||||||
NamedParameterList,
|
|
||||||
ObjectPatternBindingElement
|
|
||||||
} from '../syntax/trees/ParseTrees';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms maps into named parameters:
|
|
||||||
*
|
|
||||||
* First, it transform all calls where the last argument is an object literal
|
|
||||||
* with identifier keys, as follows:
|
|
||||||
*
|
|
||||||
* f({a: 1, b: 2}) -> f(a: 1, b: 2)
|
|
||||||
*
|
|
||||||
* Second, it removes the empty object initializer from the function definition:
|
|
||||||
*
|
|
||||||
* function f({a:1, b:2} = {}){} -> f({a:1, b:2}){}
|
|
||||||
*/
|
|
||||||
export class NamedParamsTransformer extends ParseTreeTransformer {
|
|
||||||
/**
|
|
||||||
* Transform function calls.
|
|
||||||
*
|
|
||||||
* @param {CallExpression} tree
|
|
||||||
* @return {ParseTree}
|
|
||||||
*/
|
|
||||||
transformCallExpression(tree) {
|
|
||||||
tree = super.transformCallExpression(tree);
|
|
||||||
this._handleNamedParams(tree);
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform new expressions.
|
|
||||||
*
|
|
||||||
* @param {NewExpression} tree
|
|
||||||
* @return {ParseTree}
|
|
||||||
*/
|
|
||||||
transformNewExpression(tree) {
|
|
||||||
tree = super.transformNewExpression(tree);
|
|
||||||
this._handleNamedParams(tree);
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
transformAnnotation(tree) {
|
|
||||||
tree = super.transformAnnotation(tree);
|
|
||||||
if (tree.args) this._handleNamedParams(tree);
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleNamedParams(tree) {
|
|
||||||
if (this._isLastArgAnNonEmptyObjectLiteral(tree) &&
|
|
||||||
! this._isLastArgObjectLiteralWithQuotedKeys(tree)) {
|
|
||||||
this._replaceLastArgWithNamedParams(tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_isLastArgAnNonEmptyObjectLiteral(tree) {
|
|
||||||
var lastArg = this._last(tree.args.args);
|
|
||||||
if (!lastArg) return false;
|
|
||||||
|
|
||||||
var pairs = lastArg.propertyNameAndValues;
|
|
||||||
if (!pairs || pairs.length == 0) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isLastArgObjectLiteralWithQuotedKeys(tree) {
|
|
||||||
var pairs = this._last(tree.args.args).propertyNameAndValues;
|
|
||||||
|
|
||||||
for (var pair of pairs) {
|
|
||||||
var key = pair.name.literalToken.value;
|
|
||||||
if (key.charAt(0) == '"' || key.charAt(0) == "'") return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_replaceLastArgWithNamedParams(tree) {
|
|
||||||
var args = tree.args.args;
|
|
||||||
var last = this._last(args);
|
|
||||||
args[args.length - 1] = new NamedParameterList(last.location, last.propertyNameAndValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform function declaration.
|
|
||||||
*
|
|
||||||
* @param {ObjectPattern} tree
|
|
||||||
* @return {ParseTree}
|
|
||||||
*/
|
|
||||||
transformObjectPattern(tree) {
|
|
||||||
tree = super.transformObjectPattern(tree);
|
|
||||||
tree.fields = tree.fields.map(
|
|
||||||
(e) => new ObjectPatternBindingElement(e.location, e.binding, e.initializer));
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {FormalParameterList} tree
|
|
||||||
* @return {ParseTree}
|
|
||||||
*/
|
|
||||||
transformFormalParameterList(tree) {
|
|
||||||
tree = super.transformFormalParameterList(tree);
|
|
||||||
var last = this._last(tree.parameters);
|
|
||||||
if (last && this._isObjectPatternWithAnEmptyObjectInit(last.parameter)) {
|
|
||||||
last.parameter = last.parameter.binding;
|
|
||||||
}
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isObjectPatternWithAnEmptyObjectInit(tree) {
|
|
||||||
return tree.type === BINDING_ELEMENT &&
|
|
||||||
tree.binding.type === OBJECT_PATTERN &&
|
|
||||||
this._isEmptyObjectInitializer(tree.initializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
_isEmptyObjectInitializer(initializer) {
|
|
||||||
return initializer &&
|
|
||||||
initializer.type == OBJECT_LITERAL_EXPRESSION &&
|
|
||||||
initializer.propertyNameAndValues.length == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_last(array) {
|
|
||||||
if (!array || array.length == 0) return undefined;
|
|
||||||
return array[array.length - 1];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
import {
|
|
||||||
ParseTreeTransformer as TraceurParseTreeTransformer
|
|
||||||
} from 'traceur/src/codegeneration/ParseTreeTransformer';
|
|
||||||
|
|
||||||
import {
|
|
||||||
ClassFieldDeclaration,
|
|
||||||
PropertyConstructorAssignment,
|
|
||||||
NamedParameterList,
|
|
||||||
ObjectPatternBindingElement
|
|
||||||
} from '../syntax/trees/ParseTrees'
|
|
||||||
|
|
||||||
export class ParseTreeTransformer extends TraceurParseTreeTransformer {
|
|
||||||
transformClassFieldDeclaration(tree) {
|
|
||||||
var lvalue = this.transformAny(tree.lvalue);
|
|
||||||
var typeAnnotation = this.transformAny(tree.typeAnnotation);
|
|
||||||
if (lvalue === tree.lvalue && typeAnnotation === tree.typeAnnotation) {
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
return new ClassFieldDeclaration(tree.location, lvalue, typeAnnotation, initializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
transformPropertyConstructorAssignment(tree) {
|
|
||||||
tree = super.transformPropertyMethodAssignment(tree);
|
|
||||||
var initializerList = this.transformList(tree.initializerList);
|
|
||||||
if (initializerList === tree.initializerList) {
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PropertyConstructorAssignment(tree.location, tree.isStatic, tree.functionKind,
|
|
||||||
tree.name, tree.parameterList, tree.typeAnnotation, tree.annotations, tree.body, tree.isConst,
|
|
||||||
initializerList);
|
|
||||||
}
|
|
||||||
|
|
||||||
transformNamedParameterList(tree) {
|
|
||||||
var nvPairs = this.transformList(tree.parameterNameAndValues);
|
|
||||||
if (nvPairs === tree.parameterNameAndValues) {
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
return new NamedParameterList(tree.location, nvPairs);
|
|
||||||
}
|
|
||||||
|
|
||||||
transformObjectPatternBindingElement(tree) {
|
|
||||||
var binding = this.transformAny(tree.binding);
|
|
||||||
var initializer = this.transformAny(tree.initializer);
|
|
||||||
if (binding === tree.binding && initializer === tree.initializer) {
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
return new ObjectPatternBindingElement(tree.location, binding, initializer);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
import {
|
|
||||||
createArgumentList,
|
|
||||||
createCallExpression,
|
|
||||||
createIdentifierExpression
|
|
||||||
} from 'traceur/src/codegeneration/ParseTreeFactory';
|
|
||||||
|
|
||||||
import {
|
|
||||||
EQUAL_EQUAL_EQUAL,
|
|
||||||
NOT_EQUAL_EQUAL
|
|
||||||
} from 'traceur/src/syntax/TokenType';
|
|
||||||
|
|
||||||
import {ParseTreeTransformer} from './ParseTreeTransformer';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms:
|
|
||||||
* - `a === b` to `indentical(a, b)`,
|
|
||||||
* - `a !== b` to `!identical(a, b)`
|
|
||||||
*/
|
|
||||||
export class StrictEqualityTransformer extends ParseTreeTransformer {
|
|
||||||
/**
|
|
||||||
* @param {BinaryExpression} tree
|
|
||||||
* @return {ParseTree}
|
|
||||||
*/
|
|
||||||
transformBinaryExpression(tree) {
|
|
||||||
tree.left = this.transformAny(tree.left);
|
|
||||||
tree.right = this.transformAny(tree.right);
|
|
||||||
|
|
||||||
if (tree.operator.type === EQUAL_EQUAL_EQUAL) {
|
|
||||||
// `a === b` -> `identical(a, b)`
|
|
||||||
return createCallExpression(createIdentifierExpression('identical'),
|
|
||||||
createArgumentList([tree.left, tree.right]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tree.operator.type === NOT_EQUAL_EQUAL) {
|
|
||||||
// `a !== b` -> `!identical(a, b)`
|
|
||||||
// TODO(vojta): do this in a cleaner way.
|
|
||||||
return createCallExpression(createIdentifierExpression('!identical'),
|
|
||||||
createArgumentList([tree.left, tree.right]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,4 @@
|
||||||
import {Compiler as TraceurCompiler} from 'traceur/src/Compiler';
|
import {Compiler as TraceurCompiler} from 'traceur/src/Compiler';
|
||||||
import {DartTransformer} from './codegeneration/DartTransformer';
|
|
||||||
import {DartParseTreeWriter} from './outputgeneration/DartParseTreeWriter';
|
|
||||||
import {CollectingErrorReporter} from 'traceur/src/util/CollectingErrorReporter';
|
import {CollectingErrorReporter} from 'traceur/src/util/CollectingErrorReporter';
|
||||||
import {Parser} from './parser';
|
import {Parser} from './parser';
|
||||||
import {SourceFile} from 'traceur/src/syntax/SourceFile';
|
import {SourceFile} from 'traceur/src/syntax/SourceFile';
|
||||||
|
@ -13,28 +11,6 @@ export class Compiler extends TraceurCompiler {
|
||||||
this.moduleName_ = sourceRoot;
|
this.moduleName_ = sourceRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
transform(tree, moduleName = undefined) {
|
|
||||||
if (this.options_.outputLanguage.toLowerCase() === 'dart') {
|
|
||||||
var errorReporter = new CollectingErrorReporter();
|
|
||||||
var transformer = new DartTransformer(errorReporter, this.options_);
|
|
||||||
var transformedTree = transformer.transform(tree);
|
|
||||||
this.throwIfErrors(errorReporter);
|
|
||||||
return transformedTree;
|
|
||||||
} else {
|
|
||||||
return super.transform(tree, moduleName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
write(tree, outputName = undefined, sourceRoot = undefined) {
|
|
||||||
if (this.options_.outputLanguage.toLowerCase() === 'dart') {
|
|
||||||
var writer = new DartParseTreeWriter(this.moduleName_, outputName);
|
|
||||||
writer.visitAny(tree);
|
|
||||||
return writer.toString();
|
|
||||||
} else {
|
|
||||||
return super.write(tree, outputName, sourceRoot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy of the original method to use our custom Parser
|
// Copy of the original method to use our custom Parser
|
||||||
parse(content, sourceName) {
|
parse(content, sourceName) {
|
||||||
if (!content) {
|
if (!content) {
|
||||||
|
|
|
@ -1,534 +0,0 @@
|
||||||
import {CONSTRUCTOR, FROM} from 'traceur/src/syntax/PredefinedName';
|
|
||||||
import {
|
|
||||||
AT,
|
|
||||||
CLASS,
|
|
||||||
CLOSE_CURLY,
|
|
||||||
CLOSE_PAREN,
|
|
||||||
CLOSE_SQUARE,
|
|
||||||
COLON,
|
|
||||||
COMMA,
|
|
||||||
EQUAL,
|
|
||||||
EQUAL_EQUAL_EQUAL,
|
|
||||||
EXTENDS,
|
|
||||||
IMPLEMENTS,
|
|
||||||
IMPORT,
|
|
||||||
OPEN_CURLY,
|
|
||||||
OPEN_PAREN,
|
|
||||||
OBJECT_PATTERN,
|
|
||||||
OPEN_SQUARE,
|
|
||||||
PERIOD,
|
|
||||||
SEMI_COLON,
|
|
||||||
STAR,
|
|
||||||
STATIC,
|
|
||||||
VAR,
|
|
||||||
OPEN_ANGLE,
|
|
||||||
CLOSE_ANGLE
|
|
||||||
} from 'traceur/src/syntax/TokenType';
|
|
||||||
|
|
||||||
import {
|
|
||||||
GET
|
|
||||||
} from 'traceur/src/syntax/PredefinedName';
|
|
||||||
|
|
||||||
import {ParseTreeWriter as JavaScriptParseTreeWriter, ObjectLiteralExpression} from 'traceur/src/outputgeneration/ParseTreeWriter';
|
|
||||||
import {ImportedBinding, BindingIdentifier} from 'traceur/src/syntax/trees/ParseTrees';
|
|
||||||
import {IdentifierToken} from 'traceur/src/syntax/IdentifierToken';
|
|
||||||
import {EXPORT_STAR, NAMED_EXPORT} from 'traceur/src/syntax/trees/ParseTreeType';
|
|
||||||
import {typeMapping} from '../type_mapping';
|
|
||||||
|
|
||||||
export class DartParseTreeWriter extends JavaScriptParseTreeWriter {
|
|
||||||
constructor(moduleName, outputPath) {
|
|
||||||
super(outputPath);
|
|
||||||
this.libName = moduleName.replace(/\//g, '.').replace(/[^\w.\/]/g, '_');
|
|
||||||
this.annotationContextCounter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
visitEmptyStatement() {}
|
|
||||||
|
|
||||||
// CLASS FIELDS
|
|
||||||
visitPropertyVariableDeclaration(tree) {
|
|
||||||
if (tree.isStatic) {
|
|
||||||
this.write_(STATIC);
|
|
||||||
this.writeSpace_();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tree.typeAnnotation === null) {
|
|
||||||
this.write_(tree.isFinal ? 'final' : VAR);
|
|
||||||
} else {
|
|
||||||
if (tree.isFinal) {
|
|
||||||
this.write_('final');
|
|
||||||
}
|
|
||||||
this.writeTypeAndSpace_(tree.typeAnnotation);
|
|
||||||
}
|
|
||||||
this.writeSpace_();
|
|
||||||
|
|
||||||
this.visitAny(tree.name);
|
|
||||||
this.write_(SEMI_COLON);
|
|
||||||
}
|
|
||||||
|
|
||||||
// VARIABLES - types
|
|
||||||
// ```
|
|
||||||
// var foo:bool = true;
|
|
||||||
// ==>
|
|
||||||
// bool foo = true;
|
|
||||||
// ```
|
|
||||||
visitVariableDeclarationList(tree) {
|
|
||||||
// Write `var`, only if no type declaration.
|
|
||||||
if (!tree.declarations[0].typeAnnotation) {
|
|
||||||
this.write_(tree.declarationType);
|
|
||||||
this.writeSpace_();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.writeList_(tree.declarations, COMMA, true, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitVariableDeclaration(tree) {
|
|
||||||
this.writeTypeAndSpace_(tree.typeAnnotation);
|
|
||||||
this.visitAny(tree.lvalue);
|
|
||||||
|
|
||||||
if (tree.initializer !== null) {
|
|
||||||
this.writeSpace_();
|
|
||||||
this.write_(EQUAL);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.initializer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visitTemplateLiteralExpression(tree) {
|
|
||||||
if (tree.operand) {
|
|
||||||
throw new Error('tagged template strings are not supported');
|
|
||||||
}
|
|
||||||
this.writeRaw_("'''");
|
|
||||||
this.visitList(tree.elements);
|
|
||||||
this.writeRaw_("'''");
|
|
||||||
}
|
|
||||||
|
|
||||||
visitTemplateLiteralPortion(tree) {
|
|
||||||
this.writeRaw_(tree.value.toString()
|
|
||||||
.replace(/('|")/g, "\\$&")
|
|
||||||
.replace(/([^\\])\$/g, "$1\\\$")
|
|
||||||
.replace(/^\$/, '\\\$'));
|
|
||||||
}
|
|
||||||
|
|
||||||
visitLiteralExpression(tree) {
|
|
||||||
this.write_(('' + tree.literalToken).replace(/([^\\])\$/g, "$1\\\$"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// FUNCTIONS
|
|
||||||
// - remove the "function" keyword
|
|
||||||
// - type annotation infront
|
|
||||||
visitFunction_(tree) {
|
|
||||||
this.writeAnnotations_(tree.annotations);
|
|
||||||
if (tree.isAsyncFunction()) {
|
|
||||||
this.write_(tree.functionKind);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tree.isGenerator()) {
|
|
||||||
this.write_(tree.functionKind);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tree.name) {
|
|
||||||
this.writeTypeAndSpace_(tree.typeAnnotation);
|
|
||||||
this.visitAny(tree.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.write_(OPEN_PAREN);
|
|
||||||
this.visitAny(tree.parameterList);
|
|
||||||
this.write_(CLOSE_PAREN);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.body);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Class methods.
|
|
||||||
// - type annotation infront
|
|
||||||
visitPropertyMethodAssignment(tree) {
|
|
||||||
this.writeAnnotations_(tree.annotations);
|
|
||||||
|
|
||||||
if (tree.isStatic) {
|
|
||||||
this.write_(STATIC);
|
|
||||||
this.writeSpace_();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tree.isGenerator()) {
|
|
||||||
this.write_(STAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tree.isAsyncFunction()) {
|
|
||||||
this.write_(ASYNC);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.writeTypeAndSpace_(tree.typeAnnotation);
|
|
||||||
this.visitAny(tree.name);
|
|
||||||
this.write_(OPEN_PAREN);
|
|
||||||
this.visitAny(tree.parameterList);
|
|
||||||
this.write_(CLOSE_PAREN);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitFormalParameterList(tree) {
|
|
||||||
var hasPosOptionalParams = false;
|
|
||||||
var first = true;
|
|
||||||
for (var i = 0; i < tree.parameters.length; i++) {
|
|
||||||
var parameter = tree.parameters[i];
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
this.write_(COMMA);
|
|
||||||
this.writeSpace_();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasPosOptionalParams && this._isOptionalPositionParam(parameter.parameter)) {
|
|
||||||
hasPosOptionalParams = true;
|
|
||||||
this.write_(OPEN_SQUARE);
|
|
||||||
}
|
|
||||||
this.visitAny(parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasPosOptionalParams) {
|
|
||||||
this.write_(CLOSE_SQUARE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_isOptionalPositionParam(parameter) {
|
|
||||||
return parameter.initializer && parameter.binding.type !== OBJECT_PATTERN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {PropertyMethodAssignment} tree
|
|
||||||
*/
|
|
||||||
visitPropertyConstructorAssignment(tree) {
|
|
||||||
this.writeAnnotations_(tree.annotations);
|
|
||||||
|
|
||||||
if (tree.isConst) {
|
|
||||||
this.write_('const');
|
|
||||||
this.writeSpace_();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.writeTypeAndSpace_(tree.typeAnnotation);
|
|
||||||
this.visitAny(tree.name);
|
|
||||||
this.write_(OPEN_PAREN);
|
|
||||||
this.visitAny(tree.parameterList);
|
|
||||||
this.write_(CLOSE_PAREN);
|
|
||||||
if (tree.initializerList.length > 0) {
|
|
||||||
this.write_(COLON);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.writeList_(tree.initializerList, ', ');
|
|
||||||
}
|
|
||||||
if (tree.isConst) {
|
|
||||||
this.write_(SEMI_COLON);
|
|
||||||
} else {
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
normalizeType_(typeName) {
|
|
||||||
return typeMapping[typeName] || typeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FUNCTION/METHOD ARGUMENTS
|
|
||||||
// - type infront of the arg name
|
|
||||||
visitBindingElement(tree) {
|
|
||||||
this._visitBindingElement(tree, EQUAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitObjectPatternBindingElement(tree) {
|
|
||||||
this._visitBindingElement(tree, COLON);
|
|
||||||
}
|
|
||||||
|
|
||||||
_visitBindingElement(tree, initSeparator) {
|
|
||||||
// TODO(vojta): This is awful, just copy/pasted from Traceur,
|
|
||||||
// we should still clean it up.
|
|
||||||
var typeAnnotation = this.currentParameterTypeAnnotation_;
|
|
||||||
// resetting type annotation so it doesn't filter down recursively
|
|
||||||
this.currentParameterTypeAnnotation_ = null;
|
|
||||||
|
|
||||||
this.writeTypeAndSpace_(typeAnnotation);
|
|
||||||
this.visitAny(tree.binding);
|
|
||||||
|
|
||||||
if (tree.initializer) {
|
|
||||||
this.writeSpace_();
|
|
||||||
this.write_(initSeparator);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.initializer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeTypeAndSpace_(typeAnnotation) {
|
|
||||||
this.writeType_(typeAnnotation);
|
|
||||||
this.writeSpace_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
writeType_(typeAnnotation) {
|
|
||||||
if (!typeAnnotation) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var typeNameNode;
|
|
||||||
var args = [];
|
|
||||||
if (typeAnnotation.typeName) {
|
|
||||||
typeNameNode = typeAnnotation.typeName;
|
|
||||||
args = typeAnnotation.args.args;
|
|
||||||
} else {
|
|
||||||
typeNameNode = typeAnnotation;
|
|
||||||
args = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeNameNode.moduleName && typeNameNode.moduleName.name && typeNameNode.moduleName.name.value) {
|
|
||||||
this.write_(typeNameNode.moduleName.name.value);
|
|
||||||
this.write_(PERIOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(vojta): Figure out why `typeNameNode` has different structure when used with a variable.
|
|
||||||
// This should probably be fixed in Traceur.
|
|
||||||
var typeName = typeNameNode.typeToken && typeNameNode.typeToken.value || (typeNameNode.name && typeNameNode.name.value) || null;
|
|
||||||
if (!typeName) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.write_(this.normalizeType_(typeName));
|
|
||||||
if (args.length) {
|
|
||||||
this.write_(OPEN_ANGLE);
|
|
||||||
this.writeType_(args[0]);
|
|
||||||
for (var i=1; i<args.length; i++) {
|
|
||||||
this.write_(COMMA);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.writeType_(args[i]);
|
|
||||||
}
|
|
||||||
this.write_(CLOSE_ANGLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXPORTS
|
|
||||||
visitExportDeclaration(tree) {
|
|
||||||
if (tree.declaration.type === NAMED_EXPORT) {
|
|
||||||
// export {...}
|
|
||||||
// export {...} from './foo'
|
|
||||||
// export * from './foo'
|
|
||||||
|
|
||||||
if (tree.declaration.moduleSpecifier) {
|
|
||||||
if (tree.declaration.specifierSet.type === EXPORT_STAR) {
|
|
||||||
// export * from './foo'
|
|
||||||
// ===>
|
|
||||||
// export './foo';
|
|
||||||
this.write_('export');
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitModuleSpecifier(tree.declaration.moduleSpecifier);
|
|
||||||
this.write_(SEMI_COLON);
|
|
||||||
} else {
|
|
||||||
// export {Foo, Bar} from './foo'
|
|
||||||
// ===>
|
|
||||||
// export './foo' show Foo, Bar;
|
|
||||||
this.write_('export');
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitModuleSpecifier(tree.declaration.moduleSpecifier);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.write_('show');
|
|
||||||
this.writeSpace_();
|
|
||||||
this.writeList_(tree.declaration.specifierSet.specifiers, COMMA, false);
|
|
||||||
this.write_(SEMI_COLON);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// export {...}
|
|
||||||
// This case is handled in `ExportTransformer`.
|
|
||||||
throw new Error('Should never happen!');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// export var x = true
|
|
||||||
// export class Foo {}
|
|
||||||
// export function bar() {}
|
|
||||||
// Just remove "export" keyword.
|
|
||||||
this.writeAnnotations_(tree.annotations);
|
|
||||||
this.visitAny(tree.declaration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// visitExportDefault
|
|
||||||
// visitNamedExport
|
|
||||||
// visitExportSpecifier
|
|
||||||
// visitExportSpecifierSet
|
|
||||||
// visitExportStar
|
|
||||||
|
|
||||||
|
|
||||||
// IMPORTS
|
|
||||||
visitImportDeclaration(tree) {
|
|
||||||
this.write_(IMPORT);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.moduleSpecifier);
|
|
||||||
|
|
||||||
if (tree.importClause.binding) {
|
|
||||||
// Default import, not supported as dart does not distinguish
|
|
||||||
// between explicit exports and default exports
|
|
||||||
throw new Error('default imports/exports not supported');
|
|
||||||
} else {
|
|
||||||
// Regular - import list of members.
|
|
||||||
// import {Foo, Bar} from './baz';
|
|
||||||
this.visitAny(tree.importClause);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.write_(SEMI_COLON);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translate './foo' -> './foo.dart'
|
|
||||||
transformModuleUrl(url) {
|
|
||||||
var prefix = url.charAt(1) === '.' ? '' : 'package:';
|
|
||||||
return "'" + prefix + url.substring(1, url.length - 1) + ".dart'";
|
|
||||||
}
|
|
||||||
|
|
||||||
visitModuleSpecifier(tree) {
|
|
||||||
this.write_(this.transformModuleUrl(tree.token.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
visitImportSpecifier(tree) {
|
|
||||||
if (tree.name) {
|
|
||||||
throw new Error('"as" syntax not supported');
|
|
||||||
}
|
|
||||||
this.visitAny(tree.binding);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitImportedBinding(tree) {
|
|
||||||
if (tree.binding && tree.binding.identifierToken) {
|
|
||||||
var b = tree.binding;
|
|
||||||
var t = b.identifierToken;
|
|
||||||
var token = new IdentifierToken(t.location, this.normalizeType_(t.value));
|
|
||||||
var binding = new BindingIdentifier(b.location, token);
|
|
||||||
super.visitImportedBinding(new ImportedBinding(tree.location, binding));
|
|
||||||
} else {
|
|
||||||
super.visitImportedBinding(tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visitImportSpecifierSet(tree) {
|
|
||||||
if (tree.specifiers.type == STAR) {
|
|
||||||
throw new Error('"*" syntax not supported');
|
|
||||||
} else {
|
|
||||||
this.write_(' show ');
|
|
||||||
this.writeList_(tree.specifiers, COMMA, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visitModuleDeclaration(tree) {
|
|
||||||
// module import - import the entire module.
|
|
||||||
// import * as foo from './bar';
|
|
||||||
this.write_(IMPORT);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.expression);
|
|
||||||
this.write_(' as ');
|
|
||||||
this.visitAny(tree.binding);
|
|
||||||
this.write_(SEMI_COLON);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ANNOTATIONS
|
|
||||||
// TODO(vojta): this is just fixing a bug in Traceur, send a PR.
|
|
||||||
visitAnnotation(tree) {
|
|
||||||
// TODO(tbosch): Disabled the removal of control annotations (annotations in uppercase),
|
|
||||||
// as they should be handeled by a transformer and right now lead
|
|
||||||
// to errors (unused import) in dartanalyzer.
|
|
||||||
// if (tree.name.identifierToken) {
|
|
||||||
// var nameValue = tree.name.identifierToken.value;
|
|
||||||
// if (nameValue === nameValue.toUpperCase()) {
|
|
||||||
// // control annotations for transpiler
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
this.write_(AT);
|
|
||||||
this.visitAny(tree.name);
|
|
||||||
|
|
||||||
if (tree.args !== null) {
|
|
||||||
this.annotationContextCounter++;
|
|
||||||
this.write_(OPEN_PAREN);
|
|
||||||
this.writeList_(tree.args.args, COMMA, false);
|
|
||||||
this.write_(CLOSE_PAREN);
|
|
||||||
this.annotationContextCounter--;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.writeSpace_()
|
|
||||||
}
|
|
||||||
|
|
||||||
visitGetAccessor(tree) {
|
|
||||||
this.writeAnnotations_(tree.annotations);
|
|
||||||
if (tree.isStatic) {
|
|
||||||
this.write_(STATIC);
|
|
||||||
this.writeSpace_();
|
|
||||||
}
|
|
||||||
this.writeTypeAndSpace_(tree.typeAnnotation);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.write_(GET);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.name);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitObjectLiteralExpression(tree) {
|
|
||||||
if (this.annotationContextCounter) {
|
|
||||||
this.write_('const');
|
|
||||||
}
|
|
||||||
super.visitObjectLiteralExpression(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitArrayLiteralExpression(tree) {
|
|
||||||
if (this.annotationContextCounter) {
|
|
||||||
this.write_('const');
|
|
||||||
}
|
|
||||||
super.visitArrayLiteralExpression(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitNewExpression(tree) {
|
|
||||||
if (this.annotationContextCounter) {
|
|
||||||
this.write_('const');
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.operand);
|
|
||||||
this.visitAny(tree.args);
|
|
||||||
} else {
|
|
||||||
super.visitNewExpression(tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visitNamedParameterList(tree) {
|
|
||||||
this.writeList_(tree.parameterNameAndValues, COMMA, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitClassDeclaration(tree) {
|
|
||||||
this.writeAnnotations_(tree.annotations);
|
|
||||||
this.write_(CLASS);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.name);
|
|
||||||
|
|
||||||
if (tree.superClass) {
|
|
||||||
this.writeSpace_();
|
|
||||||
this.write_(EXTENDS);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.visitAny(tree.superClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tree.implements) {
|
|
||||||
this.writeSpace_();
|
|
||||||
this.write_(IMPLEMENTS);
|
|
||||||
this.writeSpace_();
|
|
||||||
this.writeList_(tree.implements.interfaces, COMMA, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.writeSpace_();
|
|
||||||
this.write_(OPEN_CURLY);
|
|
||||||
this.writelnList_(tree.elements);
|
|
||||||
this.write_(CLOSE_CURLY);
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return "library " + this._transformLibName(this.libName) + ";\n" + super.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
_transformLibName(libName) {
|
|
||||||
var parts = libName.split('.');
|
|
||||||
for (var part of parts) {
|
|
||||||
if (DART_RESERVED_WORDS.indexOf(part) != -1) {
|
|
||||||
return libName + '_dart';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return libName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// see: https://www.dartlang.org/docs/dart-up-and-running/ch02.html for a full list.
|
|
||||||
const DART_RESERVED_WORDS = ['if', 'switch', 'for', 'class'];
|
|
|
@ -1,5 +0,0 @@
|
||||||
export var CLASS_FIELD_DECLARATION = 'CLASS_FIELD_DECLARATION';
|
|
||||||
export var PROPERTY_CONSTRUCTOR_ASSIGNMENT = 'PROPERTY_CONSTRUCTOR_ASSIGNMENT';
|
|
||||||
export var NAMED_PARAMETER_LIST = 'NAMED_PARAMETER_LIST';
|
|
||||||
export var OBJECT_PATTERN_BINDING_ELEMENT = 'OBJECT_PATTERN_BINDING_ELEMENT';
|
|
||||||
export var IMPLEMENTS_DECLARATION = "IMPLEMENTS_DECLARATION";
|
|
|
@ -1,177 +0,0 @@
|
||||||
import {ParseTree} from 'traceur/src/syntax/trees/ParseTree';
|
|
||||||
|
|
||||||
import {PropertyMethodAssignment} from 'traceur/src/syntax/trees/ParseTrees';
|
|
||||||
|
|
||||||
import * as ParseTreeType from './ParseTreeType';
|
|
||||||
|
|
||||||
// Class constructor
|
|
||||||
export class PropertyConstructorAssignment extends PropertyMethodAssignment {
|
|
||||||
/**
|
|
||||||
* @param {SourceRange} location
|
|
||||||
* @param {boolean} isStatic
|
|
||||||
* @param {Token} functionKind
|
|
||||||
* @param {ParseTree} name
|
|
||||||
* @param {FormalParameterList} parameterList
|
|
||||||
* @param {ParseTree} typeAnnotation
|
|
||||||
* @param {Array.<ParseTree>} annotations
|
|
||||||
* @param {FunctionBody} body
|
|
||||||
* @param {boolean} isConst
|
|
||||||
* @param {ParseTree} initializerList
|
|
||||||
*/
|
|
||||||
constructor(location, isStatic, functionKind, name, parameterList, typeAnnotation, annotations,
|
|
||||||
body, isConst, initializerList) {
|
|
||||||
super(location, isStatic, functionKind, name, parameterList, typeAnnotation, annotations,
|
|
||||||
body);
|
|
||||||
this.isConst = isConst;
|
|
||||||
this.initializerList = initializerList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ParseTreeTransformer} transformer
|
|
||||||
*/
|
|
||||||
transform(transformer) {
|
|
||||||
if (transformer.transformPropertyConstructorAssignment) {
|
|
||||||
return transformer.transformPropertyConstructorAssignment(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ParseTreeVisitor} visitor
|
|
||||||
*/
|
|
||||||
visit(visitor) {
|
|
||||||
if (visitor.visitPropertyConstructorAssignment) {
|
|
||||||
visitor.visitPropertyConstructorAssignment(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {ParseTreeType}
|
|
||||||
*/
|
|
||||||
get type() {
|
|
||||||
return PROPERTY_CONSTRUCTOR_ASSIGNMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var PROPERTY_CONSTRUCTOR_ASSIGNMENT = ParseTreeType.PROPERTY_CONSTRUCTOR_ASSIGNMENT;
|
|
||||||
|
|
||||||
// Named parameters
|
|
||||||
export class NamedParameterList extends ParseTree {
|
|
||||||
/**
|
|
||||||
* @param {SourceRange} location
|
|
||||||
* @param {Array.<ParseTree>} parameterNameAndValues
|
|
||||||
*/
|
|
||||||
constructor(location, parameterNameAndValues) {
|
|
||||||
super(location);
|
|
||||||
this.parameterNameAndValues = parameterNameAndValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ParseTreeTransformer} transformer
|
|
||||||
*/
|
|
||||||
transform(transformer) {
|
|
||||||
if (transformer.transformNamedParameterList) {
|
|
||||||
return transformer.transformNamedParameterList(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ParseTreeVisitor} visitor
|
|
||||||
*/
|
|
||||||
visit(visitor) {
|
|
||||||
if (visitor.visitNamedParameterList) {
|
|
||||||
visitor.visitNamedParameterList(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {ParseTreeType}
|
|
||||||
*/
|
|
||||||
get type() {
|
|
||||||
return NAMED_PARAMETER_LIST;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var NAMED_PARAMETER_LIST = ParseTreeType.NAMED_PARAMETER_LIST;
|
|
||||||
|
|
||||||
// Object pattern binding element
|
|
||||||
export class ObjectPatternBindingElement extends ParseTree {
|
|
||||||
/**
|
|
||||||
* @param {SourceRange} location
|
|
||||||
* @param {BindingIdentifier|ObjectPattern|ArrayPattern} binding
|
|
||||||
* @param {ParseTree} initializer
|
|
||||||
*/
|
|
||||||
constructor(location, binding, initializer) {
|
|
||||||
super(location);
|
|
||||||
this.binding = binding;
|
|
||||||
this.initializer = initializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ParseTreeTransformer} transformer
|
|
||||||
*/
|
|
||||||
transform(transformer) {
|
|
||||||
if (transformer.transformObjectPatternBindingElement) {
|
|
||||||
return transformer.transformObjectPatternBindingElement(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ParseTreeVisitor} visitor
|
|
||||||
*/
|
|
||||||
visit(visitor) {
|
|
||||||
if (visitor.visitObjectPatternBindingElement) {
|
|
||||||
visitor.visitObjectPatternBindingElement(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {ParseTreeType}
|
|
||||||
*/
|
|
||||||
get type() {
|
|
||||||
return OBJECT_PATTERN_BINDING_ELEMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ImplementsDeclaration extends ParseTree {
|
|
||||||
/**
|
|
||||||
* @param {SourceRange} location
|
|
||||||
* @param {Array.<ParseTree>} interfaces
|
|
||||||
*/
|
|
||||||
constructor(location, interfaces) {
|
|
||||||
super(location);
|
|
||||||
this.interfaces = interfaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ParseTreeTransformer} transformer
|
|
||||||
*/
|
|
||||||
transform(transformer) {
|
|
||||||
if (transformer.transformImplementsDeclaration) {
|
|
||||||
return transformer.transformImplementsDeclaration(this);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ParseTreeVisitor} visitor
|
|
||||||
*/
|
|
||||||
visit(visitor) {
|
|
||||||
if (visitor.visitImplementsDeclaration) {
|
|
||||||
visitor.visitImplementsDeclaration(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {ParseTreeType}
|
|
||||||
*/
|
|
||||||
get type() {
|
|
||||||
return ParseTreeType.IMPLEMENTS_DECLARATION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var OBJECT_PATTERN_BINDING_ELEMENT = ParseTreeType.OBJECT_PATTERN_BINDING_ELEMENT;
|
|
|
@ -1,11 +0,0 @@
|
||||||
// JS -> Dart
|
|
||||||
export var typeMapping = {
|
|
||||||
'number': 'num',
|
|
||||||
'boolean': 'bool',
|
|
||||||
'string': 'String',
|
|
||||||
'any': 'dynamic',
|
|
||||||
'Promise': 'Future',
|
|
||||||
'Observable': 'Stream',
|
|
||||||
'Date': 'DateTime',
|
|
||||||
'StringMap': 'Map'
|
|
||||||
};
|
|
|
@ -12,83 +12,6 @@ var DEFAULT_OPTIONS = {
|
||||||
memberVariables: true // parse class fields
|
memberVariables: true // parse class fields
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('transpile to dart', function(){
|
|
||||||
|
|
||||||
var options;
|
|
||||||
beforeEach(function() {
|
|
||||||
options = merge(DEFAULT_OPTIONS, {outputLanguage: 'dart'});
|
|
||||||
});
|
|
||||||
|
|
||||||
// https://github.com/angular/angular/issues/509
|
|
||||||
describe('string interpolation', function() {
|
|
||||||
it('should not interpolate inside old quotes', function(){
|
|
||||||
var result = compiler.compile(options, "test.js",
|
|
||||||
"var a:number = 1;" +
|
|
||||||
"var s1:string = \"${a}\";" +
|
|
||||||
"var s2:string = '\\${a}';" +
|
|
||||||
"var s3:string = '$a';");
|
|
||||||
expect(result.js).toBe("library test;\n" +
|
|
||||||
"num a = 1;\n" +
|
|
||||||
"String s1 = \"\\${a}\";\n" +
|
|
||||||
"String s2 = '\\${a}';\n" +
|
|
||||||
"String s3 = '\\$a';\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not interpolate without curly braces', function() {
|
|
||||||
var result = compiler.compile(options, "test.js",
|
|
||||||
"var a:number = 1;" +
|
|
||||||
"var s1:string = `$a`;" +
|
|
||||||
"var s2:string = `\\$a`;");
|
|
||||||
expect(result.js).toBe("library test;\n" +
|
|
||||||
"num a = 1;\n" +
|
|
||||||
"String s1 = '''\\$a''';\n" +
|
|
||||||
"String s2 = '''\\$a''';\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should interpolate inside template quotes', function() {
|
|
||||||
var result = compiler.compile(options, "test.js",
|
|
||||||
"var a:number = 1;" +
|
|
||||||
"var s1:string = `${a}`;");
|
|
||||||
expect(result.js).toBe("library test;\n" +
|
|
||||||
"num a = 1;\n" +
|
|
||||||
"String s1 = '''${a}''';\n");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('generic', function() {
|
|
||||||
|
|
||||||
it('should support types without generics', function() {
|
|
||||||
var result = compiler.compile(options, "test.js",
|
|
||||||
"var a:List = [];");
|
|
||||||
expect(result.js).toBe("library test;\nList a = [];\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support one level generics', function() {
|
|
||||||
var result = compiler.compile(options, "test.js",
|
|
||||||
"var a:List<string> = [];");
|
|
||||||
expect(result.js).toBe("library test;\nList<String> a = [];\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support multiple one level generics', function() {
|
|
||||||
var result = compiler.compile(options, "test.js",
|
|
||||||
"var a:List<A,B> = [];");
|
|
||||||
expect(result.js).toBe("library test;\nList<A, B> a = [];\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support nested generics', function() {
|
|
||||||
var result = compiler.compile(options, "test.js",
|
|
||||||
"var a:List<A<B>> = [];");
|
|
||||||
expect(result.js).toBe("library test;\nList<A<B>> a = [];\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add dart suffix to reserved words', function() {
|
|
||||||
var result = compiler.compile(options, "project/if.js",
|
|
||||||
"var a;");
|
|
||||||
expect(result.js).toBe("library project.if_dart;\nvar a;\n");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('transpile to es6', function() {
|
describe('transpile to es6', function() {
|
||||||
var options;
|
var options;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue