Skip to content

Commit 1af124c

Browse files
kallentuCommit Queue
authored andcommitted
[analyzer] Dot shorthands: Update and add tests for const dot shorthands.
Updated the AST binary reader/writer to handle dot shorthand invocations otherwise we crash when we try to evaluate a method invocation. Added a test for that in `const_test.dart`. Added a plethora of tests in `evaluation_test.dart` which led me to find a bug with not carrying over the `isDotShorthand` flag when we convert from a method invocation to a constructor invocation. Unit tests passing. Bug: #59835 Change-Id: Ide1cb7cffc0285ed7d54e9f7bc641d0d28c1d2e2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/437881 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Kallen Tu <[email protected]>
1 parent b9e9300 commit 1af124c

File tree

9 files changed

+465
-23
lines changed

9 files changed

+465
-23
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ testFineAfterLibraryAnalyzerHook;
110110
// TODO(scheglov): Clean up the list of implicitly analyzed files.
111111
class AnalysisDriver {
112112
/// The version of data format, should be incremented on every format change.
113-
static const int DATA_VERSION = 487;
113+
static const int DATA_VERSION = 488;
114114

115115
/// The number of exception contexts allowed to write. Once this field is
116116
/// zero, we stop writing any new exception contexts in this process.

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7197,8 +7197,17 @@ final class DotShorthandInvocationImpl extends InvocationExpressionImpl
71977197

71987198
base mixin DotShorthandMixin on ExpressionImpl {
71997199
/// Whether the AST node is a dot shorthand and has a dot shorthand head
7200-
/// ([DotShorthandInvocation] or [DotShorthandPropertyAccess]) as its
7200+
/// ([DotShorthandInvocation], [DotShorthandConstructorInvocation] or
7201+
/// [DotShorthandPropertyAccess]) as its
72017202
/// inner-most target.
7203+
///
7204+
/// This is `false` and remains `false` when there is no dot shorthand head as
7205+
/// its inner-most target. When we are parsing and notice that we have a dot
7206+
/// shorthand head, we flip this flag to `true` and it remains `true` for that
7207+
/// expression.
7208+
///
7209+
/// We use this flag to determine the correct context type to cache. This
7210+
/// cached context type is then used to resolve the dot shorthand head.
72027211
bool isDotShorthand = false;
72037212
}
72047213

pkg/analyzer/lib/src/dart/constant/evaluation.dart

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,11 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
920920
);
921921
}
922922

923+
@override
924+
Constant visitDotShorthandInvocation(DotShorthandInvocation node) {
925+
return _invalidConstantForMethodInvocation(node);
926+
}
927+
923928
@override
924929
Constant visitDotShorthandPropertyAccess(
925930
covariant DotShorthandPropertyAccessImpl node,
@@ -1150,20 +1155,7 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
11501155
}
11511156
}
11521157

1153-
// Some methods aren't resolved by the time we are evaluating it. We'll mark
1154-
// it and return immediately.
1155-
if (node.staticType is InvalidType) {
1156-
return InvalidConstant.forEntity(
1157-
entity: node,
1158-
diagnosticCode: CompileTimeErrorCode.INVALID_CONSTANT,
1159-
isUnresolved: true,
1160-
);
1161-
}
1162-
1163-
return InvalidConstant.forEntity(
1164-
entity: node,
1165-
diagnosticCode: CompileTimeErrorCode.CONST_EVAL_METHOD_INVOCATION,
1166-
);
1158+
return _invalidConstantForMethodInvocation(node);
11671159
}
11681160

11691161
@override
@@ -2221,6 +2213,25 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
22212213
return value;
22222214
}
22232215

2216+
// Common invalid constants for method invocations and dot shorthand
2217+
// invocations.
2218+
Constant _invalidConstantForMethodInvocation(Expression node) {
2219+
// Some methods aren't resolved by the time we are evaluating it. We'll mark
2220+
// it and return immediately.
2221+
if (node.staticType is InvalidType) {
2222+
return InvalidConstant.forEntity(
2223+
entity: node,
2224+
diagnosticCode: CompileTimeErrorCode.INVALID_CONSTANT,
2225+
isUnresolved: true,
2226+
);
2227+
}
2228+
2229+
return InvalidConstant.forEntity(
2230+
entity: node,
2231+
diagnosticCode: CompileTimeErrorCode.CONST_EVAL_METHOD_INVOCATION,
2232+
);
2233+
}
2234+
22242235
/// Returns the first not-potentially constant error found with [node] or
22252236
/// `null` if there are none.
22262237
InvalidConstant? _reportNotPotentialConstants(AstNode node) {

pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,13 +1288,16 @@ class MethodInvocationResolver with ScopeHelpers {
12881288
// [DotShorthandConstructorInvocation].
12891289
if (receiver.getNamedConstructor2(name) case ConstructorElementImpl element?
12901290
when element.isAccessibleIn2(_resolver.definingLibrary)) {
1291-
var replacement = DotShorthandConstructorInvocationImpl(
1292-
constKeyword: null,
1293-
period: node.period,
1294-
constructorName: nameNode,
1295-
typeArguments: node.typeArguments,
1296-
argumentList: node.argumentList,
1297-
)..element = element;
1291+
var replacement =
1292+
DotShorthandConstructorInvocationImpl(
1293+
constKeyword: null,
1294+
period: node.period,
1295+
constructorName: nameNode,
1296+
typeArguments: node.typeArguments,
1297+
argumentList: node.argumentList,
1298+
)
1299+
..element = element
1300+
..isDotShorthand = node.isDotShorthand;
12981301
_resolver.replaceExpression(node, replacement);
12991302
_resolver.flowAnalysis.transferTestData(node, replacement);
13001303
return replacement;

pkg/analyzer/lib/src/summary2/ast_binary_reader.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class AstBinaryReader {
6565
return _readDefaultFormalParameter();
6666
case Tag.DotShorthandConstructorInvocation:
6767
return _readDotShorthandConstructorInvocation();
68+
case Tag.DotShorthandInvocation:
69+
return _readDotShorthandInvocation();
6870
case Tag.DotShorthandPropertyAccess:
6971
return _readDotShorthandPropertyAccess();
7072
case Tag.DottedName:
@@ -482,6 +484,20 @@ class AstBinaryReader {
482484
return node;
483485
}
484486

487+
DotShorthandInvocation _readDotShorthandInvocation() {
488+
var memberName = readNode() as SimpleIdentifierImpl;
489+
var typeArguments = _readOptionalNode() as TypeArgumentListImpl?;
490+
var arguments = readNode() as ArgumentListImpl;
491+
var node = DotShorthandInvocationImpl(
492+
period: Tokens.period(),
493+
memberName: memberName,
494+
typeArguments: typeArguments,
495+
argumentList: arguments,
496+
);
497+
_readInvocationExpression(node);
498+
return node;
499+
}
500+
485501
DotShorthandPropertyAccess _readDotShorthandPropertyAccess() {
486502
var propertyName = readNode() as SimpleIdentifierImpl;
487503
var node = DotShorthandPropertyAccessImpl(

pkg/analyzer/lib/src/summary2/ast_binary_tag.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Tag {
5252
static const int DeclaredIdentifier = 90;
5353
static const int DefaultFormalParameter = 8;
5454
static const int DotShorthandConstructorInvocation = 114;
55+
static const int DotShorthandInvocation = 115;
5556
static const int DotShorthandPropertyAccess = 113;
5657
static const int DottedName = 47;
5758
static const int DoubleLiteral = 9;

pkg/analyzer/lib/src/summary2/ast_binary_writer.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,13 @@ class AstBinaryWriter extends ThrowingAstVisitor<void> {
239239
_storeExpression(node);
240240
}
241241

242+
@override
243+
void visitDotShorthandInvocation(DotShorthandInvocation node) {
244+
_writeByte(Tag.DotShorthandInvocation);
245+
_writeNode(node.memberName);
246+
_storeInvocationExpression(node);
247+
}
248+
242249
@override
243250
void visitDotShorthandPropertyAccess(DotShorthandPropertyAccess node) {
244251
_writeByte(Tag.DotShorthandPropertyAccess);

0 commit comments

Comments
 (0)