_NodeEmitterVisitor.prototype.visitBinaryOperatorExpr = function (expr) { var binaryOperator; switch (expr.operator) { case compiler_1.BinaryOperator.And: binaryOperator = ts.SyntaxKind.AmpersandAmpersandToken; break; case compiler_1.BinaryOperator.Bigger: binaryOperator = ts.SyntaxKind.GreaterThanToken; break; case compiler_1.BinaryOperator.BiggerEquals: binaryOperator = ts.SyntaxKind.GreaterThanEqualsToken; break; case compiler_1.BinaryOperator.Divide: binaryOperator = ts.SyntaxKind.SlashToken; break; case compiler_1.BinaryOperator.Equals: binaryOperator = ts.SyntaxKind.EqualsEqualsToken; break; case compiler_1.BinaryOperator.Identical: binaryOperator = ts.SyntaxKind.EqualsEqualsEqualsToken; break; case compiler_1.BinaryOperator.Lower: binaryOperator = ts.SyntaxKind.LessThanToken; break; case compiler_1.BinaryOperator.LowerEquals: binaryOperator = ts.SyntaxKind.LessThanEqualsToken; break; case compiler_1.BinaryOperator.Minus: binaryOperator = ts.SyntaxKind.MinusToken; break; case compiler_1.BinaryOperator.Modulo: binaryOperator = ts.SyntaxKind.PercentToken; break; case compiler_1.BinaryOperator.Multiply: binaryOperator = ts.SyntaxKind.AsteriskToken; break; case compiler_1.BinaryOperator.NotEquals: binaryOperator = ts.SyntaxKind.ExclamationEqualsToken; break; case compiler_1.BinaryOperator.NotIdentical: binaryOperator = ts.SyntaxKind.ExclamationEqualsEqualsToken; break; case compiler_1.BinaryOperator.Or: binaryOperator = ts.SyntaxKind.BarBarToken; break; case compiler_1.BinaryOperator.Plus: binaryOperator = ts.SyntaxKind.PlusToken; break; default: throw new Error("Unknown operator: " + expr.operator); } return this.record(expr, ts.createParen(ts.createBinary(expr.lhs.visitExpression(this, null), binaryOperator, expr.rhs.visitExpression(this, null)))); };
function createWrappedEnum(name, hostNode, statements, literalInitializer) { literalInitializer = literalInitializer || ts.createObjectLiteral(); const innerVarStmt = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ ts.createVariableDeclaration(name, undefined, literalInitializer), ])); const innerReturn = ts.createReturn(ts.createIdentifier(name)); const iife = ts.createImmediatelyInvokedFunctionExpression([ innerVarStmt, ...statements, innerReturn, ]); return updateHostNode(hostNode, ts.createParen(iife)); }
function createWrappedEnum(name, hostNode, statements, literalInitializer) { const pureFunctionComment = '@__PURE__'; literalInitializer = literalInitializer || ts.createObjectLiteral(); const innerVarStmt = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ ts.createVariableDeclaration(name, undefined, literalInitializer), ])); const innerReturn = ts.createReturn(ts.createIdentifier(name)); // NOTE: TS 2.4+ has a create IIFE helper method const iife = ts.createCall(ts.createParen(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [], undefined, ts.createBlock([ innerVarStmt, ...statements, innerReturn, ]))), undefined, []); // Update existing host node with the pure comment before the variable declaration initializer. const variableDeclaration = hostNode.declarationList.declarations[0]; const outerVarStmt = ts.updateVariableStatement(hostNode, hostNode.modifiers, ts.updateVariableDeclarationList(hostNode.declarationList, [ ts.updateVariableDeclaration(variableDeclaration, variableDeclaration.name, variableDeclaration.type, ts.addSyntheticLeadingComment(iife, ts.SyntaxKind.MultiLineCommentTrivia, pureFunctionComment, false)), ])); return outerVarStmt; }
_NodeEmitterVisitor.prototype.visitConditionalExpr = function (expr) { // TODO {chuckj}: Review use of ! on falseCase. Should it be non-nullable? return this.record(expr, ts.createParen(ts.createConditional(expr.condition.visitExpression(this, null), expr.trueCase.visitExpression(this, null), expr.falseCase.visitExpression(this, null)))); };
/** * Convert an `AST` to TypeScript code directly, without going through an intermediate `Expression` * AST. */ function astToTypescript(ast, maybeResolve, config) { var resolved = maybeResolve(ast); if (resolved !== null) { return resolved; } // Branch based on the type of expression being processed. if (ast instanceof compiler_1.ASTWithSource) { // Fall through to the underlying AST. return astToTypescript(ast.ast, maybeResolve, config); } else if (ast instanceof compiler_1.PropertyRead) { // This is a normal property read - convert the receiver to an expression and emit the correct // TypeScript expression to read the property. var receiver = astToTypescript(ast.receiver, maybeResolve, config); return ts.createPropertyAccess(receiver, ast.name); } else if (ast instanceof compiler_1.Interpolation) { return astArrayToExpression(ast.expressions, maybeResolve, config); } else if (ast instanceof compiler_1.Binary) { var lhs = astToTypescript(ast.left, maybeResolve, config); var rhs = astToTypescript(ast.right, maybeResolve, config); var op = BINARY_OPS.get(ast.operation); if (op === undefined) { throw new Error("Unsupported Binary.operation: " + ast.operation); } return ts.createBinary(lhs, op, rhs); } else if (ast instanceof compiler_1.LiteralPrimitive) { if (ast.value === undefined) { return ts.createIdentifier('undefined'); } else if (ast.value === null) { return ts.createNull(); } else { return ts.createLiteral(ast.value); } } else if (ast instanceof compiler_1.MethodCall) { var receiver = astToTypescript(ast.receiver, maybeResolve, config); var method = ts.createPropertyAccess(receiver, ast.name); var args = ast.args.map(function (expr) { return astToTypescript(expr, maybeResolve, config); }); return ts.createCall(method, undefined, args); } else if (ast instanceof compiler_1.Conditional) { var condExpr = astToTypescript(ast.condition, maybeResolve, config); var trueExpr = astToTypescript(ast.trueExp, maybeResolve, config); var falseExpr = astToTypescript(ast.falseExp, maybeResolve, config); return ts.createParen(ts.createConditional(condExpr, trueExpr, falseExpr)); } else if (ast instanceof compiler_1.LiteralArray) { var elements = ast.expressions.map(function (expr) { return astToTypescript(expr, maybeResolve, config); }); return ts.createArrayLiteral(elements); } else if (ast instanceof compiler_1.LiteralMap) { var properties = ast.keys.map(function (_a, idx) { var key = _a.key; var value = astToTypescript(ast.values[idx], maybeResolve, config); return ts.createPropertyAssignment(ts.createStringLiteral(key), value); }); return ts.createObjectLiteral(properties, true); } else if (ast instanceof compiler_1.KeyedRead) { var receiver = astToTypescript(ast.obj, maybeResolve, config); var key = astToTypescript(ast.key, maybeResolve, config); return ts.createElementAccess(receiver, key); } else if (ast instanceof compiler_1.NonNullAssert) { var expr = astToTypescript(ast.expression, maybeResolve, config); return ts.createNonNullExpression(expr); } else if (ast instanceof compiler_1.PrefixNot) { return ts.createLogicalNot(astToTypescript(ast.expression, maybeResolve, config)); } else if (ast instanceof compiler_1.SafePropertyRead) { // A safe property expression a?.b takes the form `(a != null ? a!.b : whenNull)`, where // whenNull is either of type 'any' or or 'undefined' depending on strictness. The non-null // assertion is necessary because in practice 'a' may be a method call expression, which won't // have a narrowed type when repeated in the ternary true branch. var receiver = astToTypescript(ast.receiver, maybeResolve, config); var expr = ts.createPropertyAccess(ts.createNonNullExpression(receiver), ast.name); var whenNull = config.strictSafeNavigationTypes ? UNDEFINED : NULL_AS_ANY; return safeTernary(receiver, expr, whenNull); } else if (ast instanceof compiler_1.SafeMethodCall) { var receiver = astToTypescript(ast.receiver, maybeResolve, config); // See the comment in SafePropertyRead above for an explanation of the need for the non-null // assertion here. var method = ts.createPropertyAccess(ts.createNonNullExpression(receiver), ast.name); var args = ast.args.map(function (expr) { return astToTypescript(expr, maybeResolve, config); }); var expr = ts.createCall(method, undefined, args); var whenNull = config.strictSafeNavigationTypes ? UNDEFINED : NULL_AS_ANY; return safeTernary(receiver, expr, whenNull); } else { throw new Error("Unknown node type: " + Object.getPrototypeOf(ast).constructor); } }
function safeTernary(lhs, whenNotNull, whenNull) { var notNullComp = ts.createBinary(lhs, ts.SyntaxKind.ExclamationEqualsToken, ts.createNull()); var ternary = ts.createConditional(notNullComp, whenNotNull, whenNull); return ts.createParen(ternary); }