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'; } from 'traceur/src/syntax/trees/ParseTrees';
import { import {
PropertyConstructorAssignment PropertyConstructorAssignment,
ImplementsDeclaration
} from '../syntax/trees/ParseTrees'; } 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. // Add the field definitions to the beginning of the class.
tree.elements = fields.concat(tree.elements); tree.elements = fields.concat(tree.elements);
if (isConst) { if (isConst) {
@ -187,26 +195,38 @@ export class ClassTransformer extends ParseTreeTransformer {
return superCall; 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. * Extract the @CONST annotation from the class annotations.
* When found the annotation is removed from the class annotations and returned. * When found the annotation is removed from the class annotations and returned.
*/ */
_extractConstAnnotation(tree) { _extractConstAnnotation(tree) {
return this._extractAnnotation(tree, this._isConstAnnotation);
}
_extractAnnotation(tree, predicate) {
var annotations = []; var annotations = [];
var constAnnotation = null; var extractedAnnotation = null;
var that = this;
tree.annotations.forEach((annotation) => { tree.annotations.forEach((annotation) => {
if (that._isConstAnnotation(annotation)) { if (predicate(annotation)) {
constAnnotation = annotation; extractedAnnotation = annotation;
} else { } else {
annotations.push(annotation); annotations.push(annotation);
} }
}); });
tree.annotations = annotations; tree.annotations = annotations;
return constAnnotation; return extractedAnnotation;
} }
/** /**
* Returns true if the annotation is @CONST * Returns true if the annotation is @CONST
*/ */
@ -214,4 +234,11 @@ export class ClassTransformer extends ParseTreeTransformer {
return annotation.name.identifierToken.value === 'CONST'; 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 {CONSTRUCTOR, FROM} from 'traceur/src/syntax/PredefinedName';
import { import {
AT, AT,
CLASS,
CLOSE_CURLY, CLOSE_CURLY,
CLOSE_PAREN, CLOSE_PAREN,
CLOSE_SQUARE, CLOSE_SQUARE,
@ -8,6 +9,8 @@ import {
COMMA, COMMA,
EQUAL, EQUAL,
EQUAL_EQUAL_EQUAL, EQUAL_EQUAL_EQUAL,
EXTENDS,
IMPLEMENTS,
IMPORT, IMPORT,
OPEN_CURLY, OPEN_CURLY,
OPEN_PAREN, OPEN_PAREN,
@ -456,6 +459,32 @@ export class DartParseTreeWriter extends JavaScriptParseTreeWriter {
this.writeList_(tree.parameterNameAndValues, COMMA, false); 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() { toString() {
return "library " + this.libName + ";\n" + super.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 PROPERTY_CONSTRUCTOR_ASSIGNMENT = 'PROPERTY_CONSTRUCTOR_ASSIGNMENT';
export var NAMED_PARAMETER_LIST = 'NAMED_PARAMETER_LIST'; export var NAMED_PARAMETER_LIST = 'NAMED_PARAMETER_LIST';
export var OBJECT_PATTERN_BINDING_ELEMENT = 'OBJECT_PATTERN_BINDING_ELEMENT'; 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; 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; var OBJECT_PATTERN_BINDING_ELEMENT = ParseTreeType.OBJECT_PATTERN_BINDING_ELEMENT;