UNPKG

ts2dart

Version:

Transpile TypeScript code to Dart

846 lines (844 loc) 37.3 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 path = require('path'); var ts = require('typescript'); var base = require('./base'); var FACADE_DEBUG = false; var DEFAULT_LIB_MARKER = '__ts2dart_default_lib'; var PROVIDER_IMPORT_MARKER = '__ts2dart_has_provider_import'; var TS2DART_PROVIDER_COMMENT = '@ts2dart_Provider'; function merge() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i - 0] = arguments[_i]; } var returnObject = {}; for (var _a = 0, args_1 = args; _a < args_1.length; _a++) { var arg = args_1[_a]; for (var _b = 0, _c = Object.getOwnPropertyNames(arg); _b < _c.length; _b++) { var key = _c[_b]; returnObject[key] = arg[key]; } } return returnObject; } var FacadeConverter = (function (_super) { __extends(FacadeConverter, _super); function FacadeConverter(transpiler) { var _this = this; _super.call(this, transpiler); this.candidateProperties = {}; this.candidateTypes = {}; this.genericMethodDeclDepth = 0; this.stdlibTypeReplacements = { 'Date': 'DateTime', 'Array': 'List', 'XMLHttpRequest': 'HttpRequest', 'Uint8Array': 'Uint8List', 'ArrayBuffer': 'ByteBuffer', 'Promise': 'Future', // Dart has two different incompatible DOM APIs // https://github.com/angular/angular/issues/2770 'Node': 'dynamic', 'Text': 'dynamic', 'Element': 'dynamic', 'Event': 'dynamic', 'HTMLElement': 'dynamic', 'HTMLAnchorElement': 'dynamic', 'HTMLStyleElement': 'dynamic', 'HTMLInputElement': 'dynamic', 'HTMLDocument': 'dynamic', 'History': 'dynamic', 'Location': 'dynamic' }; this.tsToDartTypeNames = (_a = {}, _a[DEFAULT_LIB_MARKER] = this.stdlibTypeReplacements, _a['angular2/src/facade/lang'] = { 'Date': 'DateTime' }, _a['rxjs/Observable'] = { 'Observable': 'Stream' }, _a['es6-promise/es6-promise'] = { 'Promise': 'Future' }, _a['es6-shim/es6-shim'] = { 'Promise': 'Future' }, _a ); this.es6Promises = { 'Promise.catch': function (c, context) { _this.visit(context); _this.emit('.catchError('); _this.visitList(c.arguments); _this.emit(')'); }, 'Promise.then': function (c, context) { // then() in Dart doesn't support 2 arguments. _this.visit(context); _this.emit('.then('); _this.visit(c.arguments[0]); _this.emit(')'); if (c.arguments.length > 1) { _this.emit('.catchError('); _this.visit(c.arguments[1]); _this.emit(')'); } }, 'Promise': function (c, context) { if (c.kind !== ts.SyntaxKind.NewExpression) return true; _this.assert(c, c.arguments.length === 1, 'Promise construction must take 2 arguments.'); _this.assert(c, c.arguments[0].kind === ts.SyntaxKind.ArrowFunction || c.arguments[0].kind === ts.SyntaxKind.FunctionExpression, 'Promise argument must be a function expression (or arrow function).'); var callback; if (c.arguments[0].kind === ts.SyntaxKind.ArrowFunction) { callback = c.arguments[0]; } else if (c.arguments[0].kind === ts.SyntaxKind.FunctionExpression) { callback = c.arguments[0]; } _this.assert(c, callback.parameters.length > 0 && callback.parameters.length < 3, 'Promise executor must take 1 or 2 arguments (resolve and reject).'); var completerVarName = _this.uniqueId('completer'); _this.assert(c, callback.parameters[0].name.kind === ts.SyntaxKind.Identifier, 'First argument of the Promise executor is not a straight parameter.'); var resolveParameterIdent = (callback.parameters[0].name); _this.emit('(() {'); // Create a new scope. _this.emit("Completer " + completerVarName + " = new Completer();"); _this.emit('var'); _this.emit(resolveParameterIdent.text); _this.emit("= " + completerVarName + ".complete;"); if (callback.parameters.length === 2) { _this.assert(c, callback.parameters[1].name.kind === ts.SyntaxKind.Identifier, 'First argument of the Promise executor is not a straight parameter.'); var rejectParameterIdent = (callback.parameters[1].name); _this.emit('var'); _this.emit(rejectParameterIdent.text); _this.emit("= " + completerVarName + ".completeError;"); } _this.emit('(()'); _this.visit(callback.body); _this.emit(')();'); _this.emit("return " + completerVarName + ".future;"); _this.emit('})()'); } }; this.es6Collections = { 'Map.set': function (c, context) { _this.visit(context); _this.emit('['); _this.visit(c.arguments[0]); _this.emit(']'); _this.emit('='); _this.visit(c.arguments[1]); }, 'Map.get': function (c, context) { _this.visit(context); _this.emit('['); _this.visit(c.arguments[0]); _this.emit(']'); }, 'Map.has': function (c, context) { _this.visit(context); _this.emitMethodCall('containsKey', c.arguments); }, 'Map.delete': function (c, context) { // JS Map.delete(k) returns whether k was present in the map, // convert to: // (Map.containsKey(k) && (Map.remove(k) !== null || true)) // (Map.remove(k) !== null || true) is required to always returns true // when Map.containsKey(k) _this.emit('('); _this.visit(context); _this.emitMethodCall('containsKey', c.arguments); _this.emit('&& ('); _this.visit(context); _this.emitMethodCall('remove', c.arguments); _this.emit('!= null || true ) )'); }, 'Map.forEach': function (c, context) { var cb; var params; switch (c.arguments[0].kind) { case ts.SyntaxKind.FunctionExpression: cb = (c.arguments[0]); params = cb.parameters; if (params.length !== 2) { _this.reportError(c, 'Map.forEach callback requires exactly two arguments'); return; } _this.visit(context); _this.emit('. forEach ( ('); _this.visit(params[1]); _this.emit(','); _this.visit(params[0]); _this.emit(')'); _this.visit(cb.body); _this.emit(')'); break; case ts.SyntaxKind.ArrowFunction: cb = (c.arguments[0]); params = cb.parameters; if (params.length !== 2) { _this.reportError(c, 'Map.forEach callback requires exactly two arguments'); return; } _this.visit(context); _this.emit('. forEach ( ('); _this.visit(params[1]); _this.emit(','); _this.visit(params[0]); _this.emit(')'); if (cb.body.kind !== ts.SyntaxKind.Block) { _this.emit('=>'); } _this.visit(cb.body); _this.emit(')'); break; default: _this.visit(context); _this.emit('. forEach ( ( k , v ) => ('); _this.visit(c.arguments[0]); _this.emit(') ( v , k ) )'); break; } }, 'Array.find': function (c, context) { _this.visit(context); _this.emit('. firstWhere ('); _this.visit(c.arguments[0]); _this.emit(', orElse : ( ) => null )'); } }; this.stdlibHandlers = merge(this.es6Promises, this.es6Collections, { 'Array.push': function (c, context) { _this.visit(context); _this.emitMethodCall('add', c.arguments); }, 'Array.pop': function (c, context) { _this.visit(context); _this.emitMethodCall('removeLast'); }, 'Array.shift': function (c, context) { _this.visit(context); _this.emit('. removeAt ( 0 )'); }, 'Array.unshift': function (c, context) { _this.emit('('); _this.visit(context); if (c.arguments.length === 1) { _this.emit('.. insert ( 0,'); _this.visit(c.arguments[0]); _this.emit(') ) . length'); } else { _this.emit('.. insertAll ( 0, ['); _this.visitList(c.arguments); _this.emit(']) ) . length'); } }, 'Array.map': function (c, context) { _this.visit(context); _this.emitMethodCall('map', c.arguments); _this.emitMethodCall('toList'); }, 'Array.filter': function (c, context) { _this.visit(context); _this.emitMethodCall('where', c.arguments); _this.emitMethodCall('toList'); }, 'Array.some': function (c, context) { _this.visit(context); _this.emitMethodCall('any', c.arguments); }, 'Array.slice': function (c, context) { _this.emitCall('ListWrapper.slice', [context].concat(c.arguments)); }, 'Array.splice': function (c, context) { _this.emitCall('ListWrapper.splice', [context].concat(c.arguments)); }, 'Array.concat': function (c, context) { _this.emit('( new List . from ('); _this.visit(context); _this.emit(')'); c.arguments.forEach(function (arg) { if (!_this.isNamedDefaultLibType(arg, 'Array')) { _this.reportError(arg, 'Array.concat only takes Array arguments'); } _this.emit('.. addAll ('); _this.visit(arg); _this.emit(')'); }); _this.emit(')'); }, 'Array.join': function (c, context) { _this.visit(context); if (c.arguments.length) { _this.emitMethodCall('join', c.arguments); } else { _this.emit('. join ( "," )'); } }, 'Array.reduce': function (c, context) { _this.visit(context); if (c.arguments.length >= 2) { _this.emitMethodCall('fold', [c.arguments[1], c.arguments[0]]); } else { _this.emit('. fold ( null ,'); _this.visit(c.arguments[0]); _this.emit(')'); } }, 'ArrayConstructor.isArray': function (c, context) { _this.emit('( ('); _this.visitList(c.arguments); // Should only be 1. _this.emit(')'); _this.emit('is List'); _this.emit(')'); }, 'Console.log': function (c, context) { _this.emit('print('); if (c.arguments.length === 1) { _this.visit(c.arguments[0]); } else { _this.emit('['); _this.visitList(c.arguments); _this.emit('].join(" ")'); } _this.emit(')'); }, 'RegExp.exec': function (c, context) { if (context.kind !== ts.SyntaxKind.RegularExpressionLiteral) { // Fail if the exec call isn't made directly on a regexp literal. // Multiple exec calls on the same global regexp have side effects // (each return the next match), which we can't reproduce with a simple // Dart RegExp (users should switch to some facade / wrapper instead). _this.reportError(c, 'exec is only supported on regexp literals, ' + 'to avoid side-effect of multiple calls on global regexps.'); } if (c.parent.kind === ts.SyntaxKind.ElementAccessExpression) { // The result of the exec call is used for immediate indexed access: // this use-case can be accommodated by RegExp.firstMatch, which returns // a Match instance with operator[] which returns groups (special index // 0 returns the full text of the match). _this.visit(context); _this.emitMethodCall('firstMatch', c.arguments); } else { // In the general case, we want to return a List. To transform a Match // into a List of its groups, we alias it in a local closure that we // call with the Match value. We are then able to use the group method // to generate a List large enough to hold groupCount groups + the // full text of the match at special group index 0. _this.emit('((match) => new List.generate(1 + match.groupCount, match.group))('); _this.visit(context); _this.emitMethodCall('firstMatch', c.arguments); _this.emit(')'); } }, 'RegExp.test': function (c, context) { _this.visit(context); _this.emitMethodCall('hasMatch', c.arguments); }, 'String.substr': function (c, context) { _this.reportError(c, 'substr is unsupported, use substring (but beware of the different semantics!)'); _this.visit(context); _this.emitMethodCall('substr', c.arguments); } }); this.callHandlerReplaceNew = (_b = {}, _b[DEFAULT_LIB_MARKER] = { 'Promise': true }, _b ); this.callHandlers = (_c = {}, _c[DEFAULT_LIB_MARKER] = this.stdlibHandlers, _c['angular2/manual_typings/globals'] = this.es6Collections, _c['angular2/src/facade/collection'] = { 'Map': function (c, context) { // The actual Map constructor is special cased for const calls. if (!_this.isInsideConstExpr(c)) return true; if (c.arguments.length) { _this.reportError(c, 'Arguments on a Map constructor in a const are unsupported'); } if (c.typeArguments) { _this.emit('<'); _this.visitList(c.typeArguments); _this.emit('>'); } _this.emit('{ }'); return false; } }, _c['angular2/src/core/di/forward_ref'] = { 'forwardRef': function (c, context) { // The special function forwardRef translates to an unwrapped value in Dart. var callback = c.arguments[0]; if (callback.kind !== ts.SyntaxKind.ArrowFunction) { _this.reportError(c, 'forwardRef takes only arrow functions'); return; } _this.visit(callback.body); } }, _c['angular2/src/facade/lang'] = { 'CONST_EXPR': function (c, context) { // `const` keyword is emitted in the array literal handling, as it needs to be transitive. _this.visitList(c.arguments); }, 'normalizeBlank': function (c, context) { // normalizeBlank is a noop in Dart, so erase it. _this.visitList(c.arguments); } }, _c ); this.es6CollectionsProp = { 'Map.size': function (p) { _this.visit(p.expression); _this.emit('.'); _this.emit('length'); } }; this.es6PromisesProp = { 'PromiseConstructor.resolve': function (p) { _this.emit('new '); _this.visit(p.expression); _this.emit('.value'); }, 'PromiseConstructor.reject': function (p) { _this.emit('new '); _this.visit(p.expression); _this.emit('.error'); } }; this.propertyHandlers = (_d = {}, _d[DEFAULT_LIB_MARKER] = merge(this.es6CollectionsProp, this.es6PromisesProp), _d ); this.extractPropertyNames(this.callHandlers, this.candidateProperties); this.extractPropertyNames(this.propertyHandlers, this.candidateProperties); this.extractPropertyNames(this.tsToDartTypeNames, this.candidateTypes); var _a, _b, _c, _d; } FacadeConverter.prototype.initializeTypeBasedConversion = function (tc, opts, host) { this.tc = tc; this.defaultLibLocation = ts.getDefaultLibFilePath(opts).replace(/\.d\.ts$/, ''); this.resolveModuleNames(opts, host, this.callHandlers); this.resolveModuleNames(opts, host, this.propertyHandlers); this.resolveModuleNames(opts, host, this.tsToDartTypeNames); this.resolveModuleNames(opts, host, this.callHandlerReplaceNew); }; FacadeConverter.prototype.extractPropertyNames = function (m, candidates) { for (var _i = 0, _a = Object.keys(m); _i < _a.length; _i++) { var fileName = _a[_i]; var file = m[fileName]; Object.keys(file) .map(function (propName) { return propName.substring(propName.lastIndexOf('.') + 1); }) .forEach(function (propName) { return candidates[propName] = true; }); } }; FacadeConverter.prototype.resolveModuleNames = function (opts, host, m) { for (var _i = 0, _a = Object.keys(m); _i < _a.length; _i++) { var mn = _a[_i]; var actual = void 0; var absolute = void 0; if (mn === DEFAULT_LIB_MARKER) { actual = this.defaultLibLocation; } else { var resolved = ts.resolveModuleName(mn, '', opts, host); if (!resolved.resolvedModule) continue; actual = resolved.resolvedModule.resolvedFileName.replace(/(\.d)?\.ts$/, ''); // TypeScript's resolution returns relative paths here, but uses absolute ones in // SourceFile.fileName later. Make sure to hit both use cases. absolute = path.resolve(actual); } if (FACADE_DEBUG) console.log('Resolved module', mn, '->', actual); m[actual] = m[mn]; if (absolute) m[absolute] = m[mn]; } }; /** * To avoid strongly referencing the Provider class (which could bloat binary size), Angular 2 * write providers as object literals. However the Dart transformers don't recognize this, so * ts2dart translates the special syntax `/* @ts2dart_Provider * / {provide: Class, param1: ...}` * into `const Provider(Class, param1: ...)`. */ FacadeConverter.prototype.maybeHandleProvider = function (ole) { var _this = this; if (!this.hasMarkerComment(ole, TS2DART_PROVIDER_COMMENT)) return false; var classParam; var remaining = ole.properties.filter(function (e) { if (e.kind !== ts.SyntaxKind.PropertyAssignment) { _this.reportError(e, TS2DART_PROVIDER_COMMENT + ' elements must be property assignments'); } if ('provide' === base.ident(e.name)) { classParam = e.initializer; return false; } return true; // include below. }); if (!classParam) { this.reportError(ole, 'missing provide: element'); return false; } this.emit('const Provider('); this.visit(classParam); if (remaining.length > 0) { this.emit(','); for (var i = 0; i < remaining.length; i++) { var e = remaining[i]; if (e.kind !== ts.SyntaxKind.PropertyAssignment) this.visit(e.name); this.emit(base.ident(e.name)); this.emit(':'); this.visit(e.initializer); if ((i + 1) < remaining.length) this.emit(','); } this.emit(')'); } return true; }; FacadeConverter.prototype.maybeHandleCall = function (c) { if (!this.tc) return false; var _a = this.getCallInformation(c), context = _a.context, symbol = _a.symbol; if (!symbol) { // getCallInformation returns a symbol if we understand this call. return false; } var handler = this.getHandler(c, symbol, this.callHandlers); return handler && !handler(c, context); }; FacadeConverter.prototype.handlePropertyAccess = function (pa) { if (!this.tc) return; var ident = pa.name.text; if (!this.candidateProperties.hasOwnProperty(ident)) return false; var symbol = this.tc.getSymbolAtLocation(pa.name); if (!symbol) { this.reportMissingType(pa, ident); return false; } var handler = this.getHandler(pa, symbol, this.propertyHandlers); return handler && !handler(pa); }; /** * Searches for type references that require extra imports and emits the imports as necessary. */ FacadeConverter.prototype.emitExtraImports = function (sourceFile) { var libraries = { 'XMLHttpRequest': 'dart:html', 'KeyboardEvent': 'dart:html', 'Uint8Array': 'dart:typed_arrays', 'ArrayBuffer': 'dart:typed_arrays', 'Promise': 'dart:async' }; var emitted = {}; this.emitImports(sourceFile, libraries, emitted, sourceFile); }; FacadeConverter.prototype.emitImports = function (n, libraries, emitted, sourceFile) { var _this = this; if (n.kind === ts.SyntaxKind.TypeReference) { var type = base.ident(n.typeName); if (libraries.hasOwnProperty(type)) { var toEmit = libraries[type]; if (!emitted[toEmit]) { this.emit("import \"" + toEmit + "\";"); emitted[toEmit] = true; } } } // Support for importing "Provider" in case /* @ts2dart_Provider */ comments are present. if (n.kind === ts.SyntaxKind.ImportDeclaration) { // See if there is already code importing 'Provider' from angular2/core. var id = n; if (id.moduleSpecifier.text === 'angular2/core') { if (id.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports) { var ni = id.importClause.namedBindings; for (var _i = 0, _a = ni.elements; _i < _a.length; _i++) { var nb = _a[_i]; if (base.ident(nb.name) === 'Provider') { emitted[PROVIDER_IMPORT_MARKER] = true; break; } } } } } if (!emitted[PROVIDER_IMPORT_MARKER] && this.hasMarkerComment(n, TS2DART_PROVIDER_COMMENT)) { // if 'Provider' has not been imported yet, and there's a @ts2dart_Provider, add it. this.emit("import \"package:angular2/core.dart\" show Provider;"); emitted[PROVIDER_IMPORT_MARKER] = true; } n.getChildren(sourceFile) .forEach(function (child) { return _this.emitImports(child, libraries, emitted, sourceFile); }); }; FacadeConverter.prototype.pushTypeParameterNames = function (n) { if (!n.typeParameters) return; this.genericMethodDeclDepth++; }; FacadeConverter.prototype.popTypeParameterNames = function (n) { if (!n.typeParameters) return; this.genericMethodDeclDepth--; }; FacadeConverter.prototype.resolvePropertyTypes = function (tn) { var res = {}; if (!tn || !this.tc) return res; var t = this.tc.getTypeAtLocation(tn); for (var _i = 0, _a = this.tc.getPropertiesOfType(t); _i < _a.length; _i++) { var sym = _a[_i]; var decl = sym.valueDeclaration || (sym.declarations && sym.declarations[0]); if (decl.kind !== ts.SyntaxKind.PropertyDeclaration && decl.kind !== ts.SyntaxKind.PropertySignature) { var msg = this.tc.getFullyQualifiedName(sym) + ' used for named parameter definition must be a property'; this.reportError(decl, msg); continue; } res[sym.name] = decl; } return res; }; /** * The Dart Development Compiler (DDC) has a syntax extension that uses comments to emulate * generic methods in Dart. ts2dart has to hack around this and keep track of which type names * in the current scope are actually DDC type parameters and need to be emitted in comments. * * TODO(martinprobst): Remove this once the DDC hack has made it into Dart proper. */ FacadeConverter.prototype.isGenericMethodTypeParameterName = function (name) { // Avoid checking this unless needed. if (this.genericMethodDeclDepth === 0 || !this.tc) return false; // Check if the type of the name is a TypeParameter. var t = this.tc.getTypeAtLocation(name); if (!t || (t.flags & ts.TypeFlags.TypeParameter) === 0) return false; // Check if the symbol we're looking at is the type parameter. var symbol = this.tc.getSymbolAtLocation(name); if (symbol !== t.symbol) return false; // Check that the Type Parameter has been declared by a function declaration. return symbol.declarations.some( // Constructors are handled separately. function (d) { return d.parent.kind === ts.SyntaxKind.FunctionDeclaration || d.parent.kind === ts.SyntaxKind.MethodDeclaration || d.parent.kind === ts.SyntaxKind.MethodSignature; }); }; FacadeConverter.prototype.visitTypeName = function (typeName) { if (typeName.kind !== ts.SyntaxKind.Identifier) { this.visit(typeName); return; } var ident = base.ident(typeName); if (this.isGenericMethodTypeParameterName(typeName)) { // DDC generic methods hack - all names that are type parameters to generic methods have to be // emitted in comments. this.emit('dynamic/*='); this.emit(ident); this.emit('*/'); return; } if (this.candidateTypes.hasOwnProperty(ident) && this.tc) { var symbol = this.tc.getSymbolAtLocation(typeName); if (!symbol) { this.reportMissingType(typeName, ident); return; } var fileAndName = this.getFileAndName(typeName, symbol); if (fileAndName) { var fileSubs = this.tsToDartTypeNames[fileAndName.fileName]; if (fileSubs && fileSubs.hasOwnProperty(fileAndName.qname)) { this.emit(fileSubs[fileAndName.qname]); return; } } } this.emit(ident); }; FacadeConverter.prototype.shouldEmitNew = function (c) { if (!this.tc) return true; var ci = this.getCallInformation(c); var symbol = ci.symbol; // getCallInformation returns a symbol if we understand this call. if (!symbol) return true; var loc = this.getFileAndName(c, symbol); if (!loc) return true; var fileName = loc.fileName, qname = loc.qname; var fileSubs = this.callHandlerReplaceNew[fileName]; if (!fileSubs) return true; return !fileSubs[qname]; }; FacadeConverter.prototype.getCallInformation = function (c) { var symbol; var context; var ident; var expr = c.expression; if (expr.kind === ts.SyntaxKind.Identifier) { // Function call. ident = base.ident(expr); if (!this.candidateProperties.hasOwnProperty(ident)) return {}; symbol = this.tc.getSymbolAtLocation(expr); if (!symbol) { this.reportMissingType(c, ident); return {}; } context = null; } else if (expr.kind === ts.SyntaxKind.PropertyAccessExpression) { // Method call. var pa = expr; ident = base.ident(pa.name); if (!this.candidateProperties.hasOwnProperty(ident)) return {}; symbol = this.tc.getSymbolAtLocation(pa); // Error will be reported by PropertyAccess handling below. if (!symbol) return {}; context = pa.expression; } return { context: context, symbol: symbol }; }; FacadeConverter.prototype.getHandler = function (n, symbol, m) { var loc = this.getFileAndName(n, symbol); if (!loc) return null; var fileName = loc.fileName, qname = loc.qname; var fileSubs = m[fileName]; if (!fileSubs) return null; return fileSubs[qname]; }; FacadeConverter.prototype.getFileAndName = function (n, originalSymbol) { var symbol = originalSymbol; while (symbol.flags & ts.SymbolFlags.Alias) symbol = this.tc.getAliasedSymbol(symbol); var decl = symbol.valueDeclaration; if (!decl) { // In the case of a pure declaration with no assignment, there is no value declared. // Just grab the first declaration, hoping it is declared once. if (!symbol.declarations || symbol.declarations.length === 0) { this.reportError(n, 'no declarations for symbol ' + originalSymbol.name); return null; } decl = symbol.declarations[0]; } var canonicalFileName = decl.getSourceFile().fileName.replace(/(\.d)?\.ts$/, ''); var qname = this.tc.getFullyQualifiedName(symbol); // Some Qualified Names include their file name. Might be a bug in TypeScript, // for the time being just special case. if (symbol.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Function | ts.SymbolFlags.Variable)) { qname = symbol.getName(); } if (FACADE_DEBUG) console.error('cfn:', canonicalFileName, 'qn:', qname); return { fileName: canonicalFileName, qname: qname }; }; FacadeConverter.prototype.isNamedDefaultLibType = function (node, qname) { var symbol = this.tc.getTypeAtLocation(node).getSymbol(); if (!symbol) return false; var actual = this.getFileAndName(node, symbol); return actual.fileName === this.defaultLibLocation && qname === actual.qname; }; FacadeConverter.prototype.reportMissingType = function (n, ident) { this.reportError(n, ("Untyped property access to \"" + ident + "\" which could be ") + "a special ts2dart builtin. " + "Please add type declarations to disambiguate."); }; FacadeConverter.prototype.isInsideConstExpr = function (node) { while (node.parent) { if (node.parent.kind === ts.SyntaxKind.Parameter && node.parent.initializer === node) { // initializers of parameters must be const in Dart. return true; } if (this.isConstExpr(node)) return true; node = node.parent; if (FacadeConverter.DECLARATIONS[node.kind]) { // Stop walking upwards when hitting a declaration - @ts2dart_const should only propagate // to the immediate declaration it applies to (but should be transitive in expressions). return false; } } return false; }; FacadeConverter.prototype.isConstClass = function (decl) { var _this = this; return this.hasConstComment(decl) || this.hasAnnotation(decl.decorators, 'CONST') || decl.members.some(function (m) { if (m.kind !== ts.SyntaxKind.Constructor) return false; return _this.hasAnnotation(m.decorators, 'CONST'); }); }; /** * isConstExpr returns true if the passed in expression itself is a const expression. const * expressions are marked by the special comment @ts2dart_const (expr), or by the special * function call CONST_EXPR. */ FacadeConverter.prototype.isConstExpr = function (node) { if (!node) return false; if (this.hasConstComment(node)) { return true; } return node.kind === ts.SyntaxKind.CallExpression && base.ident(node.expression) === 'CONST_EXPR'; }; FacadeConverter.prototype.hasConstComment = function (node) { return this.hasMarkerComment(node, '@ts2dart_const'); }; FacadeConverter.prototype.hasMarkerComment = function (node, markerText) { var text = node.getFullText(); var comments = ts.getLeadingCommentRanges(text, 0); if (!comments) return false; for (var _i = 0, comments_1 = comments; _i < comments_1.length; _i++) { var c = comments_1[_i]; var commentText = text.substring(c.pos, c.end); if (commentText.indexOf(markerText) !== -1) { return true; } } return false; }; FacadeConverter.prototype.emitMethodCall = function (name, args) { this.emit('.'); this.emitCall(name, args); }; FacadeConverter.prototype.emitCall = function (name, args) { this.emit(name); this.emit('('); if (args) this.visitList(args); this.emit(')'); }; FacadeConverter.DECLARATIONS = (_a = {}, _a[ts.SyntaxKind.ClassDeclaration] = true, _a[ts.SyntaxKind.FunctionDeclaration] = true, _a[ts.SyntaxKind.InterfaceDeclaration] = true, _a[ts.SyntaxKind.MethodDeclaration] = true, _a[ts.SyntaxKind.PropertyDeclaration] = true, _a[ts.SyntaxKind.PropertyDeclaration] = true, _a[ts.SyntaxKind.VariableDeclaration] = true, _a ); return FacadeConverter; var _a; }(base.TranspilerBase)); exports.FacadeConverter = FacadeConverter; //# sourceMappingURL=facade_converter.js.map