refactor(compiler-cli): `attachComments()` now expects a defined `leadingComments` array (#39076)
Previously the value passed to `AstFactory.attachComments()` could be `undefined` which is counterintuitive, since why attach something that doesn't exist? Now it expects there to be a defined array. Further it no longer returns a statement. Both these aspects of the interface were designed to make the usage simpler but has the result of complicating the implemenation. The `ExpressionTranslatorVisitor` now has a helper function (`attachComments()`) to handle `leadingComments` being undefined and also returning the statement. This keeps the usage in the translator simple, while ensuring that the `AstFactory` API is not influenced by how it is used. PR Close #39076
This commit is contained in:
parent
70e13dc31e
commit
05672ab136
|
@ -10,17 +10,16 @@ import * as t from '@babel/types';
|
||||||
import {AstFactory, BinaryOperator, LeadingComment, ObjectLiteralProperty, SourceMapRange, TemplateLiteral, VariableDeclarationType} from '../../../../src/ngtsc/translator';
|
import {AstFactory, BinaryOperator, LeadingComment, ObjectLiteralProperty, SourceMapRange, TemplateLiteral, VariableDeclarationType} from '../../../../src/ngtsc/translator';
|
||||||
import {assert} from '../utils';
|
import {assert} from '../utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Babel flavored implementation of the AstFactory.
|
||||||
|
*/
|
||||||
export class BabelAstFactory implements AstFactory<t.Statement, t.Expression> {
|
export class BabelAstFactory implements AstFactory<t.Statement, t.Expression> {
|
||||||
attachComments(statement: t.Statement, leadingComments: LeadingComment[]|undefined): t.Statement {
|
attachComments(statement: t.Statement, leadingComments: LeadingComment[]): void {
|
||||||
if (leadingComments === undefined) {
|
|
||||||
return statement;
|
|
||||||
}
|
|
||||||
// We must process the comments in reverse because `t.addComment()` will add new ones in front.
|
// We must process the comments in reverse because `t.addComment()` will add new ones in front.
|
||||||
for (let i = leadingComments.length - 1; i >= 0; i--) {
|
for (let i = leadingComments.length - 1; i >= 0; i--) {
|
||||||
const comment = leadingComments[i];
|
const comment = leadingComments[i];
|
||||||
t.addComment(statement, 'leading', comment.toString(), !comment.multiline);
|
t.addComment(statement, 'leading', comment.toString(), !comment.multiline);
|
||||||
}
|
}
|
||||||
return statement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createArrayLiteral = t.arrayExpression;
|
createArrayLiteral = t.arrayExpression;
|
||||||
|
|
|
@ -17,11 +17,10 @@ export interface AstFactory<TStatement, TExpression> {
|
||||||
/**
|
/**
|
||||||
* Attach the `leadingComments` to the given `statement` node.
|
* Attach the `leadingComments` to the given `statement` node.
|
||||||
*
|
*
|
||||||
* @param statement the statement where the comment is to be attached.
|
* @param statement the statement where the comments are to be attached.
|
||||||
* @param leadingComments the comments to attach.
|
* @param leadingComments the comments to attach.
|
||||||
* @returns the node passed in as `statement` with the comments attached.
|
|
||||||
*/
|
*/
|
||||||
attachComments(statement: TStatement, leadingComments: LeadingComment[]|undefined): TStatement;
|
attachComments(statement: TStatement, leadingComments: LeadingComment[]): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a literal array expresion (e.g. `[expr1, expr2]`).
|
* Create a literal array expresion (e.g. `[expr1, expr2]`).
|
||||||
|
|
|
@ -61,14 +61,14 @@ export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.E
|
||||||
const varType = this.downlevelVariableDeclarations ?
|
const varType = this.downlevelVariableDeclarations ?
|
||||||
'var' :
|
'var' :
|
||||||
stmt.hasModifier(o.StmtModifier.Final) ? 'const' : 'let';
|
stmt.hasModifier(o.StmtModifier.Final) ? 'const' : 'let';
|
||||||
return this.factory.attachComments(
|
return this.attachComments(
|
||||||
this.factory.createVariableDeclaration(
|
this.factory.createVariableDeclaration(
|
||||||
stmt.name, stmt.value?.visitExpression(this, context.withExpressionMode), varType),
|
stmt.name, stmt.value?.visitExpression(this, context.withExpressionMode), varType),
|
||||||
stmt.leadingComments);
|
stmt.leadingComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, context: Context): TStatement {
|
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, context: Context): TStatement {
|
||||||
return this.factory.attachComments(
|
return this.attachComments(
|
||||||
this.factory.createFunctionDeclaration(
|
this.factory.createFunctionDeclaration(
|
||||||
stmt.name, stmt.params.map(param => param.name),
|
stmt.name, stmt.params.map(param => param.name),
|
||||||
this.factory.createBlock(
|
this.factory.createBlock(
|
||||||
|
@ -77,14 +77,14 @@ export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.E
|
||||||
}
|
}
|
||||||
|
|
||||||
visitExpressionStmt(stmt: o.ExpressionStatement, context: Context): TStatement {
|
visitExpressionStmt(stmt: o.ExpressionStatement, context: Context): TStatement {
|
||||||
return this.factory.attachComments(
|
return this.attachComments(
|
||||||
this.factory.createExpressionStatement(
|
this.factory.createExpressionStatement(
|
||||||
stmt.expr.visitExpression(this, context.withStatementMode)),
|
stmt.expr.visitExpression(this, context.withStatementMode)),
|
||||||
stmt.leadingComments);
|
stmt.leadingComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitReturnStmt(stmt: o.ReturnStatement, context: Context): TStatement {
|
visitReturnStmt(stmt: o.ReturnStatement, context: Context): TStatement {
|
||||||
return this.factory.attachComments(
|
return this.attachComments(
|
||||||
this.factory.createReturnStatement(
|
this.factory.createReturnStatement(
|
||||||
stmt.value.visitExpression(this, context.withExpressionMode)),
|
stmt.value.visitExpression(this, context.withExpressionMode)),
|
||||||
stmt.leadingComments);
|
stmt.leadingComments);
|
||||||
|
@ -95,7 +95,7 @@ export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.E
|
||||||
}
|
}
|
||||||
|
|
||||||
visitIfStmt(stmt: o.IfStmt, context: Context): TStatement {
|
visitIfStmt(stmt: o.IfStmt, context: Context): TStatement {
|
||||||
return this.factory.attachComments(
|
return this.attachComments(
|
||||||
this.factory.createIfStatement(
|
this.factory.createIfStatement(
|
||||||
stmt.condition.visitExpression(this, context),
|
stmt.condition.visitExpression(this, context),
|
||||||
this.factory.createBlock(
|
this.factory.createBlock(
|
||||||
|
@ -111,7 +111,7 @@ export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.E
|
||||||
}
|
}
|
||||||
|
|
||||||
visitThrowStmt(stmt: o.ThrowStmt, context: Context): TStatement {
|
visitThrowStmt(stmt: o.ThrowStmt, context: Context): TStatement {
|
||||||
return this.factory.attachComments(
|
return this.attachComments(
|
||||||
this.factory.createThrowStatement(
|
this.factory.createThrowStatement(
|
||||||
stmt.error.visitExpression(this, context.withExpressionMode)),
|
stmt.error.visitExpression(this, context.withExpressionMode)),
|
||||||
stmt.leadingComments);
|
stmt.leadingComments);
|
||||||
|
@ -387,6 +387,14 @@ export class ExpressionTranslatorVisitor<TStatement, TExpression> implements o.E
|
||||||
T {
|
T {
|
||||||
return this.factory.setSourceMapRange(ast, createRange(span));
|
return this.factory.setSourceMapRange(ast, createRange(span));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private attachComments(statement: TStatement, leadingComments: o.LeadingComment[]|undefined):
|
||||||
|
TStatement {
|
||||||
|
if (leadingComments !== undefined) {
|
||||||
|
this.factory.attachComments(statement, leadingComments);
|
||||||
|
}
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -234,12 +234,7 @@ export function createTemplateTail(cooked: string, raw: string): ts.TemplateTail
|
||||||
* @param statement The statement that will have comments attached.
|
* @param statement The statement that will have comments attached.
|
||||||
* @param leadingComments The comments to attach to the statement.
|
* @param leadingComments The comments to attach to the statement.
|
||||||
*/
|
*/
|
||||||
export function attachComments<T extends ts.Statement>(
|
export function attachComments(statement: ts.Statement, leadingComments: LeadingComment[]): void {
|
||||||
statement: T, leadingComments: LeadingComment[]|undefined): T {
|
|
||||||
if (leadingComments === undefined) {
|
|
||||||
return statement;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const comment of leadingComments) {
|
for (const comment of leadingComments) {
|
||||||
const commentKind = comment.multiline ? ts.SyntaxKind.MultiLineCommentTrivia :
|
const commentKind = comment.multiline ? ts.SyntaxKind.MultiLineCommentTrivia :
|
||||||
ts.SyntaxKind.SingleLineCommentTrivia;
|
ts.SyntaxKind.SingleLineCommentTrivia;
|
||||||
|
@ -252,5 +247,4 @@ export function attachComments<T extends ts.Statement>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return statement;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,7 +287,7 @@ export class NodeEmitterVisitor implements StatementVisitor, ExpressionVisitor {
|
||||||
if (tsNode && !this._nodeMap.has(tsNode)) {
|
if (tsNode && !this._nodeMap.has(tsNode)) {
|
||||||
this._nodeMap.set(tsNode, ngNode);
|
this._nodeMap.set(tsNode, ngNode);
|
||||||
}
|
}
|
||||||
if (tsNode !== null && ngNode instanceof Statement) {
|
if (tsNode !== null && ngNode instanceof Statement && ngNode.leadingComments !== undefined) {
|
||||||
attachComments(tsNode as unknown as ts.Statement, ngNode.leadingComments);
|
attachComments(tsNode as unknown as ts.Statement, ngNode.leadingComments);
|
||||||
}
|
}
|
||||||
return tsNode as RecordedNode<T>;
|
return tsNode as RecordedNode<T>;
|
||||||
|
|
Loading…
Reference in New Issue