mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(compiler): produce binary expressions instead of dedicated write ones (#61682)
Currently our expression parser produces two different expressions for writes: `PropertyWrite` (e.g. `foo.bar = 123`) or `KeyedWrite` (e.g. `foo[0] = 123`). This is inconsistent with other ASTs, like TypeScript's, where writes are represented as binary expressions with a `=` operator and it makes it difficult to implement more write operators like `??=`, because we'd essentially have to duplicate them. These changes switch the expression parser over to produce binary expressions instead. PR Close #61682
This commit is contained in:
committed by
kirjs
parent
c663277df6
commit
08ee693995
@@ -29,7 +29,6 @@ import {
|
||||
ImplicitReceiver,
|
||||
Interpolation,
|
||||
KeyedRead,
|
||||
KeyedWrite,
|
||||
LiteralArray,
|
||||
LiteralMap,
|
||||
LiteralMapKey,
|
||||
@@ -40,7 +39,6 @@ import {
|
||||
ParseSpan,
|
||||
PrefixNot,
|
||||
PropertyRead,
|
||||
PropertyWrite,
|
||||
RecursiveAstVisitor,
|
||||
SafeCall,
|
||||
SafeKeyedRead,
|
||||
@@ -1214,14 +1212,13 @@ class _ParseAST {
|
||||
return id;
|
||||
});
|
||||
const nameSpan = this.sourceSpan(nameStart);
|
||||
let receiver: AST;
|
||||
|
||||
if (isSafe) {
|
||||
if (this.consumeOptionalOperator('=')) {
|
||||
this.error("The '?.' operator cannot be used in the assignment");
|
||||
receiver = new EmptyExpr(this.span(start), this.sourceSpan(start));
|
||||
return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
||||
} else {
|
||||
receiver = new SafePropertyRead(
|
||||
return new SafePropertyRead(
|
||||
this.span(start),
|
||||
this.sourceSpan(start),
|
||||
nameSpan,
|
||||
@@ -1235,18 +1232,17 @@ class _ParseAST {
|
||||
this.error('Bindings cannot contain assignments');
|
||||
return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
||||
}
|
||||
|
||||
const receiver = new PropertyRead(
|
||||
this.span(start),
|
||||
this.sourceSpan(start),
|
||||
nameSpan,
|
||||
readReceiver,
|
||||
id,
|
||||
);
|
||||
const value = this.parseConditional();
|
||||
receiver = new PropertyWrite(
|
||||
this.span(start),
|
||||
this.sourceSpan(start),
|
||||
nameSpan,
|
||||
readReceiver,
|
||||
id,
|
||||
value,
|
||||
);
|
||||
return new Binary(this.span(start), this.sourceSpan(start), '=', receiver, value);
|
||||
} else {
|
||||
receiver = new PropertyRead(
|
||||
return new PropertyRead(
|
||||
this.span(start),
|
||||
this.sourceSpan(start),
|
||||
nameSpan,
|
||||
@@ -1255,8 +1251,6 @@ class _ParseAST {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return receiver;
|
||||
}
|
||||
|
||||
private parseCall(receiver: AST, start: number, isSafe: boolean): AST {
|
||||
@@ -1375,8 +1369,14 @@ class _ParseAST {
|
||||
if (isSafe) {
|
||||
this.error("The '?.' operator cannot be used in the assignment");
|
||||
} else {
|
||||
const binaryReceiver = new KeyedRead(
|
||||
this.span(start),
|
||||
this.sourceSpan(start),
|
||||
receiver,
|
||||
key,
|
||||
);
|
||||
const value = this.parseConditional();
|
||||
return new KeyedWrite(this.span(start), this.sourceSpan(start), receiver, key, value);
|
||||
return new Binary(this.span(start), this.sourceSpan(start), '=', binaryReceiver, value);
|
||||
}
|
||||
} else {
|
||||
return isSafe
|
||||
|
||||
@@ -532,13 +532,13 @@ describe('parser', () => {
|
||||
it('should record property write span', () => {
|
||||
const ast = parseAction('a = b');
|
||||
expect(unparseWithSpan(ast)).toContain(['a = b', 'a = b']);
|
||||
expect(unparseWithSpan(ast)).toContain(['a = b', '[nameSpan] a']);
|
||||
expect(unparseWithSpan(ast)).toContain(['a', '[nameSpan] a']);
|
||||
});
|
||||
|
||||
it('should record accessed property write span', () => {
|
||||
const ast = parseAction('a.b = c');
|
||||
expect(unparseWithSpan(ast)).toContain(['a.b = c', 'a.b = c']);
|
||||
expect(unparseWithSpan(ast)).toContain(['a.b = c', '[nameSpan] b']);
|
||||
expect(unparseWithSpan(ast)).toContain(['a.b', '[nameSpan] b']);
|
||||
});
|
||||
|
||||
it('should record spans for untagged template literals with no interpolations', () => {
|
||||
|
||||
Reference in New Issue
Block a user