Skip to content

Commit 965f70b

Browse files
committed
feat(transpiler): implement @implements
1 parent a379502 commit 965f70b

File tree

5 files changed

+122
-6
lines changed

5 files changed

+122
-6
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {ddescribe, describe, it, expect, IS_DARTIUM} from 'test_lib/test_lib';
2+
import {IMPLEMENTS} from './fixtures/annotations';
3+
4+
class Interface1 {}
5+
class Interface2 {}
6+
7+
@IMPLEMENTS(Interface1, Interface2)
8+
class SomeClass {}
9+
10+
export function main() {
11+
describe('interfaces', function() {
12+
//TODO: remvoe when interfaces are supported in AtScript
13+
if (IS_DARTIUM) {
14+
it('should work', function () {
15+
var s = new SomeClass();
16+
expect(s instanceof Interface1).toBeTrue();
17+
expect(s instanceof Interface2).toBeTrue();
18+
});
19+
}
20+
});
21+
22+
}

tools/transpiler/src/codegeneration/ClassTransformer.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ import {
2525
} from 'traceur/src/syntax/trees/ParseTrees';
2626

2727
import {
28-
PropertyConstructorAssignment
28+
PropertyConstructorAssignment,
29+
ImplementsDeclaration
2930
} from '../syntax/trees/ParseTrees';
3031

3132
/**
@@ -122,6 +123,13 @@ export class ClassTransformer extends ParseTreeTransformer {
122123
}
123124
}
124125

126+
let implementsAnnotation = this._extractImplementsAnnotation(tree);
127+
if (implementsAnnotation !== null) {
128+
tree.implements = new ImplementsDeclaration(
129+
implementsAnnotation.location,
130+
implementsAnnotation.args.args);
131+
}
132+
125133
// Add the field definitions to the beginning of the class.
126134
tree.elements = fields.concat(tree.elements);
127135
if (isConst) {
@@ -187,31 +195,50 @@ export class ClassTransformer extends ParseTreeTransformer {
187195
return superCall;
188196
}
189197

198+
/**
199+
* Extract the @IMPLEMENTS annotation from the class annotations.
200+
* When found the annotation is removed from the class annotations and returned.
201+
*/
202+
_extractImplementsAnnotation(tree) {
203+
return this._extractAnnotation(tree, this._isImplementsAnnotation);
204+
}
205+
190206
/**
191207
* Extract the @CONST annotation from the class annotations.
192208
* When found the annotation is removed from the class annotations and returned.
193209
*/
194210
_extractConstAnnotation(tree) {
211+
return this._extractAnnotation(tree, this._isConstAnnotation);
212+
}
213+
214+
_extractAnnotation(tree, predicate) {
195215
var annotations = [];
196-
var constAnnotation = null;
197-
var that = this;
216+
var extractedAnnotation = null;
198217

199218
tree.annotations.forEach((annotation) => {
200-
if (that._isConstAnnotation(annotation)) {
201-
constAnnotation = annotation;
219+
if (predicate(annotation)) {
220+
extractedAnnotation = annotation;
202221
} else {
203222
annotations.push(annotation);
204223
}
205224
});
206225

207226
tree.annotations = annotations;
208-
return constAnnotation;
227+
return extractedAnnotation;
209228
}
229+
210230
/**
211231
* Returns true if the annotation is @CONST
212232
*/
213233
_isConstAnnotation(annotation) {
214234
return annotation.name.identifierToken.value === 'CONST';
215235
}
216236

237+
/**
238+
* Returns true if the annotation is @IMPLEMENTS
239+
*/
240+
_isImplementsAnnotation(annotation) {
241+
return annotation.name.identifierToken.value === 'IMPLEMENTS';
242+
}
243+
217244
}

tools/transpiler/src/outputgeneration/DartParseTreeWriter.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import {CONSTRUCTOR, FROM} from 'traceur/src/syntax/PredefinedName';
22
import {
33
AT,
4+
CLASS,
45
CLOSE_CURLY,
56
CLOSE_PAREN,
67
CLOSE_SQUARE,
78
COLON,
89
COMMA,
910
EQUAL,
1011
EQUAL_EQUAL_EQUAL,
12+
EXTENDS,
13+
IMPLEMENTS,
1114
IMPORT,
1215
OPEN_CURLY,
1316
OPEN_PAREN,
@@ -456,6 +459,32 @@ export class DartParseTreeWriter extends JavaScriptParseTreeWriter {
456459
this.writeList_(tree.parameterNameAndValues, COMMA, false);
457460
}
458461

462+
visitClassDeclaration(tree) {
463+
this.writeAnnotations_(tree.annotations);
464+
this.write_(CLASS);
465+
this.writeSpace_();
466+
this.visitAny(tree.name);
467+
468+
if (tree.superClass) {
469+
this.writeSpace_();
470+
this.write_(EXTENDS);
471+
this.writeSpace_();
472+
this.visitAny(tree.superClass);
473+
}
474+
475+
if (tree.implements) {
476+
this.writeSpace_();
477+
this.write_(IMPLEMENTS);
478+
this.writeSpace_();
479+
this.writeList_(tree.implements.interfaces, COMMA, false);
480+
}
481+
482+
this.writeSpace_();
483+
this.write_(OPEN_CURLY);
484+
this.writelnList_(tree.elements);
485+
this.write_(CLOSE_CURLY);
486+
}
487+
459488
toString() {
460489
return "library " + this.libName + ";\n" + super.toString();
461490
}

tools/transpiler/src/syntax/trees/ParseTreeType.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export var CLASS_FIELD_DECLARATION = 'CLASS_FIELD_DECLARATION';
22
export var PROPERTY_CONSTRUCTOR_ASSIGNMENT = 'PROPERTY_CONSTRUCTOR_ASSIGNMENT';
33
export var NAMED_PARAMETER_LIST = 'NAMED_PARAMETER_LIST';
44
export var OBJECT_PATTERN_BINDING_ELEMENT = 'OBJECT_PATTERN_BINDING_ELEMENT';
5+
export var IMPLEMENTS_DECLARATION = "IMPLEMENTS_DECLARATION";

tools/transpiler/src/syntax/trees/ParseTrees.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,41 @@ export class ObjectPatternBindingElement extends ParseTree {
137137
return OBJECT_PATTERN_BINDING_ELEMENT;
138138
}
139139
}
140+
141+
export class ImplementsDeclaration extends ParseTree {
142+
/**
143+
* @param {SourceRange} location
144+
* @param {Array.<ParseTree>} interfaces
145+
*/
146+
constructor(location, interfaces) {
147+
this.location = location;
148+
this.interfaces = interfaces;
149+
}
150+
151+
/**
152+
* @param {ParseTreeTransformer} transformer
153+
*/
154+
transform(transformer) {
155+
if (transformer.transformImplementsDeclaration) {
156+
return transformer.transformImplementsDeclaration(this);
157+
}
158+
return this;
159+
}
160+
161+
/**
162+
* @param {ParseTreeVisitor} visitor
163+
*/
164+
visit(visitor) {
165+
if (visitor.visitImplementsDeclaration) {
166+
visitor.visitImplementsDeclaration(this);
167+
}
168+
}
169+
170+
/**
171+
* @type {ParseTreeType}
172+
*/
173+
get type() {
174+
return ParseTreeType.IMPLEMENTS_DECLARATION;
175+
}
176+
}
140177
var OBJECT_PATTERN_BINDING_ELEMENT = ParseTreeType.OBJECT_PATTERN_BINDING_ELEMENT;

0 commit comments

Comments
 (0)