Skip to content

Commit e0c0cab

Browse files
scheglovCommit Queue
authored andcommitted
Macro. Code optimizer. Update initializers of final fields, when has const constructor.
Change-Id: I7a0097e240c2e54c47e6a24cb07054f656950ea8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/353582 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Phil Quitslund <pquitslund@google.com>
1 parent 35c6cc6 commit e0c0cab

File tree

3 files changed

+152
-9
lines changed

3 files changed

+152
-9
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class LibraryBuilder {
191191
/// The fields that were speculatively created as [ConstFieldElementImpl],
192192
/// but we want to clear [ConstVariableElement.constantInitializer] for it
193193
/// if the class will not end up with a `const` constructor. We don't know
194-
/// at the time when we create them, because of future augmentations, use
194+
/// at the time when we create them, because of future augmentations, user
195195
/// written or macro generated.
196196
final Set<ConstFieldElementImpl> finalInstanceFields = Set.identity();
197197

@@ -555,6 +555,7 @@ class LibraryBuilder {
555555
augmentation: augmentation,
556556
).perform(updateConstants: () {
557557
MacroUpdateConstantsForOptimizedCode(
558+
libraryElement: element,
558559
unitNode: mergedUnit,
559560
codeEdits: optimizedCodeEdits,
560561
unitElement: unitElement,

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

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ class MacroElementsMerger {
235235
}
236236

237237
class MacroUpdateConstantsForOptimizedCode {
238+
/// The container of [unitElement].
239+
final LibraryElementImpl libraryElement;
240+
238241
/// The parsed merged code.
239242
final ast.CompilationUnit unitNode;
240243

@@ -245,7 +248,11 @@ class MacroUpdateConstantsForOptimizedCode {
245248
/// The merged element, with elements in the same order as in [unitNode].
246249
final CompilationUnitElementImpl unitElement;
247250

251+
/// The names of classes that have a `const` constructor.
252+
final Set<String> _namesOfConstClasses = {};
253+
248254
MacroUpdateConstantsForOptimizedCode({
255+
required this.libraryElement,
249256
required this.unitNode,
250257
required this.codeEdits,
251258
required this.unitElement,
@@ -263,6 +270,7 @@ class MacroUpdateConstantsForOptimizedCode {
263270
/// The same elements, in the same order.
264271
/// If not, we have a bug in [MacroElementsMerger].
265272
void perform() {
273+
_findConstClasses();
266274
var nodeRecords = _orderedForNodes();
267275
var elementRecords = _orderedForElement();
268276
assert(nodeRecords.length == elementRecords.length);
@@ -295,6 +303,21 @@ class MacroUpdateConstantsForOptimizedCode {
295303
}
296304
}
297305

306+
void _findConstClasses() {
307+
for (var element in libraryElement.topLevelElements) {
308+
if (element is! ClassElementImpl) continue;
309+
if (element.isAugmentation) continue;
310+
311+
var augmented = element.augmented;
312+
if (augmented == null) continue;
313+
314+
var hasConst = augmented.constructors.any((e) => e.isConst);
315+
if (hasConst) {
316+
_namesOfConstClasses.add(element.name);
317+
}
318+
}
319+
}
320+
298321
List<(ElementImpl, ast.AstNodeImpl)> _orderedForElement() {
299322
var result = <(ElementImpl, ast.AstNodeImpl)>[];
300323

@@ -390,22 +413,31 @@ class MacroUpdateConstantsForOptimizedCode {
390413

391414
void addVariableList(
392415
ast.VariableDeclarationListImpl variableList,
393-
List<ast.AnnotationImpl> metadata,
394-
) {
416+
List<ast.AnnotationImpl> metadata, {
417+
required bool withFinals,
418+
}) {
395419
for (var variable in variableList.variables) {
396420
addMetadata(variable, metadata);
397-
if (variableList.isConst) {
421+
422+
if (variableList.isConst || variableList.isFinal && withFinals) {
398423
if (variable.initializer case var initializer?) {
399424
result.add((variable, initializer));
400425
}
401426
}
402427
}
403428
}
404429

405-
void addInterfaceMembers(List<ast.ClassMemberImpl> members) {
430+
void addInterfaceMembers(
431+
List<ast.ClassMemberImpl> members, {
432+
required bool hasConstConstructor,
433+
}) {
406434
for (var field in members) {
407435
if (field is ast.FieldDeclarationImpl) {
408-
addVariableList(field.fields, field.metadata);
436+
addVariableList(
437+
field.fields,
438+
field.metadata,
439+
withFinals: hasConstConstructor && !field.isStatic,
440+
);
409441
}
410442
}
411443

@@ -438,13 +470,22 @@ class MacroUpdateConstantsForOptimizedCode {
438470
for (var class_ in unitNode.declarations) {
439471
if (class_ is ast.ClassDeclarationImpl) {
440472
addAnnotatedNode(class_);
441-
addInterfaceMembers(class_.members);
473+
addInterfaceMembers(
474+
class_.members,
475+
hasConstConstructor: _namesOfConstClasses.contains(
476+
class_.name.lexeme,
477+
),
478+
);
442479
}
443480
}
444481

445482
for (var topVariable in unitNode.declarations) {
446483
if (topVariable is ast.TopLevelVariableDeclarationImpl) {
447-
addVariableList(topVariable.variables, topVariable.metadata);
484+
addVariableList(
485+
topVariable.variables,
486+
topVariable.metadata,
487+
withFinals: false,
488+
);
448489
}
449490
}
450491

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

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2861,7 +2861,7 @@ augment class A {
28612861
''');
28622862
}
28632863

2864-
test_codeOptimizer_constant_classField_constant() async {
2864+
test_codeOptimizer_constant_classField_const() async {
28652865
newFile('$testPackageLibPath/a.dart', r'''
28662866
const a = 0;
28672867
''');
@@ -2913,6 +2913,107 @@ augment class B {
29132913
''');
29142914
}
29152915

2916+
test_codeOptimizer_constant_classField_final_hasConstConstructor() async {
2917+
newFile('$testPackageLibPath/a.dart', r'''
2918+
const a = 0;
2919+
''');
2920+
2921+
var library = await buildLibrary(r'''
2922+
import 'append.dart';
2923+
import 'a.dart';
2924+
2925+
@DeclareInType(' final x = {{package:test/a.dart@a}};')
2926+
class B {
2927+
const B();
2928+
}
2929+
''');
2930+
2931+
configuration.forCodeOptimizer();
2932+
checkElementText(library, r'''
2933+
library
2934+
imports
2935+
package:test/append.dart
2936+
package:test/a.dart
2937+
augmentationImports
2938+
package:test/test.macro.dart
2939+
macroGeneratedCode
2940+
---
2941+
library augment 'test.dart';
2942+
2943+
import 'package:test/a.dart';
2944+
2945+
augment class B {
2946+
final x = a;
2947+
}
2948+
---
2949+
imports
2950+
package:test/a.dart
2951+
definingUnit
2952+
classes
2953+
augment class B @75
2954+
augmentationTarget: self::@class::B
2955+
fields
2956+
final x @87
2957+
type: int
2958+
shouldUseTypeForInitializerInference: false
2959+
constantInitializer
2960+
SimpleIdentifier
2961+
token: a @91
2962+
staticElement: package:test/a.dart::@getter::a
2963+
staticType: int
2964+
accessors
2965+
synthetic get x @-1
2966+
returnType: int
2967+
''');
2968+
}
2969+
2970+
test_codeOptimizer_constant_classField_final_noConstConstructor() async {
2971+
newFile('$testPackageLibPath/a.dart', r'''
2972+
const a = 0;
2973+
''');
2974+
2975+
var library = await buildLibrary(r'''
2976+
import 'append.dart';
2977+
import 'a.dart';
2978+
2979+
@DeclareInType(' final x = {{package:test/a.dart@a}};')
2980+
class B {}
2981+
''');
2982+
2983+
configuration.forCodeOptimizer();
2984+
checkElementText(library, r'''
2985+
library
2986+
imports
2987+
package:test/append.dart
2988+
package:test/a.dart
2989+
augmentationImports
2990+
package:test/test.macro.dart
2991+
macroGeneratedCode
2992+
---
2993+
library augment 'test.dart';
2994+
2995+
import 'package:test/a.dart';
2996+
2997+
augment class B {
2998+
final x = a;
2999+
}
3000+
---
3001+
imports
3002+
package:test/a.dart
3003+
definingUnit
3004+
classes
3005+
augment class B @75
3006+
augmentationTarget: self::@class::B
3007+
fields
3008+
final x @87
3009+
type: int
3010+
shouldUseTypeForInitializerInference: false
3011+
accessors
3012+
synthetic get x @-1
3013+
returnType: int
3014+
''');
3015+
}
3016+
29163017
test_codeOptimizer_constant_classField_namedType() async {
29173018
newFile('$testPackageLibPath/a.dart', r'''
29183019
class A<T> {}

0 commit comments

Comments
 (0)