feat(compiler): support a non-null postfix assert (#16672)
Template expressions can now use a post-fix `!` operator that asserts the target of the operator is not null. This is similar to the TypeScript non-null assert operator. Expressions generated in factories will be generated with the non-null assert operator. Closes: #10855
This commit is contained in:

committed by
Jason Aden

parent
2eca6e67e1
commit
b9521b568f
@ -344,6 +344,10 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
|
||||
ast.condition.visitExpression(this, ctx);
|
||||
return null;
|
||||
}
|
||||
visitAssertNotNullExpr(ast: o.AssertNotNull, ctx: EmitterVisitorContext): any {
|
||||
ast.condition.visitExpression(this, ctx);
|
||||
return null;
|
||||
}
|
||||
abstract visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any;
|
||||
abstract visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, context: any): any;
|
||||
|
||||
|
@ -377,6 +377,15 @@ export class NotExpr extends Expression {
|
||||
}
|
||||
}
|
||||
|
||||
export class AssertNotNull extends Expression {
|
||||
constructor(public condition: Expression, sourceSpan?: ParseSourceSpan|null) {
|
||||
super(condition.type, sourceSpan);
|
||||
}
|
||||
visitExpression(visitor: ExpressionVisitor, context: any): any {
|
||||
return visitor.visitAssertNotNullExpr(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
export class CastExpr extends Expression {
|
||||
constructor(public value: Expression, type?: Type|null, sourceSpan?: ParseSourceSpan|null) {
|
||||
super(type, sourceSpan);
|
||||
@ -503,6 +512,7 @@ export interface ExpressionVisitor {
|
||||
visitExternalExpr(ast: ExternalExpr, context: any): any;
|
||||
visitConditionalExpr(ast: ConditionalExpr, context: any): any;
|
||||
visitNotExpr(ast: NotExpr, context: any): any;
|
||||
visitAssertNotNullExpr(ast: AssertNotNull, context: any): any;
|
||||
visitCastExpr(ast: CastExpr, context: any): any;
|
||||
visitFunctionExpr(ast: FunctionExpr, context: any): any;
|
||||
visitBinaryOperatorExpr(ast: BinaryOperatorExpr, context: any): any;
|
||||
@ -768,6 +778,11 @@ export class AstTransformer implements StatementVisitor, ExpressionVisitor {
|
||||
new NotExpr(ast.condition.visitExpression(this, context), ast.sourceSpan), context);
|
||||
}
|
||||
|
||||
visitAssertNotNullExpr(ast: AssertNotNull, context: any): any {
|
||||
return this.transformExpr(
|
||||
new AssertNotNull(ast.condition.visitExpression(this, context), ast.sourceSpan), context);
|
||||
}
|
||||
|
||||
visitCastExpr(ast: CastExpr, context: any): any {
|
||||
return this.transformExpr(
|
||||
new CastExpr(ast.value.visitExpression(this, context), ast.type, ast.sourceSpan), context);
|
||||
@ -948,6 +963,10 @@ export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor
|
||||
ast.condition.visitExpression(this, context);
|
||||
return ast;
|
||||
}
|
||||
visitAssertNotNullExpr(ast: AssertNotNull, context: any): any {
|
||||
ast.condition.visitExpression(this, context);
|
||||
return ast;
|
||||
}
|
||||
visitCastExpr(ast: CastExpr, context: any): any {
|
||||
ast.value.visitExpression(this, context);
|
||||
return ast;
|
||||
@ -1139,6 +1158,11 @@ export function not(expr: Expression, sourceSpan?: ParseSourceSpan | null): NotE
|
||||
return new NotExpr(expr, sourceSpan);
|
||||
}
|
||||
|
||||
export function assertNotNull(
|
||||
expr: Expression, sourceSpan?: ParseSourceSpan | null): AssertNotNull {
|
||||
return new AssertNotNull(expr, sourceSpan);
|
||||
}
|
||||
|
||||
export function fn(
|
||||
params: FnParam[], body: Statement[], type?: Type | null,
|
||||
sourceSpan?: ParseSourceSpan | null): FunctionExpr {
|
||||
|
@ -233,6 +233,9 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
visitNotExpr(ast: o.NotExpr, ctx: _ExecutionContext): any {
|
||||
return !ast.condition.visitExpression(this, ctx);
|
||||
}
|
||||
visitAssertNotNullExpr(ast: o.AssertNotNull, ctx: _ExecutionContext): any {
|
||||
return ast.condition.visitExpression(this, ctx);
|
||||
}
|
||||
visitCastExpr(ast: o.CastExpr, ctx: _ExecutionContext): any {
|
||||
return ast.value.visitExpression(this, ctx);
|
||||
}
|
||||
|
@ -129,6 +129,12 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
||||
return null;
|
||||
}
|
||||
|
||||
visitAssertNotNullExpr(ast: o.AssertNotNull, ctx: EmitterVisitorContext): any {
|
||||
const result = super.visitAssertNotNullExpr(ast, ctx);
|
||||
ctx.print(ast, '!');
|
||||
return result;
|
||||
}
|
||||
|
||||
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any {
|
||||
if (ctx.isExportedVar(stmt.name) && stmt.value instanceof o.ExternalExpr && !stmt.type) {
|
||||
// check for a reexport
|
||||
|
Reference in New Issue
Block a user