Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 2471888

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Serialize any MethodInvocation as possible const.
Bug: dart-lang/sdk#32823 Change-Id: I0be8d25cf9d5ac16aacb693c4730ddaba3ccad5a Reviewed-on: https://dart-review.googlesource.com/50160 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
1 parent b430570 commit 2471888

File tree

7 files changed

+190
-133
lines changed

7 files changed

+190
-133
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
9595
/**
9696
* The version of data format, should be incremented on every format change.
9797
*/
98-
static const int DATA_VERSION = 55;
98+
static const int DATA_VERSION = 56;
9999

100100
/**
101101
* The number of exception contexts allowed to write. Once this field is

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import 'package:analyzer/error/listener.dart';
1818
import 'package:analyzer/exception/exception.dart';
1919
import 'package:analyzer/src/dart/ast/ast.dart';
2020
import 'package:analyzer/src/dart/ast/ast_factory.dart';
21+
import 'package:analyzer/src/dart/ast/token.dart';
2122
import 'package:analyzer/src/dart/ast/utilities.dart';
2223
import 'package:analyzer/src/dart/element/element.dart';
2324
import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
@@ -44,12 +45,14 @@ export 'package:analyzer/src/generated/type_system.dart';
4445
* feature.
4546
*/
4647
class AstRewriteVisitor extends ScopedVisitor {
48+
final bool addConstKeyword;
49+
4750
/**
4851
* Initialize a newly created visitor.
4952
*/
5053
AstRewriteVisitor(LibraryElement definingLibrary, Source source,
5154
TypeProvider typeProvider, AnalysisErrorListener errorListener,
52-
{Scope nameScope})
55+
{Scope nameScope, this.addConstKeyword: false})
5356
: super(definingLibrary, source, typeProvider, errorListener,
5457
nameScope: nameScope);
5558

@@ -77,7 +80,7 @@ class AstRewriteVisitor extends ScopedVisitor {
7780
TypeName typeName = astFactory.typeName(methodName, node.typeArguments);
7881
InstanceCreationExpression instanceCreationExpression =
7982
astFactory.instanceCreationExpression(
80-
null,
83+
_getKeyword(node),
8184
astFactory.constructorName(typeName, null, null),
8285
node.argumentList);
8386
DartType type = _getType(element, node.typeArguments);
@@ -100,7 +103,7 @@ class AstRewriteVisitor extends ScopedVisitor {
100103
TypeName typeName = astFactory.typeName(target, node.typeArguments);
101104
InstanceCreationExpression instanceCreationExpression =
102105
astFactory.instanceCreationExpression(
103-
null,
106+
_getKeyword(node),
104107
astFactory.constructorName(
105108
typeName, node.operator, methodName),
106109
node.argumentList);
@@ -124,7 +127,7 @@ class AstRewriteVisitor extends ScopedVisitor {
124127
node.typeArguments);
125128
InstanceCreationExpression instanceCreationExpression =
126129
astFactory.instanceCreationExpression(
127-
null,
130+
_getKeyword(node),
128131
astFactory.constructorName(typeName, null, null),
129132
node.argumentList);
130133
DartType type = _getType(prefixedElement, node.typeArguments);
@@ -145,7 +148,7 @@ class AstRewriteVisitor extends ScopedVisitor {
145148
TypeName typeName = astFactory.typeName(target, node.typeArguments);
146149
InstanceCreationExpression instanceCreationExpression =
147150
astFactory.instanceCreationExpression(
148-
null,
151+
_getKeyword(node),
149152
astFactory.constructorName(
150153
typeName, node.operator, methodName),
151154
node.argumentList);
@@ -161,6 +164,16 @@ class AstRewriteVisitor extends ScopedVisitor {
161164
return null;
162165
}
163166

167+
/**
168+
* Return the token that should be used in the [InstanceCreationExpression]
169+
* that corresponds to the given invocation [node].
170+
*/
171+
Token _getKeyword(MethodInvocation node) {
172+
return addConstKeyword
173+
? new KeywordToken(Keyword.CONST, node.offset)
174+
: null;
175+
}
176+
164177
/**
165178
* Return the type of the given class [element] after substituting any type
166179
* arguments from the list of [typeArguments] for the class' type parameters.

pkg/analyzer/lib/src/summary/resynthesize.dart

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ library summary_resynthesizer;
77
import 'dart:collection';
88

99
import 'package:analyzer/dart/ast/ast.dart';
10+
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
1011
import 'package:analyzer/dart/element/element.dart';
1112
import 'package:analyzer/dart/element/type.dart';
13+
import 'package:analyzer/error/listener.dart';
1214
import 'package:analyzer/src/dart/element/element.dart';
1315
import 'package:analyzer/src/dart/element/handle.dart';
1416
import 'package:analyzer/src/dart/element/member.dart';
@@ -1118,6 +1120,11 @@ class _UnitResynthesizer extends UnitResynthesizer with UnitResynthesizerMixin {
11181120
*/
11191121
CompilationUnitElementImpl unit;
11201122

1123+
/**
1124+
* The visitor to rewrite implicit `new` and `const`.
1125+
*/
1126+
AstRewriteVisitor astRewriteVisitor;
1127+
11211128
/**
11221129
* Map from slot id to the corresponding [EntityRef] object for linked types
11231130
* (i.e. propagated and inferred types).
@@ -1561,7 +1568,18 @@ class _UnitResynthesizer extends UnitResynthesizer with UnitResynthesizerMixin {
15611568
}
15621569

15631570
Expression _buildConstExpression(ElementImpl context, UnlinkedExpr uc) {
1564-
return new ExprBuilder(this, context, uc).build();
1571+
var expression = new ExprBuilder(this, context, uc).build();
1572+
1573+
if (expression != null && context.context.analysisOptions.previewDart2) {
1574+
astRewriteVisitor ??= new AstRewriteVisitor(libraryResynthesizer.library,
1575+
unit.source, typeProvider, AnalysisErrorListener.NULL_LISTENER,
1576+
addConstKeyword: true);
1577+
var container = astFactory.expressionStatement(expression, null);
1578+
expression.accept(astRewriteVisitor);
1579+
expression = container.expression;
1580+
}
1581+
1582+
return expression;
15651583
}
15661584

15671585
/**

pkg/analyzer/lib/src/summary/summarize_const_expr.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -595,10 +595,6 @@ abstract class AbstractConstExprSerializer {
595595
}
596596

597597
void _serializeMethodInvocation(MethodInvocation invocation) {
598-
if (invocation.target != null ||
599-
invocation.methodName.name != 'identical') {
600-
isValidConst = false;
601-
}
602598
Expression target = invocation.target;
603599
SimpleIdentifier methodName = invocation.methodName;
604600
ArgumentList argumentList = invocation.argumentList;

pkg/analyzer/test/src/dart/analysis/driver_test.dart

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ class AnalysisDriverSchedulerTest {
344344

345345
@reflectiveTest
346346
class AnalysisDriverTest extends BaseAnalysisDriverTest {
347+
void configurePreviewDart2() {
348+
driver.configure(
349+
analysisOptions: new AnalysisOptionsImpl.from(driver.analysisOptions)
350+
..previewDart2 = true);
351+
}
352+
347353
test_addedFiles() async {
348354
var a = _p('/test/lib/a.dart');
349355
var b = _p('/test/lib/b.dart');
@@ -1002,6 +1008,63 @@ class B {}
10021008
expect(x.constantValue, isNotNull);
10031009
}
10041010

1011+
test_const_implicitCreation() async {
1012+
configurePreviewDart2();
1013+
1014+
var a = _p('/test/bin/a.dart');
1015+
var b = _p('/test/bin/b.dart');
1016+
provider.newFile(a, r'''
1017+
class C {
1018+
const C();
1019+
static const C WARNING = C();
1020+
}
1021+
''');
1022+
provider.newFile(b, r'''
1023+
import 'a.dart';
1024+
1025+
class D {
1026+
const D();
1027+
static const D WARNING = D();
1028+
}
1029+
1030+
const c = C.WARNING;
1031+
const d = D.WARNING;
1032+
''');
1033+
AnalysisResult result = await driver.getResult(b);
1034+
expect(result.errors, isEmpty);
1035+
}
1036+
1037+
test_const_implicitCreation_rewrite() async {
1038+
configurePreviewDart2();
1039+
1040+
var a = _p('/test/bin/a.dart');
1041+
var b = _p('/test/bin/b.dart');
1042+
provider.newFile(a, r'''
1043+
class A {
1044+
const A();
1045+
}
1046+
1047+
class B {
1048+
final A a;
1049+
const B(this.a);
1050+
}
1051+
1052+
class C {
1053+
const b = B(A());
1054+
const C();
1055+
}
1056+
''');
1057+
provider.newFile(b, r'''
1058+
import 'a.dart';
1059+
1060+
main() {
1061+
const C();
1062+
}
1063+
''');
1064+
AnalysisResult result = await driver.getResult(b);
1065+
expect(result.errors, isEmpty);
1066+
}
1067+
10051068
test_const_implicitSuperConstructorInvocation() async {
10061069
addTestFile('''
10071070
class Base {}

pkg/analyzer/test/src/summary/resynthesize_common.dart

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,7 +2526,7 @@ class C {
25262526
}
25272527

25282528
test_const_invalid_field_const() async {
2529-
variablesWithNotConstInitializers.add('f');
2529+
shouldCompareLibraryElements = false;
25302530
var library = await checkLibrary(r'''
25312531
class C {
25322532
static const f = 1 + foo();
@@ -2545,14 +2545,16 @@ int foo() {}
25452545
} else if (isStrongMode) {
25462546
checkElementText(library, r'''
25472547
class C {
2548-
static const int f;
2548+
static const int f = 1 +
2549+
foo/*location: test.dart;foo*/();
25492550
}
25502551
int foo() {}
25512552
''');
25522553
} else {
25532554
checkElementText(library, r'''
25542555
class C {
2555-
static const dynamic f;
2556+
static const dynamic f = 1 +
2557+
foo/*location: test.dart;foo*/();
25562558
}
25572559
int foo() {}
25582560
''');
@@ -2594,7 +2596,7 @@ const int x = 0;
25942596
}
25952597

25962598
test_const_invalid_topLevel() async {
2597-
variablesWithNotConstInitializers.add('v');
2599+
shouldCompareLibraryElements = false;
25982600
var library = await checkLibrary(r'''
25992601
const v = 1 + foo();
26002602
int foo() => 42;
@@ -2608,12 +2610,14 @@ int foo() {}
26082610
''');
26092611
} else if (isStrongMode) {
26102612
checkElementText(library, r'''
2611-
const int v;
2613+
const int v = 1 +
2614+
foo/*location: test.dart;foo*/();
26122615
int foo() {}
26132616
''');
26142617
} else {
26152618
checkElementText(library, r'''
2616-
const dynamic v;
2619+
const dynamic v = 1 +
2620+
foo/*location: test.dart;foo*/();
26172621
int foo() {}
26182622
''');
26192623
}
@@ -4566,17 +4570,16 @@ class C {
45664570
}
45674571

45684572
test_constructor_initializers_field_notConst() async {
4569-
variablesWithNotConstInitializers.add('x');
4573+
shouldCompareLibraryElements = false;
45704574
var library = await checkLibrary('''
45714575
class C {
45724576
final x;
45734577
const C() : x = foo();
45744578
}
45754579
int foo() => 42;
45764580
''', allowErrors: true);
4577-
if (isSharedFrontEnd) {
4578-
// It is OK to keep non-constant initializers.
4579-
checkElementText(library, r'''
4581+
// It is OK to keep non-constant initializers.
4582+
checkElementText(library, r'''
45804583
class C {
45814584
final dynamic x;
45824585
const C() :
@@ -4585,16 +4588,6 @@ class C {
45854588
}
45864589
int foo() {}
45874590
''');
4588-
} else {
4589-
checkElementText(library, r'''
4590-
class C {
4591-
final dynamic x;
4592-
const C() :
4593-
x/*location: test.dart;C;x*/ = <null>;
4594-
}
4595-
int foo() {}
4596-
''');
4597-
}
45984591
}
45994592

46004593
test_constructor_initializers_field_withParameter() async {

0 commit comments

Comments
 (0)