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

Commit e54f2c8

Browse files
authored
Const finder missing static const list/map/set fields. (#16896)
1 parent 63bdf3e commit e54f2c8

File tree

4 files changed

+315
-11
lines changed

4 files changed

+315
-11
lines changed

tools/const_finder/lib/const_finder.dart

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:collection';
6+
57
import 'package:kernel/kernel.dart' hide MapEntry;
68
import 'package:meta/meta.dart';
79

@@ -13,7 +15,7 @@ class _ConstVisitor extends RecursiveVisitor<void> {
1315
) : assert(kernelFilePath != null),
1416
assert(classLibraryUri != null),
1517
assert(className != null),
16-
_visitedInstnaces = <String>{},
18+
_visitedInstances = <String>{},
1719
constantInstances = <Map<String, dynamic>>[],
1820
nonConstantLocations = <Map<String, dynamic>>[];
1921

@@ -26,15 +28,30 @@ class _ConstVisitor extends RecursiveVisitor<void> {
2628
/// The name of the class to find.
2729
final String className;
2830

29-
final Set<String> _visitedInstnaces;
31+
final Set<String> _visitedInstances;
3032
final List<Map<String, dynamic>> constantInstances;
3133
final List<Map<String, dynamic>> nonConstantLocations;
3234

3335
bool _matches(Class node) {
34-
return node.enclosingLibrary.canonicalName.name == classLibraryUri &&
36+
return node.enclosingLibrary.importUri.toString() == classLibraryUri &&
3537
node.name == className;
3638
}
3739

40+
// Avoid visiting the same constant more than once.
41+
Set<Constant> _cache = LinkedHashSet<Constant>.identity();
42+
43+
@override
44+
void defaultConstant(Constant node) {
45+
if (_cache.add(node)) {
46+
super.defaultConstant(node);
47+
}
48+
}
49+
50+
@override
51+
void defaultConstantReference(Constant node) {
52+
defaultConstant(node);
53+
}
54+
3855
@override
3956
void visitConstructorInvocation(ConstructorInvocation node) {
4057
final Class parentClass = node.target.parent as Class;
@@ -51,9 +68,8 @@ class _ConstVisitor extends RecursiveVisitor<void> {
5168

5269
@override
5370
void visitInstanceConstantReference(InstanceConstant node) {
54-
node.fieldValues.values.whereType<InstanceConstant>().forEach(visitInstanceConstantReference);
71+
super.visitInstanceConstantReference(node);
5572
if (!_matches(node.classNode)) {
56-
super.visitInstanceConstantReference(node);
5773
return;
5874
}
5975
final Map<String, dynamic> instance = <String, dynamic>{};
@@ -62,9 +78,9 @@ class _ConstVisitor extends RecursiveVisitor<void> {
6278
continue;
6379
}
6480
final PrimitiveConstant<dynamic> value = kvp.value as PrimitiveConstant<dynamic>;
65-
instance[kvp.key.canonicalName.name] = value.value;
81+
instance[kvp.key.asField.name.name] = value.value;
6682
}
67-
if (_visitedInstnaces.add(instance.toString())) {
83+
if (_visitedInstances.add(instance.toString())) {
6884
constantInstances.add(instance);
6985
}
7086
}
@@ -90,7 +106,7 @@ class ConstFinder {
90106

91107
/// Finds all instances
92108
Map<String, dynamic> findInstances() {
93-
_visitor._visitedInstnaces.clear();
109+
_visitor._visitedInstances.clear();
94110
for (Library library in loadComponentFromBinary(_visitor.kernelFilePath).libraries) {
95111
library.visitChildren(_visitor);
96112
}

tools/const_finder/test/const_finder_test.dart

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ void expect<T>(T value, T expected) {
1919
final String basePath =
2020
path.canonicalize(path.join(path.dirname(Platform.script.path), '..'));
2121
final String fixtures = path.join(basePath, 'test', 'fixtures');
22+
final String box = path.join(fixtures, 'lib', 'box.dart');
2223
final String consts = path.join(fixtures, 'lib', 'consts.dart');
2324
final String dotPackages = path.join(fixtures, '.packages');
2425
final String constsAndNon = path.join(fixtures, 'lib', 'consts_and_non.dart');
26+
final String boxDill = path.join(fixtures, 'box.dill');
2527
final String constsDill = path.join(fixtures, 'consts.dill');
2628
final String constsAndNonDill = path.join(fixtures, 'consts_and_non.dill');
2729

@@ -30,18 +32,37 @@ final String constsAndNonDill = path.join(fixtures, 'consts_and_non.dill');
3032
final String dart = Platform.resolvedExecutable;
3133
final String bat = Platform.isWindows ? '.bat' : '';
3234

35+
void _checkRecursion() {
36+
stdout.writeln('Checking recursive calls.');
37+
final ConstFinder finder = ConstFinder(
38+
kernelFilePath: boxDill,
39+
classLibraryUri: 'package:const_finder_fixtures/box.dart',
40+
className: 'Box',
41+
);
42+
// Will timeout if we did things wrong.
43+
jsonEncode(finder.findInstances());
44+
}
45+
3346
void _checkConsts() {
34-
print('Checking for expected constants.');
47+
stdout.writeln('Checking for expected constants.');
3548
final ConstFinder finder = ConstFinder(
3649
kernelFilePath: constsDill,
3750
classLibraryUri: 'package:const_finder_fixtures/target.dart',
3851
className: 'Target',
3952
);
40-
4153
expect<String>(
4254
jsonEncode(finder.findInstances()),
4355
jsonEncode(<String, dynamic>{
4456
'constantInstances': <Map<String, dynamic>>[
57+
<String, dynamic>{'stringValue': '100', 'intValue': 100, 'targetValue': null},
58+
<String, dynamic>{'stringValue': '102', 'intValue': 102, 'targetValue': null},
59+
<String, dynamic>{'stringValue': '101', 'intValue': 101},
60+
<String, dynamic>{'stringValue': '103', 'intValue': 103, 'targetValue': null},
61+
<String, dynamic>{'stringValue': '105', 'intValue': 105, 'targetValue': null},
62+
<String, dynamic>{'stringValue': '104', 'intValue': 104},
63+
<String, dynamic>{'stringValue': '106', 'intValue': 106, 'targetValue': null},
64+
<String, dynamic>{'stringValue': '108', 'intValue': 108, 'targetValue': null},
65+
<String, dynamic>{'stringValue': '107', 'intValue': 107},
4566
<String, dynamic>{'stringValue': '1', 'intValue': 1, 'targetValue': null},
4667
<String, dynamic>{'stringValue': '4', 'intValue': 4, 'targetValue': null},
4768
<String, dynamic>{'stringValue': '2', 'intValue': 2},
@@ -58,7 +79,7 @@ void _checkConsts() {
5879
}
5980

6081
void _checkNonConsts() {
61-
print('Checking for non-constant instances.');
82+
stdout.writeln('Checking for non-constant instances.');
6283
final ConstFinder finder = ConstFinder(
6384
kernelFilePath: constsAndNonDill,
6485
classLibraryUri: 'package:const_finder_fixtures/target.dart',
@@ -121,6 +142,18 @@ Future<void> main(List<String> args) async {
121142

122143
stdout.writeln('Generating kernel fixtures...');
123144
stdout.writeln(consts);
145+
146+
_checkProcessResult(Process.runSync(dart, <String>[
147+
frontendServer,
148+
'--sdk-root=$sdkRoot',
149+
'--target=flutter',
150+
'--aot',
151+
'--tfa',
152+
'--packages=$dotPackages',
153+
'--output-dill=$boxDill',
154+
box,
155+
]));
156+
124157
_checkProcessResult(Process.runSync(dart, <String>[
125158
frontendServer,
126159
'--sdk-root=$sdkRoot',
@@ -143,6 +176,7 @@ Future<void> main(List<String> args) async {
143176
constsAndNon,
144177
]));
145178

179+
_checkRecursion();
146180
_checkConsts();
147181
_checkNonConsts();
148182
} finally {
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// If canonicalization uses deep structural hashing without memoizing, this
6+
// will exhibit superlinear time.
7+
8+
// Compare with Dart version of this test at:
9+
// https://github.com/dart-lang/sdk/blob/ca3ad264a64937d5d336cd04dbf2746d1b7d8fc4/tests/language_2/canonicalize/hashing_memoize_instance_test.dart
10+
11+
class Box {
12+
final Object content1;
13+
final Object content2;
14+
const Box(this.content1, this.content2);
15+
}
16+
17+
const Box box1_0 = Box(null, null);
18+
const Box box1_1 = Box(box1_0, box1_0);
19+
const Box box1_2 = Box(box1_1, box1_1);
20+
const Box box1_3 = Box(box1_2, box1_2);
21+
const Box box1_4 = Box(box1_3, box1_3);
22+
const Box box1_5 = Box(box1_4, box1_4);
23+
const Box box1_6 = Box(box1_5, box1_5);
24+
const Box box1_7 = Box(box1_6, box1_6);
25+
const Box box1_8 = Box(box1_7, box1_7);
26+
const Box box1_9 = Box(box1_8, box1_8);
27+
const Box box1_10 = Box(box1_9, box1_9);
28+
const Box box1_11 = Box(box1_10, box1_10);
29+
const Box box1_12 = Box(box1_11, box1_11);
30+
const Box box1_13 = Box(box1_12, box1_12);
31+
const Box box1_14 = Box(box1_13, box1_13);
32+
const Box box1_15 = Box(box1_14, box1_14);
33+
const Box box1_16 = Box(box1_15, box1_15);
34+
const Box box1_17 = Box(box1_16, box1_16);
35+
const Box box1_18 = Box(box1_17, box1_17);
36+
const Box box1_19 = Box(box1_18, box1_18);
37+
const Box box1_20 = Box(box1_19, box1_19);
38+
const Box box1_21 = Box(box1_20, box1_20);
39+
const Box box1_22 = Box(box1_21, box1_21);
40+
const Box box1_23 = Box(box1_22, box1_22);
41+
const Box box1_24 = Box(box1_23, box1_23);
42+
const Box box1_25 = Box(box1_24, box1_24);
43+
const Box box1_26 = Box(box1_25, box1_25);
44+
const Box box1_27 = Box(box1_26, box1_26);
45+
const Box box1_28 = Box(box1_27, box1_27);
46+
const Box box1_29 = Box(box1_28, box1_28);
47+
const Box box1_30 = Box(box1_29, box1_29);
48+
const Box box1_31 = Box(box1_30, box1_30);
49+
const Box box1_32 = Box(box1_31, box1_31);
50+
const Box box1_33 = Box(box1_32, box1_32);
51+
const Box box1_34 = Box(box1_33, box1_33);
52+
const Box box1_35 = Box(box1_34, box1_34);
53+
const Box box1_36 = Box(box1_35, box1_35);
54+
const Box box1_37 = Box(box1_36, box1_36);
55+
const Box box1_38 = Box(box1_37, box1_37);
56+
const Box box1_39 = Box(box1_38, box1_38);
57+
const Box box1_40 = Box(box1_39, box1_39);
58+
const Box box1_41 = Box(box1_40, box1_40);
59+
const Box box1_42 = Box(box1_41, box1_41);
60+
const Box box1_43 = Box(box1_42, box1_42);
61+
const Box box1_44 = Box(box1_43, box1_43);
62+
const Box box1_45 = Box(box1_44, box1_44);
63+
const Box box1_46 = Box(box1_45, box1_45);
64+
const Box box1_47 = Box(box1_46, box1_46);
65+
const Box box1_48 = Box(box1_47, box1_47);
66+
const Box box1_49 = Box(box1_48, box1_48);
67+
const Box box1_50 = Box(box1_49, box1_49);
68+
const Box box1_51 = Box(box1_50, box1_50);
69+
const Box box1_52 = Box(box1_51, box1_51);
70+
const Box box1_53 = Box(box1_52, box1_52);
71+
const Box box1_54 = Box(box1_53, box1_53);
72+
const Box box1_55 = Box(box1_54, box1_54);
73+
const Box box1_56 = Box(box1_55, box1_55);
74+
const Box box1_57 = Box(box1_56, box1_56);
75+
const Box box1_58 = Box(box1_57, box1_57);
76+
const Box box1_59 = Box(box1_58, box1_58);
77+
const Box box1_60 = Box(box1_59, box1_59);
78+
const Box box1_61 = Box(box1_60, box1_60);
79+
const Box box1_62 = Box(box1_61, box1_61);
80+
const Box box1_63 = Box(box1_62, box1_62);
81+
const Box box1_64 = Box(box1_63, box1_63);
82+
const Box box1_65 = Box(box1_64, box1_64);
83+
const Box box1_66 = Box(box1_65, box1_65);
84+
const Box box1_67 = Box(box1_66, box1_66);
85+
const Box box1_68 = Box(box1_67, box1_67);
86+
const Box box1_69 = Box(box1_68, box1_68);
87+
const Box box1_70 = Box(box1_69, box1_69);
88+
const Box box1_71 = Box(box1_70, box1_70);
89+
const Box box1_72 = Box(box1_71, box1_71);
90+
const Box box1_73 = Box(box1_72, box1_72);
91+
const Box box1_74 = Box(box1_73, box1_73);
92+
const Box box1_75 = Box(box1_74, box1_74);
93+
const Box box1_76 = Box(box1_75, box1_75);
94+
const Box box1_77 = Box(box1_76, box1_76);
95+
const Box box1_78 = Box(box1_77, box1_77);
96+
const Box box1_79 = Box(box1_78, box1_78);
97+
const Box box1_80 = Box(box1_79, box1_79);
98+
const Box box1_81 = Box(box1_80, box1_80);
99+
const Box box1_82 = Box(box1_81, box1_81);
100+
const Box box1_83 = Box(box1_82, box1_82);
101+
const Box box1_84 = Box(box1_83, box1_83);
102+
const Box box1_85 = Box(box1_84, box1_84);
103+
const Box box1_86 = Box(box1_85, box1_85);
104+
const Box box1_87 = Box(box1_86, box1_86);
105+
const Box box1_88 = Box(box1_87, box1_87);
106+
const Box box1_89 = Box(box1_88, box1_88);
107+
const Box box1_90 = Box(box1_89, box1_89);
108+
const Box box1_91 = Box(box1_90, box1_90);
109+
const Box box1_92 = Box(box1_91, box1_91);
110+
const Box box1_93 = Box(box1_92, box1_92);
111+
const Box box1_94 = Box(box1_93, box1_93);
112+
const Box box1_95 = Box(box1_94, box1_94);
113+
const Box box1_96 = Box(box1_95, box1_95);
114+
const Box box1_97 = Box(box1_96, box1_96);
115+
const Box box1_98 = Box(box1_97, box1_97);
116+
const Box box1_99 = Box(box1_98, box1_98);
117+
118+
const Box box2_0 = Box(null, null);
119+
const Box box2_1 = Box(box2_0, box2_0);
120+
const Box box2_2 = Box(box2_1, box2_1);
121+
const Box box2_3 = Box(box2_2, box2_2);
122+
const Box box2_4 = Box(box2_3, box2_3);
123+
const Box box2_5 = Box(box2_4, box2_4);
124+
const Box box2_6 = Box(box2_5, box2_5);
125+
const Box box2_7 = Box(box2_6, box2_6);
126+
const Box box2_8 = Box(box2_7, box2_7);
127+
const Box box2_9 = Box(box2_8, box2_8);
128+
const Box box2_10 = Box(box2_9, box2_9);
129+
const Box box2_11 = Box(box2_10, box2_10);
130+
const Box box2_12 = Box(box2_11, box2_11);
131+
const Box box2_13 = Box(box2_12, box2_12);
132+
const Box box2_14 = Box(box2_13, box2_13);
133+
const Box box2_15 = Box(box2_14, box2_14);
134+
const Box box2_16 = Box(box2_15, box2_15);
135+
const Box box2_17 = Box(box2_16, box2_16);
136+
const Box box2_18 = Box(box2_17, box2_17);
137+
const Box box2_19 = Box(box2_18, box2_18);
138+
const Box box2_20 = Box(box2_19, box2_19);
139+
const Box box2_21 = Box(box2_20, box2_20);
140+
const Box box2_22 = Box(box2_21, box2_21);
141+
const Box box2_23 = Box(box2_22, box2_22);
142+
const Box box2_24 = Box(box2_23, box2_23);
143+
const Box box2_25 = Box(box2_24, box2_24);
144+
const Box box2_26 = Box(box2_25, box2_25);
145+
const Box box2_27 = Box(box2_26, box2_26);
146+
const Box box2_28 = Box(box2_27, box2_27);
147+
const Box box2_29 = Box(box2_28, box2_28);
148+
const Box box2_30 = Box(box2_29, box2_29);
149+
const Box box2_31 = Box(box2_30, box2_30);
150+
const Box box2_32 = Box(box2_31, box2_31);
151+
const Box box2_33 = Box(box2_32, box2_32);
152+
const Box box2_34 = Box(box2_33, box2_33);
153+
const Box box2_35 = Box(box2_34, box2_34);
154+
const Box box2_36 = Box(box2_35, box2_35);
155+
const Box box2_37 = Box(box2_36, box2_36);
156+
const Box box2_38 = Box(box2_37, box2_37);
157+
const Box box2_39 = Box(box2_38, box2_38);
158+
const Box box2_40 = Box(box2_39, box2_39);
159+
const Box box2_41 = Box(box2_40, box2_40);
160+
const Box box2_42 = Box(box2_41, box2_41);
161+
const Box box2_43 = Box(box2_42, box2_42);
162+
const Box box2_44 = Box(box2_43, box2_43);
163+
const Box box2_45 = Box(box2_44, box2_44);
164+
const Box box2_46 = Box(box2_45, box2_45);
165+
const Box box2_47 = Box(box2_46, box2_46);
166+
const Box box2_48 = Box(box2_47, box2_47);
167+
const Box box2_49 = Box(box2_48, box2_48);
168+
const Box box2_50 = Box(box2_49, box2_49);
169+
const Box box2_51 = Box(box2_50, box2_50);
170+
const Box box2_52 = Box(box2_51, box2_51);
171+
const Box box2_53 = Box(box2_52, box2_52);
172+
const Box box2_54 = Box(box2_53, box2_53);
173+
const Box box2_55 = Box(box2_54, box2_54);
174+
const Box box2_56 = Box(box2_55, box2_55);
175+
const Box box2_57 = Box(box2_56, box2_56);
176+
const Box box2_58 = Box(box2_57, box2_57);
177+
const Box box2_59 = Box(box2_58, box2_58);
178+
const Box box2_60 = Box(box2_59, box2_59);
179+
const Box box2_61 = Box(box2_60, box2_60);
180+
const Box box2_62 = Box(box2_61, box2_61);
181+
const Box box2_63 = Box(box2_62, box2_62);
182+
const Box box2_64 = Box(box2_63, box2_63);
183+
const Box box2_65 = Box(box2_64, box2_64);
184+
const Box box2_66 = Box(box2_65, box2_65);
185+
const Box box2_67 = Box(box2_66, box2_66);
186+
const Box box2_68 = Box(box2_67, box2_67);
187+
const Box box2_69 = Box(box2_68, box2_68);
188+
const Box box2_70 = Box(box2_69, box2_69);
189+
const Box box2_71 = Box(box2_70, box2_70);
190+
const Box box2_72 = Box(box2_71, box2_71);
191+
const Box box2_73 = Box(box2_72, box2_72);
192+
const Box box2_74 = Box(box2_73, box2_73);
193+
const Box box2_75 = Box(box2_74, box2_74);
194+
const Box box2_76 = Box(box2_75, box2_75);
195+
const Box box2_77 = Box(box2_76, box2_76);
196+
const Box box2_78 = Box(box2_77, box2_77);
197+
const Box box2_79 = Box(box2_78, box2_78);
198+
const Box box2_80 = Box(box2_79, box2_79);
199+
const Box box2_81 = Box(box2_80, box2_80);
200+
const Box box2_82 = Box(box2_81, box2_81);
201+
const Box box2_83 = Box(box2_82, box2_82);
202+
const Box box2_84 = Box(box2_83, box2_83);
203+
const Box box2_85 = Box(box2_84, box2_84);
204+
const Box box2_86 = Box(box2_85, box2_85);
205+
const Box box2_87 = Box(box2_86, box2_86);
206+
const Box box2_88 = Box(box2_87, box2_87);
207+
const Box box2_89 = Box(box2_88, box2_88);
208+
const Box box2_90 = Box(box2_89, box2_89);
209+
const Box box2_91 = Box(box2_90, box2_90);
210+
const Box box2_92 = Box(box2_91, box2_91);
211+
const Box box2_93 = Box(box2_92, box2_92);
212+
const Box box2_94 = Box(box2_93, box2_93);
213+
const Box box2_95 = Box(box2_94, box2_94);
214+
const Box box2_96 = Box(box2_95, box2_95);
215+
const Box box2_97 = Box(box2_96, box2_96);
216+
const Box box2_98 = Box(box2_97, box2_97);
217+
const Box box2_99 = Box(box2_98, box2_98);
218+
219+
Object confuse(Box x) {
220+
try { throw x; } catch (e) { return e; }
221+
}
222+
223+
void main() {
224+
if (!identical(confuse(box1_99), confuse(box2_99))) {
225+
throw Exception('box1_99 !== box2_99');
226+
}
227+
}

0 commit comments

Comments
 (0)