feat(transpiler): implement @IMPLEMENTS

This commit is contained in:
vsavkin 2014-12-22 14:15:18 -08:00
parent a37950293a
commit 965f70bfbe
5 changed files with 122 additions and 6 deletions

View File

@ -0,0 +1,22 @@
import {ddescribe, describe, it, expect, IS_DARTIUM} from 'test_lib/test_lib';
import {IMPLEMENTS} from './fixtures/annotations';
class Interface1 {}
class Interface2 {}
@IMPLEMENTS(Interface1, Interface2)
class SomeClass {}
export function main() {
describe('interfaces', function() {
//TODO: remvoe when interfaces are supported in AtScript
if (IS_DARTIUM) {
it('should work', function () {
var s = new SomeClass();
expect(s instanceof Interface1).toBeTrue();
expect(s instanceof Interface2).toBeTrue();
});
}
});
}

View File

@ -25,7 +25,8 @@ import {
} from 'traceur/src/syntax/trees/ParseTrees';
import {
PropertyConstructorAssignment
PropertyConstructorAssignment,
ImplementsDeclaration
} from '../syntax/trees/ParseTrees';
/**
@ -122,6 +123,13 @@ export class ClassTransformer extends ParseTreeTransformer {
}
}
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) {
@ -187,26 +195,38 @@ export class ClassTransformer extends ParseTreeTransformer {
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 constAnnotation = null;
var that = this;
var extractedAnnotation = null;
tree.annotations.forEach((annotation) => {
if (that._isConstAnnotation(annotation)) {
constAnnotation = annotation;
if (predicate(annotation)) {
extractedAnnotation = annotation;
} else {
annotations.push(annotation);
}
});
tree.annotations = annotations;
return constAnnotation;
return extractedAnnotation;
}
/**
* Returns true if the annotation is @CONST
*/
@ -214,4 +234,11 @@ export class ClassTransformer extends ParseTreeTransformer {
return annotation.name.identifierToken.value === 'CONST';
}
/**
* Returns true if the annotation is @IMPLEMENTS
*/
_isImplementsAnnotation(annotation) {
return annotation.name.identifierToken.value === 'IMPLEMENTS';
}
}

View File

@ -1,6 +1,7 @@
import {CONSTRUCTOR, FROM} from 'traceur/src/syntax/PredefinedName';
import {
AT,
CLASS,
CLOSE_CURLY,
CLOSE_PAREN,
CLOSE_SQUARE,
@ -8,6 +9,8 @@ import {
COMMA,
EQUAL,
EQUAL_EQUAL_EQUAL,
EXTENDS,
IMPLEMENTS,
IMPORT,
OPEN_CURLY,
OPEN_PAREN,
@ -456,6 +459,32 @@ export class DartParseTreeWriter extends JavaScriptParseTreeWriter {
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.libName + ";\n" + super.toString();
}

View File

@ -2,3 +2,4 @@ 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";

View File

@ -137,4 +137,41 @@ export class ObjectPatternBindingElement extends ParseTree {
return OBJECT_PATTERN_BINDING_ELEMENT;
}
}
export class ImplementsDeclaration extends ParseTree {
/**
* @param {SourceRange} location
* @param {Array.<ParseTree>} interfaces
*/
constructor(location, interfaces) {
this.location = 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;