MCPcopy Create free account
hub / github.com/angular/angular / TcbExprTranslator

Class TcbExprTranslator

packages/compiler/src/typecheck/expression.ts:58–417  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

56}
57
58class TcbExprTranslator implements AstVisitor {
59 constructor(
60 private maybeResolve: (ast: AST) => TcbExpr | null,
61 private config: TypeCheckingConfig,
62 ) {}
63
64 translate(ast: AST): TcbExpr {
65 if (ast instanceof ASTWithSource) {
66 ast = ast.ast;
67 }
68
69 // First attempt to let any custom resolution logic provide a translation for the given node.
70 const resolved = this.maybeResolve(ast);
71 if (resolved !== null) {
72 return resolved;
73 }
74
75 return ast.visit(this);
76 }
77
78 visitUnary(ast: Unary): TcbExpr {
79 const expr = this.translate(ast.expr);
80 const node = new TcbExpr(`${ast.operator}${expr.print()}`);
81 return node.wrapForTypeChecker().addParseSpanInfo(ast.sourceSpan);
82 }
83
84 visitBinary(ast: Binary): TcbExpr {
85 const lhs = this.translate(ast.left);
86 const rhs = this.translate(ast.right);
87 lhs.wrapForTypeChecker();
88 rhs.wrapForTypeChecker();
89 const expression = `${lhs.print()} ${ast.operation} ${rhs.print()}`;
90 const node = new TcbExpr(
91 ast.operation === '??' || ast.operation === '**' ? `(${expression})` : expression,
92 );
93 node.addParseSpanInfo(ast.sourceSpan);
94 return node;
95 }
96
97 visitChain(ast: Chain): TcbExpr {
98 const elements = ast.expressions.map((expr) => this.translate(expr).print());
99 const node = new TcbExpr(elements.join(', '));
100 node.wrapForTypeChecker();
101 node.addParseSpanInfo(ast.sourceSpan);
102 return node;
103 }
104
105 visitConditional(ast: Conditional): TcbExpr {
106 const condExpr = this.translate(ast.condition);
107 const trueExpr = this.translate(ast.trueExp);
108 // Wrap `falseExpr` in parens so that the trailing parse span info is not attributed to the
109 // whole conditional.
110 // In the following example, the last source span comment (5,6) could be seen as the
111 // trailing comment for _either_ the whole conditional expression _or_ just the `falseExpr` that
112 // is immediately before it:
113 // `conditional /*1,2*/ ? trueExpr /*3,4*/ : falseExpr /*5,6*/`
114 // This should be instead be `conditional /*1,2*/ ? trueExpr /*3,4*/ : (falseExpr /*5,6*/)`
115 const falseExpr = this.translate(ast.falseExp).wrapForTypeChecker();

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected