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

Commit 8467604

Browse files
fix
1 parent 86d7cbf commit 8467604

File tree

2 files changed

+80
-10
lines changed

2 files changed

+80
-10
lines changed

tools/const_finder/lib/const_finder.dart

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,31 @@ class _ConstVisitor extends RecursiveVisitor<void> {
3232

3333
bool inIgnoredClass = false;
3434

35+
/// Whether or not we are currently within the declaration of the target class.
36+
///
37+
/// We use this to determine when to skip tracking non-constant
38+
/// [ConstructorInvocation]s. This is because, in web builds, a static
39+
/// method is always created called _#new#tearOff() which returns the result
40+
/// of a non-constant invocation of the unnamed constructor.
41+
///
42+
/// For the following Dart class "FooBar":
43+
///
44+
/// class FooBar {
45+
/// const FooBar();
46+
/// }
47+
///
48+
/// The following kernel structure is generated:
49+
///
50+
/// class FooBar extends core::Object /*hasConstConstructor*/ {
51+
/// const constructor •() → min::FooBar
52+
/// : super core::Object::•()
53+
/// ;
54+
/// static method _#new#tearOff() → min::FooBar
55+
/// return new min::FooBar::•(); /* this is a non-const constructor invocation */
56+
/// method noOp() → void {}
57+
/// }
58+
bool inTargetClass = false;
59+
3560
/// The name of the name of the class of the annotation marking classes
3661
/// whose constant references should be ignored.
3762
final String? annotationClassName;
@@ -73,7 +98,7 @@ class _ConstVisitor extends RecursiveVisitor<void> {
7398
@override
7499
void visitConstructorInvocation(ConstructorInvocation node) {
75100
final Class parentClass = node.target.parent! as Class;
76-
if (_matches(parentClass)) {
101+
if (_matches(parentClass) && !inTargetClass) {
77102
final Location location = node.location!;
78103
nonConstantLocations.add(<String, dynamic>{
79104
'file': location.file.toString(),
@@ -86,9 +111,11 @@ class _ConstVisitor extends RecursiveVisitor<void> {
86111

87112
@override
88113
void visitClass(Class node) {
114+
inTargetClass = _matches(node);
89115
// check if this is a class that we should ignore
90116
inIgnoredClass = _classShouldBeIgnored(node);
91117
super.visitClass(node);
118+
inTargetClass = false;
92119
inIgnoredClass = false;
93120
}
94121

tools/const_finder/test/const_finder_test.dart

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ void expectInstances(dynamic value, dynamic expected, Compiler compiler) {
3131

3232
final Equality<Object?> equality;
3333
if (compiler == Compiler.dart2js) {
34-
// Ignore comparing nonConstantLocations in web dills because it will have
35-
// extra fields.
36-
(value as Map<String, Object?>).remove('nonConstantLocations');
37-
(expected as Map<String, Object?>).remove('nonConstantLocations');
3834
equality = const Dart2JSDeepCollectionEquality();
3935
} else {
4036
equality = const DeepCollectionEquality();
@@ -69,9 +65,7 @@ void _checkConsts(String dillPath, Compiler compiler) {
6965
classLibraryUri: 'package:const_finder_fixtures/target.dart',
7066
className: 'Target',
7167
);
72-
expectInstances(
73-
finder.findInstances(),
74-
<String, dynamic>{
68+
final Map<String, Object?> expectation = <String, dynamic>{
7569
'constantInstances': <Map<String, dynamic>>[
7670
<String, dynamic>{'stringValue': '100', 'intValue': 100, 'targetValue': null},
7771
<String, dynamic>{'stringValue': '102', 'intValue': 102, 'targetValue': null},
@@ -95,7 +89,27 @@ void _checkConsts(String dillPath, Compiler compiler) {
9589
<String, dynamic>{'stringValue': 'package', 'intValue':-1, 'targetValue': null},
9690
],
9791
'nonConstantLocations': <dynamic>[],
98-
},
92+
};
93+
if (compiler == Compiler.aot) {
94+
expectation['nonConstantLocations'] = <Object?>[];
95+
} else {
96+
// Without true tree-shaking, there is a non-const reference in a
97+
// never-invoked function that will be present in the dill.
98+
final String fixturesUrl = Platform.isWindows
99+
? '/$fixtures'.replaceAll(Platform.pathSeparator, '/')
100+
: fixtures;
101+
102+
expectation['nonConstantLocations'] = <Object?>[
103+
<String, dynamic>{
104+
'file': 'file://$fixturesUrl/pkg/package.dart',
105+
'line': 14,
106+
'column': 25,
107+
},
108+
];
109+
}
110+
expectInstances(
111+
finder.findInstances(),
112+
expectation,
99113
compiler,
100114
);
101115

@@ -212,6 +226,9 @@ void _checkNonConstsWeb(String dillPath, Compiler compiler) {
212226
className: 'Target',
213227
);
214228

229+
final String fixturesUrl = Platform.isWindows
230+
? '/$fixtures'.replaceAll(Platform.pathSeparator, '/')
231+
: fixtures;
215232
expectInstances(
216233
finder.findInstances(),
217234
<String, dynamic>{
@@ -225,7 +242,33 @@ void _checkNonConstsWeb(String dillPath, Compiler compiler) {
225242
<String, dynamic>{'stringValue': '7', 'intValue': 7, 'targetValue': null},
226243
<String, dynamic>{'stringValue': 'package', 'intValue': -1, 'targetValue': null},
227244
],
228-
'nonConstantLocations': <dynamic>[]
245+
'nonConstantLocations': <dynamic>[
246+
<String, dynamic>{
247+
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
248+
'line': 14,
249+
'column': 26,
250+
},
251+
<String, dynamic>{
252+
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
253+
'line': 16,
254+
'column': 26,
255+
},
256+
<String, dynamic>{
257+
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
258+
'line': 16,
259+
'column': 41,
260+
},
261+
<String, dynamic>{
262+
'file': 'file://$fixturesUrl/lib/consts_and_non.dart',
263+
'line': 17,
264+
'column': 26,
265+
},
266+
<String, dynamic>{
267+
'file': 'file://$fixturesUrl/pkg/package.dart',
268+
'line': 14,
269+
'column': 25,
270+
}
271+
],
229272
},
230273
compiler,
231274
);

0 commit comments

Comments
 (0)