Skip to content

Commit 2936dca

Browse files
kallentuCommit Queue
authored and
Commit Queue
committed
[analyzer] Dot Shorthands: Add DotShorthandConstructorInvocation AST and resolve constructors.
When we resolve a DotShorthandInvocation, it can either be a method invocation or a constructor invocation. This CL adds a `DotShorthandConstructorInvocation` node to represent the shorthand equivalent of an `InstanceCreationExpression` (without the extra bulk of needing a synthetic `NamedType`), and adds the resolution logic. Test added in the form of unit test and existing language tests. Bug: #59835 Change-Id: I6966ce549f2b079efc0b002fba41bc31a90871c1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/422544 Reviewed-by: Paul Berry <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Kallen Tu <[email protected]>
1 parent 157a0f0 commit 2936dca

17 files changed

+462
-33
lines changed

pkg/analyzer/api.txt

+10
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ package:analyzer/dart/ast/ast.dart:
373373
visitDeclaredVariablePattern (method: R? Function(DeclaredVariablePattern))
374374
visitDefaultFormalParameter (method: R? Function(DefaultFormalParameter))
375375
visitDoStatement (method: R? Function(DoStatement))
376+
visitDotShorthandConstructorInvocation (method: R? Function(DotShorthandConstructorInvocation))
376377
visitDotShorthandInvocation (method: R? Function(DotShorthandInvocation))
377378
visitDotShorthandPropertyAccess (method: R? Function(DotShorthandPropertyAccess))
378379
visitDottedName (method: R? Function(DottedName))
@@ -715,6 +716,9 @@ package:analyzer/dart/ast/ast.dart:
715716
rightParenthesis (getter: Token)
716717
semicolon (getter: Token)
717718
whileKeyword (getter: Token)
719+
DotShorthandConstructorInvocation (class extends InvocationExpression implements ConstructorReferenceNode, experimental):
720+
constructorName (getter: SimpleIdentifier)
721+
period (getter: Token)
718722
DotShorthandInvocation (class extends InvocationExpression, experimental):
719723
memberName (getter: SimpleIdentifier)
720724
period (getter: Token)
@@ -1897,6 +1901,7 @@ package:analyzer/dart/ast/visitor.dart:
18971901
visitDefaultFormalParameter (method: R? Function(DefaultFormalParameter))
18981902
visitDirective (method: R? Function(Directive))
18991903
visitDoStatement (method: R? Function(DoStatement))
1904+
visitDotShorthandConstructorInvocation (method: R? Function(DotShorthandConstructorInvocation))
19001905
visitDotShorthandInvocation (method: R? Function(DotShorthandInvocation))
19011906
visitDotShorthandPropertyAccess (method: R? Function(DotShorthandPropertyAccess))
19021907
visitDottedName (method: R? Function(DottedName))
@@ -2095,6 +2100,7 @@ package:analyzer/dart/ast/visitor.dart:
20952100
visitDeclaredVariablePattern (method: R? Function(DeclaredVariablePattern))
20962101
visitDefaultFormalParameter (method: R? Function(DefaultFormalParameter))
20972102
visitDoStatement (method: R? Function(DoStatement))
2103+
visitDotShorthandConstructorInvocation (method: R? Function(DotShorthandConstructorInvocation))
20982104
visitDotShorthandInvocation (method: R? Function(DotShorthandInvocation))
20992105
visitDotShorthandPropertyAccess (method: R? Function(DotShorthandPropertyAccess))
21002106
visitDottedName (method: R? Function(DottedName))
@@ -2271,6 +2277,7 @@ package:analyzer/dart/ast/visitor.dart:
22712277
visitDeclaredVariablePattern (method: R? Function(DeclaredVariablePattern))
22722278
visitDefaultFormalParameter (method: R? Function(DefaultFormalParameter))
22732279
visitDoStatement (method: R? Function(DoStatement))
2280+
visitDotShorthandConstructorInvocation (method: R? Function(DotShorthandConstructorInvocation))
22742281
visitDotShorthandInvocation (method: R? Function(DotShorthandInvocation))
22752282
visitDotShorthandPropertyAccess (method: R? Function(DotShorthandPropertyAccess))
22762283
visitDottedName (method: R? Function(DottedName))
@@ -2447,6 +2454,7 @@ package:analyzer/dart/ast/visitor.dart:
24472454
visitDeclaredVariablePattern (method: R? Function(DeclaredVariablePattern))
24482455
visitDefaultFormalParameter (method: R? Function(DefaultFormalParameter))
24492456
visitDoStatement (method: R? Function(DoStatement))
2457+
visitDotShorthandConstructorInvocation (method: R? Function(DotShorthandConstructorInvocation))
24502458
visitDotShorthandInvocation (method: R? Function(DotShorthandInvocation))
24512459
visitDotShorthandPropertyAccess (method: R? Function(DotShorthandPropertyAccess))
24522460
visitDottedName (method: R? Function(DottedName))
@@ -2624,6 +2632,7 @@ package:analyzer/dart/ast/visitor.dart:
26242632
visitDeclaredVariablePattern (method: T? Function(DeclaredVariablePattern))
26252633
visitDefaultFormalParameter (method: T? Function(DefaultFormalParameter))
26262634
visitDoStatement (method: T? Function(DoStatement))
2635+
visitDotShorthandConstructorInvocation (method: T? Function(DotShorthandConstructorInvocation))
26272636
visitDotShorthandInvocation (method: T? Function(DotShorthandInvocation))
26282637
visitDotShorthandPropertyAccess (method: T? Function(DotShorthandPropertyAccess))
26292638
visitDottedName (method: T? Function(DottedName))
@@ -2800,6 +2809,7 @@ package:analyzer/dart/ast/visitor.dart:
28002809
visitDeclaredVariablePattern (method: R? Function(DeclaredVariablePattern))
28012810
visitDefaultFormalParameter (method: R? Function(DefaultFormalParameter))
28022811
visitDoStatement (method: R? Function(DoStatement))
2812+
visitDotShorthandConstructorInvocation (method: R? Function(DotShorthandConstructorInvocation))
28032813
visitDotShorthandInvocation (method: R? Function(DotShorthandInvocation))
28042814
visitDotShorthandPropertyAccess (method: R? Function(DotShorthandPropertyAccess))
28052815
visitDottedName (method: R? Function(DottedName))

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

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export 'package:analyzer/src/dart/ast/ast.dart'
9393
Directive,
9494
DoStatement,
9595
DotShorthandInvocation,
96+
DotShorthandConstructorInvocation,
9697
DotShorthandPropertyAccess,
9798
DottedName,
9899
DoubleLiteral,

pkg/analyzer/lib/dart/ast/visitor.dart

+36
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ class GeneralizingAstVisitor<R> implements AstVisitor<R> {
279279
@override
280280
R? visitDoStatement(DoStatement node) => visitStatement(node);
281281

282+
@override
283+
R? visitDotShorthandConstructorInvocation(
284+
DotShorthandConstructorInvocation node) =>
285+
visitExpression(node);
286+
282287
@override
283288
R? visitDotShorthandInvocation(DotShorthandInvocation node) =>
284289
visitExpression(node);
@@ -1043,6 +1048,13 @@ class RecursiveAstVisitor<R> implements AstVisitor<R> {
10431048
return null;
10441049
}
10451050

1051+
@override
1052+
R? visitDotShorthandConstructorInvocation(
1053+
DotShorthandConstructorInvocation node) {
1054+
node.visitChildren(this);
1055+
return null;
1056+
}
1057+
10461058
@override
10471059
R? visitDotShorthandInvocation(DotShorthandInvocation node) {
10481060
node.visitChildren(this);
@@ -1985,6 +1997,11 @@ class SimpleAstVisitor<R> implements AstVisitor<R> {
19851997
@override
19861998
R? visitDoStatement(DoStatement node) => null;
19871999

2000+
@override
2001+
R? visitDotShorthandConstructorInvocation(
2002+
DotShorthandConstructorInvocation node) =>
2003+
null;
2004+
19882005
@override
19892006
R? visitDotShorthandInvocation(DotShorthandInvocation node) => null;
19902007

@@ -2534,6 +2551,11 @@ class ThrowingAstVisitor<R> implements AstVisitor<R> {
25342551
@override
25352552
R? visitDoStatement(DoStatement node) => _throw(node);
25362553

2554+
@override
2555+
R? visitDotShorthandConstructorInvocation(
2556+
DotShorthandConstructorInvocation node) =>
2557+
_throw(node);
2558+
25372559
@override
25382560
R? visitDotShorthandInvocation(DotShorthandInvocation node) => _throw(node);
25392561

@@ -3299,6 +3321,15 @@ class TimedAstVisitor<T> implements AstVisitor<T> {
32993321
return result;
33003322
}
33013323

3324+
@override
3325+
T? visitDotShorthandConstructorInvocation(
3326+
DotShorthandConstructorInvocation node) {
3327+
stopwatch.start();
3328+
T? result = _baseVisitor.visitDotShorthandConstructorInvocation(node);
3329+
stopwatch.stop();
3330+
return result;
3331+
}
3332+
33023333
@override
33033334
T? visitDotShorthandInvocation(DotShorthandInvocation node) {
33043335
stopwatch.start();
@@ -4521,6 +4552,11 @@ class UnifyingAstVisitor<R> implements AstVisitor<R> {
45214552
@override
45224553
R? visitDoStatement(DoStatement node) => visitNode(node);
45234554

4555+
@override
4556+
R? visitDotShorthandConstructorInvocation(
4557+
DotShorthandConstructorInvocation node) =>
4558+
visitNode(node);
4559+
45244560
@override
45254561
R? visitDotShorthandInvocation(DotShorthandInvocation node) =>
45264562
visitNode(node);

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

+97-3
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,9 @@ abstract class AstVisitor<R> {
12331233

12341234
R? visitDoStatement(DoStatement node);
12351235

1236+
R? visitDotShorthandConstructorInvocation(
1237+
DotShorthandConstructorInvocation node);
1238+
12361239
R? visitDotShorthandInvocation(DotShorthandInvocation node);
12371240

12381241
R? visitDotShorthandPropertyAccess(DotShorthandPropertyAccess node);
@@ -5192,6 +5195,91 @@ final class DoStatementImpl extends StatementImpl implements DoStatement {
51925195
}
51935196
}
51945197

5198+
/// A node that represents a dot shorthand constructor invocation.
5199+
///
5200+
/// For example, `.fromCharCode(42)`.
5201+
///
5202+
/// dotShorthandHead ::=
5203+
/// '.' [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
5204+
@experimental
5205+
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
5206+
abstract final class DotShorthandConstructorInvocation
5207+
extends InvocationExpression implements ConstructorReferenceNode {
5208+
/// The name of the constructor invocation.
5209+
SimpleIdentifier get constructorName;
5210+
5211+
/// The token representing the period.
5212+
Token get period;
5213+
}
5214+
5215+
final class DotShorthandConstructorInvocationImpl
5216+
extends InvocationExpressionImpl
5217+
implements
5218+
DotShorthandConstructorInvocation,
5219+
RewrittenMethodInvocationImpl {
5220+
@override
5221+
final Token period;
5222+
5223+
SimpleIdentifierImpl _constructorName;
5224+
5225+
@override
5226+
ConstructorElementImpl2? element;
5227+
5228+
/// Initializes a newly created dot shorthand constructor invocation.
5229+
DotShorthandConstructorInvocationImpl({
5230+
required this.period,
5231+
required SimpleIdentifierImpl constructorName,
5232+
required super.typeArguments,
5233+
required super.argumentList,
5234+
}) : _constructorName = constructorName {
5235+
_becomeParentOf(_constructorName);
5236+
}
5237+
5238+
@override
5239+
Token get beginToken => period;
5240+
5241+
@override
5242+
SimpleIdentifierImpl get constructorName => _constructorName;
5243+
5244+
set constructorName(SimpleIdentifierImpl identifier) {
5245+
_constructorName = _becomeParentOf(identifier);
5246+
}
5247+
5248+
@override
5249+
Token get endToken => argumentList.endToken;
5250+
5251+
@override
5252+
ExpressionImpl get function => constructorName;
5253+
5254+
@override
5255+
Precedence get precedence => Precedence.postfix;
5256+
5257+
@override
5258+
ChildEntities get _childEntities => ChildEntities()
5259+
..addToken('period', period)
5260+
..addNode('constructorName', constructorName)
5261+
..addNode('typeArguments', typeArguments)
5262+
..addNode('argumentList', argumentList);
5263+
5264+
@override
5265+
E? accept<E>(AstVisitor<E> visitor) =>
5266+
visitor.visitDotShorthandConstructorInvocation(this);
5267+
5268+
@override
5269+
void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
5270+
throw StateError(
5271+
'DotShorthandConstructorInvocationImpl should only appear in fully'
5272+
' resolved ASTs');
5273+
}
5274+
5275+
@override
5276+
void visitChildren(AstVisitor visitor) {
5277+
constructorName.accept(visitor);
5278+
typeArguments?.accept(visitor);
5279+
argumentList.accept(visitor);
5280+
}
5281+
}
5282+
51955283
/// A node that represents a dot shorthand static method or constructor
51965284
/// invocation.
51975285
///
@@ -8488,7 +8576,7 @@ abstract final class FunctionExpressionInvocation
84888576

84898577
final class FunctionExpressionInvocationImpl extends InvocationExpressionImpl
84908578
with NullShortableExpressionImpl
8491-
implements FunctionExpressionInvocation {
8579+
implements FunctionExpressionInvocation, RewrittenMethodInvocationImpl {
84928580
ExpressionImpl _function;
84938581

84948582
@override
@@ -10562,8 +10650,8 @@ final class InterpolationStringImpl extends InterpolationElementImpl
1056210650

1056310651
/// The invocation of a function or method.
1056410652
///
10565-
/// This will either be a [FunctionExpressionInvocation], [MethodInvocation],
10566-
/// or a [DotShorthandInvocation].
10653+
/// This will either be a [FunctionExpressionInvocation], a [MethodInvocation],
10654+
/// a [DotShorthandConstructorInvocation], or a [DotShorthandInvocation].
1056710655
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
1056810656
abstract final class InvocationExpression implements Expression {
1056910657
/// The list of arguments to the method.
@@ -15345,6 +15433,12 @@ final class ReturnStatementImpl extends StatementImpl
1534515433
}
1534615434
}
1534715435

15436+
/// A resolved dot shorthand invocation.
15437+
///
15438+
/// Either a [FunctionExpressionInvocationImpl], a static method invocation, or
15439+
/// a [DotShorthandConstructorInvocationImpl], a constructor invocation.
15440+
sealed class RewrittenMethodInvocationImpl implements ExpressionImpl {}
15441+
1534815442
/// A script tag that can optionally occur at the beginning of a compilation
1534915443
/// unit.
1535015444
///

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

+9
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,15 @@ class ToSourceVisitor implements AstVisitor<void> {
348348
sink.write(');');
349349
}
350350

351+
@override
352+
void visitDotShorthandConstructorInvocation(
353+
DotShorthandConstructorInvocation node) {
354+
_visitToken(node.period);
355+
_visitNode(node.constructorName);
356+
_visitNode(node.typeArguments);
357+
_visitNode(node.argumentList);
358+
}
359+
351360
@override
352361
void visitDotShorthandInvocation(DotShorthandInvocation node) {
353362
_visitToken(node.period);

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ class ConstructorReferenceResolver {
9191
{required DartType contextType}) {
9292
var constructorName = node.constructorName;
9393
var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
94-
constructorName: constructorName,
94+
typeElement: constructorName.type.element2,
95+
constructorName: constructorName.name,
9596
definingLibrary: _resolver.definingLibrary,
9697
);
9798

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

+46-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import 'package:analyzer/src/dart/element/type.dart';
77
import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
88
import 'package:analyzer/src/generated/resolver.dart';
99

10-
/// A resolver for [InstanceCreationExpression] nodes.
10+
/// A resolver for [InstanceCreationExpression] and
11+
/// [DotShorthandConstructorInvocation] nodes.
1112
///
1213
/// This resolver is responsible for rewriting a given
1314
/// [InstanceCreationExpression] as a [MethodInvocation] if the parsed
@@ -49,6 +50,48 @@ class InstanceCreationExpressionResolver {
4950
_resolveInstanceCreationExpression(node, contextType: contextType);
5051
}
5152

53+
/// Resolves a [DotShorthandConstructorInvocation] node.
54+
void resolveDotShorthand(DotShorthandConstructorInvocationImpl node) {
55+
TypeImpl contextType =
56+
_resolver.getDotShorthandContext().unwrapTypeSchemaView();
57+
58+
// The static namespace denoted by `S` is also the namespace denoted by
59+
// `FutureOr<S>`.
60+
contextType = _resolver.typeSystem.futureOrBase(contextType);
61+
62+
// TODO(kallentu): Support other context types
63+
if (contextType is InterfaceTypeImpl) {
64+
_resolveDotShorthandConstructorInvocation(node, contextType: contextType);
65+
}
66+
67+
// TODO(kallentu): Report error.
68+
}
69+
70+
void _resolveDotShorthandConstructorInvocation(
71+
DotShorthandConstructorInvocationImpl node,
72+
{required TypeImpl contextType}) {
73+
var whyNotPromotedArguments = <WhyNotPromotedGetter>[];
74+
_resolver.elementResolver.visitDotShorthandConstructorInvocation(node);
75+
var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
76+
typeElement: contextType.element3,
77+
constructorName: node.constructorName,
78+
definingLibrary: _resolver.definingLibrary,
79+
);
80+
DotShorthandConstructorInvocationInferrer(
81+
resolver: _resolver,
82+
node: node,
83+
argumentList: node.argumentList,
84+
contextType: contextType,
85+
whyNotPromotedArguments: whyNotPromotedArguments)
86+
.resolveInvocation(
87+
// TODO(paulberry): eliminate this cast by changing the type of
88+
// `ConstructorElementToInfer.asType`.
89+
rawType: elementToInfer?.asType as FunctionTypeImpl?);
90+
node.recordStaticType(contextType, resolver: _resolver);
91+
_resolver.checkForArgumentTypesNotAssignableInList(
92+
node.argumentList, whyNotPromotedArguments);
93+
}
94+
5295
void _resolveInstanceCreationExpression(InstanceCreationExpressionImpl node,
5396
{required TypeImpl contextType}) {
5497
var whyNotPromotedArguments = <WhyNotPromotedGetter>[];
@@ -58,7 +101,8 @@ class InstanceCreationExpressionResolver {
58101
constructorName = node.constructorName;
59102
_resolver.elementResolver.visitInstanceCreationExpression(node);
60103
var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
61-
constructorName: constructorName,
104+
typeElement: constructorName.type.element2,
105+
constructorName: node.constructorName.name,
62106
definingLibrary: _resolver.definingLibrary,
63107
);
64108
InstanceCreationInferrer(

0 commit comments

Comments
 (0)