Skip to content

Commit b809c53

Browse files
authored
Updated handling of types with constructor members (the new() method) (dart-archive#66)
1 parent 9bcb146 commit b809c53

File tree

7 files changed

+652
-246
lines changed

7 files changed

+652
-246
lines changed

lib/base.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export class ImportSummary {
6969
asPrefix: string;
7070
}
7171

72+
export type Constructor = ts.ConstructorDeclaration|ts.ConstructSignatureDeclaration;
7273
export type ClassLike = ts.ClassLikeDeclaration|ts.InterfaceDeclaration;
7374
export type NamedDeclaration = ClassLike|ts.PropertyDeclaration|ts.VariableDeclaration|
7475
ts.MethodDeclaration|ts.ModuleDeclaration|ts.FunctionDeclaration;
@@ -115,7 +116,8 @@ export function isExtendsClause(heritageClause: ts.HeritageClause) {
115116
return heritageClause.token === ts.SyntaxKind.ExtendsKeyword &&
116117
!ts.isInterfaceDeclaration(heritageClause.parent);
117118
}
118-
export function isConstructor(n: ts.Node): boolean {
119+
120+
export function isConstructor(n: ts.Node): n is Constructor {
119121
return ts.isConstructorDeclaration(n) || ts.isConstructSignatureDeclaration(n);
120122
}
121123

@@ -274,6 +276,16 @@ export function copyLocation(src: ts.Node, dest: ts.Node) {
274276
dest.parent = src.parent;
275277
}
276278

279+
export function cloneNodeArray<T extends ts.Node>(src?: ts.NodeArray<T>): ts.NodeArray<T>|
280+
undefined {
281+
if (!src) {
282+
return undefined;
283+
}
284+
const clone = ts.createNodeArray(src.map(ts.getMutableClone));
285+
copyNodeArrayLocation(src, clone);
286+
return clone;
287+
}
288+
277289
export function copyNodeArrayLocation(src: ts.TextRange, dest: ts.NodeArray<any>) {
278290
dest.pos = src.pos;
279291
dest.end = src.end;

lib/declaration.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ export default class DeclarationTranspiler extends base.TranspilerBase {
295295
let propertyDecl = <ts.PropertyDeclaration|ts.VariableDeclaration>node;
296296
// We need to emit these as properties not fields.
297297
if (!this.promoteFunctionLikeMembers || !isFunctionLikeProperty(propertyDecl, this.tc)) {
298+
// Suppress the prototype member
299+
if (base.ident(propertyDecl.name) === 'prototype') {
300+
return;
301+
}
298302
orderedGroups.push([node]);
299303
return;
300304
}
@@ -611,18 +615,17 @@ export default class DeclarationTranspiler extends base.TranspilerBase {
611615
this.emit('/* WARNING: export assignment not yet supported. */\n');
612616
break;
613617
case ts.SyntaxKind.TypeAliasDeclaration: {
614-
// Object literal type alias declarations can be treated like interface declarations.
615-
let alias = <ts.TypeAliasDeclaration>node;
616-
let type = alias.type;
617-
if (type.kind === ts.SyntaxKind.TypeLiteral) {
618-
let literal = <ts.TypeLiteralNode>type;
618+
const alias = <ts.TypeAliasDeclaration>node;
619+
const type = alias.type;
620+
if (ts.isTypeLiteralNode(type)) {
621+
// Object literal type alias declarations can be treated like interface declarations.
622+
const literal = type;
619623
this.emit('@anonymous\n@JS()\n');
620624
this.visitClassLikeHelper(
621625
'abstract class', literal, alias.name, alias.typeParameters, null);
622-
} else if (type.kind === ts.SyntaxKind.FunctionType) {
626+
} else if (ts.isFunctionTypeNode(type)) {
623627
// Function type alias definitions are equivalent to dart typedefs.
624-
this.visitFunctionTypedefInterface(
625-
base.ident(alias.name), type as ts.FunctionTypeNode, alias.typeParameters);
628+
this.visitFunctionTypedefInterface(base.ident(alias.name), type, alias.typeParameters);
626629
} else {
627630
this.enterCodeComment();
628631
if (ts.isMappedTypeNode(alias.type)) {
@@ -691,6 +694,17 @@ export default class DeclarationTranspiler extends base.TranspilerBase {
691694
case ts.SyntaxKind.Constructor:
692695
case ts.SyntaxKind.ConstructSignature: {
693696
const ctorDecl = <ts.ConstructorDeclaration>node;
697+
if (ts.isTypeLiteralNode(node.parent)) {
698+
// All constructors within TypeLiteralNodes should have been merged into corresponding
699+
// classes. The only exception is this case, where there exist aliases to those literals.
700+
this.emit('// Skipping constructor from aliased type.\n');
701+
this.enterCodeComment();
702+
this.emit('new');
703+
this.visitParameters(ctorDecl.parameters, {namesOnly: false});
704+
this.emitNoSpace(';');
705+
this.exitCodeComment();
706+
break;
707+
}
694708
// Find containing class name.
695709
let classDecl = base.getEnclosingClass(ctorDecl);
696710
if (!classDecl) this.reportError(ctorDecl, 'cannot find outer class node');
@@ -802,7 +816,7 @@ export default class DeclarationTranspiler extends base.TranspilerBase {
802816
this.fc.visitTypeName(name);
803817
}
804818

805-
if (fn.typeParameters) {
819+
if (fn.typeParameters && fn.typeParameters.length > 0) {
806820
let insideComment = this.insideCodeComment;
807821
if (!insideComment) {
808822
this.enterCodeComment();
@@ -928,7 +942,7 @@ export default class DeclarationTranspiler extends base.TranspilerBase {
928942
this.emitNoSpace('Extensions');
929943
}
930944

931-
if (typeParameters) {
945+
if (typeParameters && typeParameters.length > 0) {
932946
this.emit('<');
933947
this.enterTypeArguments();
934948
this.visitList(typeParameters);

lib/main.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ export class Transpiler {
194194
});
195195

196196
sourceFiles.forEach((f: ts.SourceFile) => {
197-
const dartCode = this.translate(f);
197+
const dartCode = this.translate(f, fileSet);
198198

199199
if (destination) {
200200
const outputFile = this.getOutputPath(path.resolve(f.fileName), destination);
@@ -219,7 +219,7 @@ export class Transpiler {
219219
.filter(
220220
(sourceFile: ts.SourceFile) =>
221221
(!sourceFile.fileName.match(/\.d\.ts$/) && !!sourceFile.fileName.match(/\.[jt]s$/)))
222-
.forEach((f) => paths[f.fileName] = this.translate(f));
222+
.forEach((f) => paths[f.fileName] = this.translate(f, new Set([f.fileName])));
223223
this.checkForErrors(program);
224224
return paths;
225225
}
@@ -278,7 +278,7 @@ export class Transpiler {
278278
this.outputStack.pop();
279279
}
280280

281-
private translate(sourceFile: ts.SourceFile): string {
281+
private translate(sourceFile: ts.SourceFile, fileSet: Set<string>): string {
282282
this.currentFile = sourceFile;
283283
this.outputs = [];
284284
this.outputStack = [];
@@ -288,7 +288,7 @@ export class Transpiler {
288288
}
289289

290290
this.lastCommentIdx = -1;
291-
merge.normalizeSourceFile(sourceFile, this.fc, this.options.explicitStatic);
291+
merge.normalizeSourceFile(sourceFile, this.fc, fileSet, this.options.explicitStatic);
292292
this.pushContext(OutputContext.Default);
293293
this.visit(sourceFile);
294294
this.popContext();

0 commit comments

Comments
 (0)