UNPKG

ts2dart

Version:

Transpile TypeScript code to Dart

177 lines (175 loc) 7.54 kB
"use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var ts = require('typescript'); var base = require('./base'); var ModuleTranspiler = (function (_super) { __extends(ModuleTranspiler, _super); function ModuleTranspiler(tr, fc, generateLibraryName) { _super.call(this, tr); this.fc = fc; this.generateLibraryName = generateLibraryName; } ModuleTranspiler.prototype.visitNode = function (node) { switch (node.kind) { case ts.SyntaxKind.SourceFile: var sf = node; if (this.generateLibraryName) { this.emit('library'); this.emit(this.getLibraryName(sf.fileName)); this.emit(';'); } this.fc.emitExtraImports(sf); ts.forEachChild(sf, this.visit.bind(this)); break; case ts.SyntaxKind.EndOfFileToken: ts.forEachChild(node, this.visit.bind(this)); break; case ts.SyntaxKind.ImportDeclaration: var importDecl = node; if (importDecl.importClause) { if (this.isEmptyImport(importDecl)) return true; this.emit('import'); this.visitExternalModuleReferenceExpr(importDecl.moduleSpecifier); this.visit(importDecl.importClause); } else { this.reportError(importDecl, 'bare import is unsupported'); } this.emit(';'); break; case ts.SyntaxKind.ImportClause: var importClause = node; if (importClause.name) this.fc.visitTypeName(importClause.name); if (importClause.namedBindings) { this.visit(importClause.namedBindings); } break; case ts.SyntaxKind.NamespaceImport: var nsImport = node; this.emit('as'); this.fc.visitTypeName(nsImport.name); break; case ts.SyntaxKind.NamedImports: this.emit('show'); var used = this.filterImports(node.elements); if (used.length === 0) { this.reportError(node, 'internal error, used imports must not be empty'); } this.visitList(used); break; case ts.SyntaxKind.NamedExports: var exportElements = node.elements; this.emit('show'); if (exportElements.length === 0) this.reportError(node, 'empty export list'); this.visitList(node.elements); break; case ts.SyntaxKind.ImportSpecifier: case ts.SyntaxKind.ExportSpecifier: var spec = node; if (spec.propertyName) { this.reportError(spec.propertyName, 'import/export renames are unsupported in Dart'); } this.fc.visitTypeName(spec.name); break; case ts.SyntaxKind.ExportDeclaration: var exportDecl = node; this.emit('export'); if (exportDecl.moduleSpecifier) { this.visitExternalModuleReferenceExpr(exportDecl.moduleSpecifier); } else { this.reportError(node, 're-exports must have a module URL (export x from "./y").'); } if (exportDecl.exportClause) this.visit(exportDecl.exportClause); this.emit(';'); break; case ts.SyntaxKind.ImportEqualsDeclaration: var importEqDecl = node; this.emit('import'); this.visit(importEqDecl.moduleReference); this.emit('as'); this.fc.visitTypeName(importEqDecl.name); this.emit(';'); break; case ts.SyntaxKind.ExternalModuleReference: this.visitExternalModuleReferenceExpr(node.expression); break; default: return false; } return true; }; ModuleTranspiler.isIgnoredImport = function (e) { // TODO: unify with facade_converter.ts var name = base.ident(e.name); switch (name) { case 'CONST': case 'CONST_EXPR': case 'normalizeBlank': case 'forwardRef': case 'ABSTRACT': case 'IMPLEMENTS': return true; default: return false; } }; ModuleTranspiler.prototype.visitExternalModuleReferenceExpr = function (expr) { // TODO: what if this isn't a string literal? var moduleName = expr; var text = moduleName.text; if (text.match(/^\.\//)) { // Strip './' to be more Dart-idiomatic. text = text.substring(2); } else if (!text.match(/^\.\.\//)) { // Replace '@angular' with 'angular2' for Dart. text = text.replace(/^@angular\//, 'angular2/'); // Unprefixed/absolute imports are package imports. text = 'package:' + text; } this.emit(JSON.stringify(text + '.dart')); }; ModuleTranspiler.prototype.isEmptyImport = function (n) { var bindings = n.importClause.namedBindings; if (bindings.kind !== ts.SyntaxKind.NamedImports) return false; var elements = bindings.elements; // An import list being empty *after* filtering is ok, but if it's empty in the code itself, // it's nonsensical code, so probably a programming error. if (elements.length === 0) this.reportError(n, 'empty import list'); return elements.every(ModuleTranspiler.isIgnoredImport); }; ModuleTranspiler.prototype.filterImports = function (ns) { return ns.filter(function (e) { return !ModuleTranspiler.isIgnoredImport(e); }); }; ModuleTranspiler.prototype.getLibraryName = function (fileName) { fileName = this.getRelativeFileName(fileName); var parts = fileName.split('/'); return parts.filter(function (p) { return p.length > 0; }) .map(function (p) { return p.replace(/^@/, ''); }) .map(function (p) { return p.replace(/[^\w.]/g, '_'); }) .map(function (p) { return p.replace(/\.[jt]s$/g, ''); }) .map(function (p) { return ModuleTranspiler.DART_RESERVED_WORDS.indexOf(p) !== -1 ? '_' + p : p; }) .join('.'); }; // For the Dart keyword list see // https://www.dartlang.org/docs/dart-up-and-running/ch02.html#keywords ModuleTranspiler.DART_RESERVED_WORDS = ('assert break case catch class const continue default do else enum extends false final ' + 'finally for if in is new null rethrow return super switch this throw true try let void ' + 'while with') .split(/ /); return ModuleTranspiler; }(base.TranspilerBase)); exports.__esModule = true; exports["default"] = ModuleTranspiler; //# sourceMappingURL=module.js.map