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:
Pete Bacon Darwin 2020-10-01 13:43:26 +01:00 committed by Joey Perrott
parent 70e13dc31e
commit 05672ab136
5 changed files with 22 additions and 22 deletions

View File

@ -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;

View File

@ -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]`).

View File

@ -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;
}
} }
/** /**

View File

@ -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;
} }

View File

@ -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>;