Skip to content

Commit a86db84

Browse files
mralephcommit-bot@chromium.org
authored andcommitted
[fasta] Preserve information about const constructors in outline.
- for classes with const constructors parse field initializers; - for const constructions parse initializer lists and default parameter values; Fixes issue #37357 Fixes issue #36635 Change-Id: Iff0e47f8bd2925cee9f42a2b309de4de84e99cad Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108279 Commit-Queue: Vyacheslav Egorov <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 25319ef commit a86db84

31 files changed

+310
-65
lines changed

pkg/analyzer/lib/src/fasta/ast_builder.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -996,8 +996,14 @@ class AstBuilder extends StackListener {
996996
}
997997

998998
@override
999-
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
1000-
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
999+
void endFormalParameter(
1000+
Token thisKeyword,
1001+
Token periodAfterThis,
1002+
Token nameToken,
1003+
Token initializerStart,
1004+
Token initializerEnd,
1005+
FormalParameterKind kind,
1006+
MemberKind memberKind) {
10011007
assert(optionalOrNull('this', thisKeyword));
10021008
assert(thisKeyword == null
10031009
? periodAfterThis == null

pkg/analyzer/test/generated/parser_fasta_listener.dart

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -762,11 +762,17 @@ class ForwardingTestListener extends ForwardingListener {
762762
}
763763

764764
@override
765-
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
766-
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
765+
void endFormalParameter(
766+
Token thisKeyword,
767+
Token periodAfterThis,
768+
Token nameToken,
769+
Token initializerStart,
770+
Token initializerEnd,
771+
FormalParameterKind kind,
772+
MemberKind memberKind) {
767773
end('FormalParameter');
768-
super.endFormalParameter(
769-
thisKeyword, periodAfterThis, nameToken, kind, memberKind);
774+
super.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
775+
initializerStart, initializerEnd, kind, memberKind);
770776
}
771777

772778
@override

pkg/analyzer/tool/summary/mini_ast.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,14 @@ class MiniAstBuilder extends StackListener {
297297
}
298298

299299
@override
300-
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
301-
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
300+
void endFormalParameter(
301+
Token thisKeyword,
302+
Token periodAfterThis,
303+
Token nameToken,
304+
Token initializerStart,
305+
Token initializerEnd,
306+
FormalParameterKind kind,
307+
MemberKind memberKind) {
302308
debugEvent("FormalParameter");
303309
pop(); // Name
304310
pop(); // Type

pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,6 @@ abstract class FormalParameterBuilder<T extends TypeBuilder>
5050
String get fullNameForErrors => name;
5151

5252
FormalParameterBuilder forFormalParameterInitializerScope();
53+
54+
void buildOutlineExpressions(LibraryBuilder library);
5355
}

pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
633633
ProcedureBuilder<TypeBuilder> member = this.member;
634634
scope = member.computeFormalParameterInitializerScope(scope);
635635
if (member is KernelConstructorBuilder) {
636+
member.prepareInitializers();
636637
if (member.formals != null) {
637638
for (KernelFormalParameterBuilder formal in member.formals) {
638639
if (formal.isInitializingFormal) {
@@ -1128,6 +1129,16 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
11281129
return fakeReturn.expression;
11291130
}
11301131

1132+
void parseInitializers(Token token) {
1133+
Parser parser = new Parser(this);
1134+
if (!token.isEof) {
1135+
token = parser.parseInitializers(token);
1136+
checkEmpty(token.charOffset);
1137+
} else {
1138+
handleNoInitializers();
1139+
}
1140+
}
1141+
11311142
Expression parseFieldInitializer(Token token) {
11321143
Parser parser = new Parser(this);
11331144
token = parser.parseExpression(parser.syntheticPreviousToken(token));
@@ -2886,8 +2897,14 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
28862897
}
28872898

28882899
@override
2889-
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
2890-
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
2900+
void endFormalParameter(
2901+
Token thisKeyword,
2902+
Token periodAfterThis,
2903+
Token nameToken,
2904+
Token initializerStart,
2905+
Token initializerEnd,
2906+
FormalParameterKind kind,
2907+
MemberKind memberKind) {
28912908
debugEvent("FormalParameter");
28922909
if (thisKeyword != null) {
28932910
if (!inConstructor) {

pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ class KernelBodyBuilder extends BodyBuilder {
5959
classBuilder,
6060
member?.isInstanceMember ?? false,
6161
fileUri,
62-
library.loader.typeInferenceEngine
63-
?.createLocalTypeInferrer(fileUri, null, library));
62+
library.loader.typeInferenceEngine?.createLocalTypeInferrer(
63+
fileUri, classBuilder?.target?.thisType, library));
6464

6565
@override
6666
void enterThenForTypePromotion(Expression condition) {

pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,16 @@ class KernelFieldBuilder extends FieldBuilder<Expression> {
109109
ClassBuilder classBuilder = isClassMember ? parent : null;
110110
KernelMetadataBuilder.buildAnnotations(
111111
field, metadata, library, classBuilder, this);
112-
if (constInitializerToken != null) {
112+
113+
// For modular compilation we need to include initializers of all const
114+
// fields and all non-static final fields in classes with const constructors
115+
// into the outline.
116+
if ((isConst ||
117+
(isFinal &&
118+
!isStatic &&
119+
isClassMember &&
120+
classBuilder.hasConstConstructor)) &&
121+
constInitializerToken != null) {
113122
Scope scope = classBuilder?.scope ?? library.scope;
114123
KernelBodyBuilder bodyBuilder =
115124
new KernelBodyBuilder.forOutlineExpression(
@@ -118,7 +127,6 @@ class KernelFieldBuilder extends FieldBuilder<Expression> {
118127
isConst ? ConstantContext.inferred : ConstantContext.none;
119128
initializer = bodyBuilder.parseFieldInitializer(constInitializerToken)
120129
..parent = field;
121-
constInitializerToken = null;
122130
bodyBuilder.typeInferrer
123131
?.inferFieldInitializer(bodyBuilder, field.type, field.initializer);
124132
if (library.loader is SourceLoader) {
@@ -128,6 +136,7 @@ class KernelFieldBuilder extends FieldBuilder<Expression> {
128136
}
129137
bodyBuilder.resolveRedirectingFactoryTargets();
130138
}
139+
constInitializerToken = null;
131140
}
132141

133142
Field get target => field;

pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,28 @@ library fasta.kernel_formal_parameter_builder;
66

77
import 'package:kernel/ast.dart' show VariableDeclaration;
88

9+
import '../constant_context.dart' show ConstantContext;
10+
911
import '../modifier.dart' show finalMask, initializingFormalMask;
1012

13+
import '../scanner.dart' show Token;
14+
15+
import '../scope.dart' show Scope;
16+
17+
import '../source/source_loader.dart' show SourceLoader;
18+
19+
import 'kernel_body_builder.dart' show KernelBodyBuilder;
20+
1121
import 'kernel_builder.dart'
1222
show
1323
ClassBuilder,
1424
Declaration,
1525
FormalParameterBuilder,
26+
KernelConstructorBuilder,
1627
KernelFieldBuilder,
1728
KernelLibraryBuilder,
1829
KernelTypeBuilder,
30+
LibraryBuilder,
1931
MetadataBuilder,
2032
TypeBuilder;
2133

@@ -25,6 +37,8 @@ class KernelFormalParameterBuilder
2537
extends FormalParameterBuilder<KernelTypeBuilder> {
2638
VariableDeclaration declaration;
2739

40+
Token initializerToken;
41+
2842
KernelFormalParameterBuilder(
2943
List<MetadataBuilder> metadata,
3044
int modifiers,
@@ -83,4 +97,31 @@ class KernelFormalParameterBuilder
8397
}
8498
}
8599
}
100+
101+
@override
102+
void buildOutlineExpressions(LibraryBuilder library) {
103+
// For modular compilation we need to include initializers for all
104+
// parameters of const constructors into the outline.
105+
if (parent is KernelConstructorBuilder &&
106+
parent.target.isConst &&
107+
initializerToken != null) {
108+
final ClassBuilder classBuilder = parent.parent;
109+
Scope scope = classBuilder.scope;
110+
KernelBodyBuilder bodyBuilder =
111+
new KernelBodyBuilder.forOutlineExpression(
112+
library, classBuilder, this, scope, fileUri);
113+
bodyBuilder.constantContext = ConstantContext.required;
114+
target.initializer = bodyBuilder.parseFieldInitializer(initializerToken)
115+
..parent = target;
116+
bodyBuilder.typeInferrer?.inferParameterInitializer(
117+
bodyBuilder, target.initializer, target.type);
118+
if (library.loader is SourceLoader) {
119+
SourceLoader loader = library.loader;
120+
loader.transformPostInference(target, bodyBuilder.transformSetLiterals,
121+
bodyBuilder.transformCollections);
122+
}
123+
bodyBuilder.resolveRedirectingFactoryTargets();
124+
}
125+
initializerToken = null;
126+
}
86127
}

pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ class KernelLibraryBuilder
704704
currentDeclaration?.hasConstConstructor = true;
705705
// const constructors will have their initializers compiled and written
706706
// into the outline.
707-
procedure.beginInitializers = beginInitializers;
707+
procedure.beginInitializers = beginInitializers ?? Token.eof(-1);
708708
}
709709
}
710710

@@ -901,12 +901,14 @@ class KernelLibraryBuilder
901901
KernelTypeBuilder type,
902902
String name,
903903
bool hasThis,
904-
int charOffset) {
904+
int charOffset,
905+
Token initializerToken) {
905906
if (hasThis) {
906907
modifiers |= initializingFormalMask;
907908
}
908909
KernelFormalParameterBuilder formal = new KernelFormalParameterBuilder(
909910
metadata, modifiers, type, name, this, charOffset);
911+
formal.initializerToken = initializerToken;
910912
if (legacyMode && hasThis && type == null) {
911913
(untypedInitializingFormals ??= <KernelFormalParameterBuilder>[])
912914
.add(formal);

pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import 'package:kernel/type_algebra.dart' show containsTypeVariable, substitute;
3636

3737
import '../../scanner/token.dart' show Token;
3838

39+
import '../constant_context.dart' show ConstantContext;
40+
3941
import '../loader.dart' show Loader;
4042

4143
import '../messages.dart'
@@ -55,9 +57,13 @@ import '../problems.dart' show unexpected;
5557

5658
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
5759

60+
import '../source/source_loader.dart' show SourceLoader;
61+
5862
import '../type_inference/type_inference_engine.dart'
5963
show IncludesTypeParametersCovariantly;
6064

65+
import 'kernel_body_builder.dart' show KernelBodyBuilder;
66+
6167
import 'kernel_builder.dart'
6268
show
6369
ClassBuilder,
@@ -238,6 +244,22 @@ abstract class KernelFunctionBuilder
238244

239245
Member build(SourceLibraryBuilder library);
240246

247+
@override
248+
void buildOutlineExpressions(LibraryBuilder library) {
249+
KernelMetadataBuilder.buildAnnotations(
250+
target, metadata, library, isClassMember ? parent : null, this);
251+
252+
if (formals != null) {
253+
// For const constructors we need to include default parameter values
254+
// into the outline. For all other formals we need to call
255+
// buildOutlineExpressions to clear initializerToken to prevent
256+
// consuming too much memory.
257+
for (FormalParameterBuilder<KernelTypeBuilder> formal in formals) {
258+
formal.buildOutlineExpressions(library);
259+
}
260+
}
261+
}
262+
241263
void becomeNative(Loader loader) {
242264
Declaration constructor = loader.getNativeAnnotation();
243265
Arguments arguments =
@@ -359,12 +381,6 @@ class KernelProcedureBuilder extends KernelFunctionBuilder {
359381
return procedure;
360382
}
361383

362-
@override
363-
void buildOutlineExpressions(LibraryBuilder library) {
364-
KernelMetadataBuilder.buildAnnotations(
365-
target, metadata, library, isClassMember ? parent : null, this);
366-
}
367-
368384
Procedure get target => origin.procedure;
369385

370386
@override
@@ -491,8 +507,24 @@ class KernelConstructorBuilder extends KernelFunctionBuilder {
491507

492508
@override
493509
void buildOutlineExpressions(LibraryBuilder library) {
494-
KernelMetadataBuilder.buildAnnotations(
495-
target, metadata, library, parent, this);
510+
super.buildOutlineExpressions(library);
511+
512+
// For modular compilation purposes we need to include initializers
513+
// for const constructors into the outline.
514+
if (isConst && beginInitializers != null) {
515+
ClassBuilder classBuilder = parent;
516+
KernelBodyBuilder bodyBuilder =
517+
new KernelBodyBuilder.forOutlineExpression(
518+
library, classBuilder, this, classBuilder.scope, fileUri);
519+
bodyBuilder.constantContext = ConstantContext.inferred;
520+
bodyBuilder.parseInitializers(beginInitializers);
521+
if (library.loader is SourceLoader) {
522+
SourceLoader loader = library.loader;
523+
loader.transformPostInference(target, bodyBuilder.transformSetLiterals,
524+
bodyBuilder.transformCollections);
525+
}
526+
bodyBuilder.resolveRedirectingFactoryTargets();
527+
}
496528
beginInitializers = null;
497529
}
498530

@@ -601,6 +633,21 @@ class KernelConstructorBuilder extends KernelFunctionBuilder {
601633
reportPatchMismatch(patch);
602634
}
603635
}
636+
637+
void prepareInitializers() {
638+
// For const constructors we parse initializers already at the outlining
639+
// stage, there is no easy way to make body building stage skip initializer
640+
// parsing, so we simply clear parsed initializers and rebuild them
641+
// again.
642+
// Note: this method clears both initializers from the target Kernel node
643+
// and internal state associated with parsing initializers.
644+
if (target.isConst) {
645+
target.initializers.length = 0;
646+
redirectingInitializer = null;
647+
superInitializer = null;
648+
hasMovedSuperInitializer = false;
649+
}
650+
}
604651
}
605652

606653
class KernelRedirectingFactoryBuilder extends KernelProcedureBuilder {

0 commit comments

Comments
 (0)