Version 3.8.0-207.0.dev
Merge 47f7972a2fbb9b906a33d45bb06b10532ca6b41d into dev
diff --git a/docs/gsoc/Dart-GSoC-2025-Project-Ideas.md b/docs/gsoc/Dart-GSoC-2025-Project-Ideas.md
index 6db1a6c..d6b399f 100644
--- a/docs/gsoc/Dart-GSoC-2025-Project-Ideas.md
+++ b/docs/gsoc/Dart-GSoC-2025-Project-Ideas.md
@@ -126,7 +126,7 @@
- **Possible Mentor(s)**: `mudit.somani00@gmail.com`
- **Difficulty**: Medium
- - **Project size**: Medium (175 hours)
+ - **Project size**: Large (350 hours)
- **Skills**: Dart, CLIs
**Description**: Dart is already used to create GUI applications through Flutter, it would be great if it can also be used to develop good looking TUI applications. Currently the language of choice for TUI development would be either Golang or Python due to their developed package ecosystems (like [charm](https://charm.sh/) or [textual](https://www.textualize.io/)) so a package that makes TUI development easier and faster on dart would increase its adoption in that space.
@@ -141,6 +141,8 @@
* Composable methods to style text on the terminal (kinda like [libgloss](https://github.com/charmbracelet/lipgloss)).
* Component based model to render and interact with terminal based text inputs and checkboxes (kinda like [bubbles](https://github.com/charmbracelet/bubbles)).
+* Functions to detect terminal width/height and enter fullscreen mode (alternate screen buffer).
+* Handle pointer events in the terminal (like clicking buttons).
**Expected outcome**: A package on pub.dev with terminal primitives like text styling, inputs, checkboxes, tables, layouts, spinners etc.
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 2829f7e..f69a1a7 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -764,6 +764,7 @@
abbr: 'E',
help: 'An extra option to pass to the dart2wasm compiler.',
hide: !verbose,
+ splitCommas: false,
)
..addOption(
'optimization-level',
diff --git a/pkg/dynamic_modules/test/data/extension_type/dynamic_interface.yaml b/pkg/dynamic_modules/test/data/extension_type/dynamic_interface.yaml
new file mode 100644
index 0000000..30007df
--- /dev/null
+++ b/pkg/dynamic_modules/test/data/extension_type/dynamic_interface.yaml
@@ -0,0 +1,16 @@
+# Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+callable:
+ - library: 'shared/shared.dart'
+ # TODO(sigmund): This should be included by default
+ - library: 'dart:core'
+ class: 'Object'
+ - library: 'dart:core'
+ class: 'int'
+ - library: 'dart:core'
+ class: 'String'
+ - library: 'dart:core'
+ class: 'pragma'
+ member: '_'
diff --git a/pkg/dynamic_modules/test/data/extension_type/main.dart b/pkg/dynamic_modules/test/data/extension_type/main.dart
new file mode 100644
index 0000000..768525b
--- /dev/null
+++ b/pkg/dynamic_modules/test/data/extension_type/main.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../../common/testing.dart' as helper;
+import 'package:expect/expect.dart';
+
+import 'shared/shared.dart'; // ignore: unused_import
+
+/// A dynamic module is allowed to extend a class in the dynamic interface and
+/// override its members.
+void main() async {
+ final result = (await helper.load('entry1.dart')) as String;
+ Expect.equals('abcdef42', result);
+ helper.done();
+}
diff --git a/pkg/dynamic_modules/test/data/extension_type/modules/entry1.dart b/pkg/dynamic_modules/test/data/extension_type/modules/entry1.dart
new file mode 100644
index 0000000..43d37a2
--- /dev/null
+++ b/pkg/dynamic_modules/test/data/extension_type/modules/entry1.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../shared/shared.dart';
+
+@pragma('dyn-module:entry-point')
+Object? dynamicModuleEntrypoint() =>
+ 'abc'.addSuffix('def') + MyExtensionType.foo(42).info.toString();
diff --git a/pkg/dynamic_modules/test/data/extension_type/shared/shared.dart b/pkg/dynamic_modules/test/data/extension_type/shared/shared.dart
new file mode 100644
index 0000000..8e8a160
--- /dev/null
+++ b/pkg/dynamic_modules/test/data/extension_type/shared/shared.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension type MyExtensionType.foo(int _info) {
+ int get info => _info;
+}
+
+extension MyExtension on String {
+ String addSuffix(String suffix) => this + suffix;
+}
diff --git a/pkg/front_end/lib/src/fragment/enum_element.dart b/pkg/front_end/lib/src/fragment/enum_element.dart
index 3e333e0..133baf3 100644
--- a/pkg/front_end/lib/src/fragment/enum_element.dart
+++ b/pkg/front_end/lib/src/fragment/enum_element.dart
@@ -133,7 +133,7 @@
required bool createFileUriExpression}) {
BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
for (Annotatable annotatable in annotatables) {
- _buildMetadataForOutlineExpressions(libraryBuilder, enclosingScope,
+ buildMetadataForOutlineExpressions(libraryBuilder, enclosingScope,
bodyBuilderContext, annotatable, metadata,
fileUri: fileUri, createFileUriExpression: createFileUriExpression);
}
diff --git a/pkg/front_end/lib/src/fragment/field.dart b/pkg/front_end/lib/src/fragment/field.dart
index 20d8b34..eb8de1a 100644
--- a/pkg/front_end/lib/src/fragment/field.dart
+++ b/pkg/front_end/lib/src/fragment/field.dart
@@ -298,7 +298,7 @@
required bool createFileUriExpression}) {
BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
for (Annotatable annotatable in annotatables) {
- _buildMetadataForOutlineExpressions(libraryBuilder, enclosingScope,
+ buildMetadataForOutlineExpressions(libraryBuilder, enclosingScope,
bodyBuilderContext, annotatable, metadata,
fileUri: fileUri, createFileUriExpression: createFileUriExpression);
}
diff --git a/pkg/front_end/lib/src/fragment/fragment.dart b/pkg/front_end/lib/src/fragment/fragment.dart
index d2d4e30..95eff56 100644
--- a/pkg/front_end/lib/src/fragment/fragment.dart
+++ b/pkg/front_end/lib/src/fragment/fragment.dart
@@ -62,6 +62,10 @@
import '../type_inference/type_inferrer.dart';
import '../type_inference/type_schema.dart';
import 'constructor/declaration.dart';
+import 'getter/declaration.dart';
+import 'getter/encoding.dart';
+import 'setter/declaration.dart';
+import 'setter/encoding.dart';
part 'class.dart';
part 'class/declaration.dart';
diff --git a/pkg/front_end/lib/src/fragment/getter.dart b/pkg/front_end/lib/src/fragment/getter.dart
index e3f0079..ea4731f 100644
--- a/pkg/front_end/lib/src/fragment/getter.dart
+++ b/pkg/front_end/lib/src/fragment/getter.dart
@@ -61,7 +61,7 @@
SourcePropertyBuilder? _builder;
- late final _GetterEncoding _encoding;
+ GetterDeclaration? _declaration;
GetterFragment({
required this.name,
@@ -91,19 +91,20 @@
return _builder!;
}
- void setBuilder(
- ProblemReporting problemReporting,
- SourcePropertyBuilder value,
- PropertyEncodingStrategy encodingStrategy,
- List<NominalParameterBuilder> unboundNominalParameters) {
+ void set builder(SourcePropertyBuilder value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
- _encoding = encodingStrategy.createGetterEncoding(
- value, this, unboundNominalParameters);
- typeParameterNameSpace.addTypeParameters(
- problemReporting, _encoding.clonedAndDeclaredTypeParameters,
- ownerName: name, allowNameConflict: true);
- returnType.registerInferredTypeListener(_encoding);
+ }
+
+ GetterDeclaration get declaration {
+ assert(_declaration != null, "Builder has not been computed for $this.");
+ return _declaration!;
+ }
+
+ void set declaration(GetterDeclaration value) {
+ assert(_declaration == null,
+ "Declaration has already been computed for $this.");
+ _declaration = value;
}
@override
@@ -111,82 +112,6 @@
return new _GetterBodyBuildingContext(this);
}
- void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
- {required List<TypeParameter>? classTypeParameters}) {
- _encoding.buildOutlineNode(libraryBuilder, nameScheme, f, references,
- isAbstractOrExternal: modifiers.isAbstract || modifiers.isExternal,
- classTypeParameters: classTypeParameters);
- }
-
- void buildOutlineExpressions(
- ClassHierarchy classHierarchy,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- Annotatable annotatable,
- {required bool isClassInstanceMember,
- required bool createFileUriExpression}) {
- _encoding.buildOutlineExpressions(classHierarchy, libraryBuilder,
- declarationBuilder, createBodyBuilderContext(), annotatable,
- isClassInstanceMember: isClassInstanceMember,
- createFileUriExpression: createFileUriExpression);
- }
-
- Iterable<Reference> getExportedMemberReferences(GetterReference references) =>
- [references.getterReference];
-
- BodyBuilderContext createBodyBuilderContext() {
- return new _GetterFragmentBodyBuilderContext(
- this, builder.libraryBuilder, builder.declarationBuilder,
- isDeclarationInstanceMember: builder.isDeclarationInstanceMember);
- }
-
- void becomeNative(SourceLoader loader) {
- _encoding.becomeNative(loader);
- }
-
- int computeDefaultTypes(ComputeDefaultTypeContext context) {
- return _encoding.computeDefaultTypes(context);
- }
-
- void ensureTypes(ClassMembersBuilder membersBuilder,
- Set<ClassMember>? getterOverrideDependencies) {
- if (getterOverrideDependencies != null) {
- membersBuilder.inferGetterType(
- builder.declarationBuilder as SourceClassBuilder,
- returnType,
- getterOverrideDependencies,
- name: name,
- fileUri: fileUri,
- nameOffset: nameOffset,
- nameLength: name.length);
- }
- _encoding.ensureTypes(
- builder.libraryBuilder, membersBuilder.hierarchyBuilder);
- }
-
- void checkTypes(SourceLibraryBuilder libraryBuilder,
- TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
- {required bool isAbstract, required bool isExternal}) {
- _encoding.checkTypes(libraryBuilder, typeEnvironment, setterBuilder,
- isAbstract: isAbstract, isExternal: isExternal);
- }
-
- void checkVariance(
- SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
- _encoding.checkVariance(sourceClassBuilder, typeEnvironment);
- }
-
- Procedure get readTarget => _encoding.readTarget;
-
- // Coverage-ignore(suite): Not run.
- List<NominalParameterBuilder>? get typeParametersForTesting =>
- _encoding.clonedAndDeclaredTypeParameters;
-
- // Coverage-ignore(suite): Not run.
- List<FormalParameterBuilder>? get formalsForTesting =>
- _encoding.formalsForTesting;
-
@override
String toString() => '$runtimeType($name,$fileUri,$nameOffset)';
}
@@ -208,7 +133,7 @@
@override
LocalScope computeFormalParameterScope(LookupScope typeParameterScope) {
- return _fragment._encoding.createFormalParameterScope(typeParameterScope);
+ return _fragment.declaration.createFormalParameterScope(typeParameterScope);
}
@override
@@ -218,7 +143,7 @@
@override
BodyBuilderContext createBodyBuilderContext() {
- return _fragment.createBodyBuilderContext();
+ return _fragment.declaration.createBodyBuilderContext(_fragment.builder);
}
@override
@@ -230,716 +155,8 @@
@override
List<TypeParameter>? get thisTypeParameters =>
- _fragment._encoding.thisTypeParameters;
+ _fragment.declaration.thisTypeParameters;
@override
- VariableDeclaration? get thisVariable => _fragment._encoding.thisVariable;
-}
-
-sealed class _GetterEncoding implements InferredTypeListener {
- VariableDeclaration? get thisVariable;
- List<TypeParameter>? get thisTypeParameters;
- FunctionNode get function;
- Procedure get readTarget;
-
- void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
- {required bool isAbstractOrExternal,
- required List<TypeParameter>? classTypeParameters});
-
- void buildOutlineExpressions(
- ClassHierarchy classHierarchy,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- BodyBuilderContext bodyBuilderContext,
- Annotatable annotatable,
- {required bool isClassInstanceMember,
- required bool createFileUriExpression});
-
- LocalScope createFormalParameterScope(LookupScope typeParameterScope);
-
- int computeDefaultTypes(ComputeDefaultTypeContext context);
-
- void ensureTypes(
- SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy);
-
- void becomeNative(SourceLoader loader);
-
- List<FormalParameterBuilder>? get formals;
-
- VariableDeclaration getFormalParameter(int index);
-
- void checkTypes(SourceLibraryBuilder libraryBuilder,
- TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
- {required bool isAbstract, required bool isExternal});
-
- void checkVariance(
- SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
-
- List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters;
-
- List<FormalParameterBuilder>? get formalsForTesting;
-}
-
-mixin _DirectGetterEncodingMixin implements _GetterEncoding {
- GetterFragment get _fragment;
-
- Procedure? _procedure;
-
- @override
- VariableDeclaration? get thisVariable => null;
-
- @override
- List<TypeParameter>? get thisTypeParameters => null;
-
- BuiltMemberKind get _builtMemberKind;
-
- bool get _isExtensionMember;
-
- bool get _isExtensionTypeMember;
-
- @override
- void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
- {required bool isAbstractOrExternal,
- List<TypeParameter>? classTypeParameters}) {
- FunctionNode function = new FunctionNode(
- isAbstractOrExternal ? null : new EmptyStatement(),
- asyncMarker: _fragment.asyncModifier)
- ..fileOffset = _fragment.formalsOffset
- ..fileEndOffset = _fragment.endOffset;
- buildTypeParametersAndFormals(
- libraryBuilder,
- function,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders,
- _fragment.declaredFormals,
- classTypeParameters: classTypeParameters,
- supportsTypeParameters: true);
- if (_fragment.returnType is! InferableTypeBuilder) {
- function.returnType =
- _fragment.returnType.build(libraryBuilder, TypeUse.returnType);
- }
-
- MemberName memberName =
- nameScheme.getProcedureMemberName(ProcedureKind.Getter, _fragment.name);
- Procedure procedure = _procedure = new Procedure(
- memberName.name, ProcedureKind.Getter, function,
- reference: references.getterReference, fileUri: _fragment.fileUri)
- ..fileStartOffset = _fragment.startOffset
- ..fileOffset = _fragment.nameOffset
- ..fileEndOffset = _fragment.endOffset
- ..isAbstract = _fragment.modifiers.isAbstract
- ..isExternal = _fragment.modifiers.isExternal
- ..isConst = _fragment.modifiers.isConst
- ..isStatic = _fragment.modifiers.isStatic
- ..isExtensionMember = _isExtensionMember
- ..isExtensionTypeMember = _isExtensionTypeMember;
- memberName.attachMember(procedure);
-
- f(kind: _builtMemberKind, member: procedure);
- }
-
- @override
- void buildOutlineExpressions(
- ClassHierarchy classHierarchy,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- BodyBuilderContext bodyBuilderContext,
- Annotatable annotatable,
- {required bool isClassInstanceMember,
- required bool createFileUriExpression}) {
- _buildMetadataForOutlineExpressions(
- libraryBuilder,
- _fragment.enclosingScope,
- bodyBuilderContext,
- annotatable,
- _fragment.metadata,
- fileUri: _fragment.fileUri,
- createFileUriExpression: createFileUriExpression);
- _buildTypeParametersForOutlineExpressions(
- classHierarchy,
- libraryBuilder,
- bodyBuilderContext,
- _fragment.typeParameterScope,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- _buildFormalsForOutlineExpressions(
- libraryBuilder, declarationBuilder, _fragment.declaredFormals,
- scope: _fragment.typeParameterScope,
- isClassInstanceMember: isClassInstanceMember);
- }
-
- @override
- FunctionNode get function => _procedure!.function;
-
- @override
- Procedure get readTarget => _procedure!;
-
- @override
- LocalScope createFormalParameterScope(LookupScope typeParameterScope) {
- return new FormalParameterScope(parent: typeParameterScope);
- }
-
- @override
- int computeDefaultTypes(ComputeDefaultTypeContext context) {
- bool hasErrors = context.reportSimplicityIssuesForTypeParameters(_fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
- if (_fragment.returnType is! OmittedTypeBuilder) {
- hasErrors |=
- context.reportInboundReferenceIssuesForType(_fragment.returnType);
- context.recursivelyReportGenericFunctionTypesAsBoundsForType(
- _fragment.returnType);
- }
- return context.computeDefaultTypesForVariables(
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders,
- inErrorRecovery: hasErrors);
- }
-
- @override
- void ensureTypes(
- SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy) {
- _fragment.returnType
- .build(libraryBuilder, TypeUse.returnType, hierarchy: hierarchy);
- }
-
- @override
- void onInferredType(DartType type) {
- function.returnType = type;
- }
-
- @override
- void becomeNative(SourceLoader loader) {
- loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
- }
-
- @override
- List<FormalParameterBuilder>? get formals => _fragment.declaredFormals;
-
- @override
- VariableDeclaration getFormalParameter(int index) =>
- _fragment.declaredFormals![index].variable!;
-
- @override
- void checkTypes(SourceLibraryBuilder libraryBuilder,
- TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
- {required bool isAbstract, required bool isExternal}) {
- List<TypeParameterBuilder>? typeParameters = _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders;
- // Coverage-ignore(suite): Not run.
- if (typeParameters != null && typeParameters.isNotEmpty) {
- libraryBuilder.checkTypeParameterDependencies(typeParameters);
- }
- libraryBuilder.checkInitializersInFormals(
- _fragment.declaredFormals, typeEnvironment,
- isAbstract: isAbstract, isExternal: isExternal);
- if (setterBuilder != null) {
- DartType getterType = function.returnType;
- DartType setterType = SourcePropertyBuilder.getSetterType(setterBuilder,
- getterExtensionTypeParameters: null);
- libraryBuilder.checkGetterSetterTypes(typeEnvironment,
- getterType: getterType,
- getterName: _fragment.name,
- getterFileOffset: _fragment.nameOffset,
- getterFileUri: _fragment.fileUri,
- getterNameLength: _fragment.name.length,
- setterType: setterType,
- setterName: setterBuilder.name,
- setterFileOffset: setterBuilder.fileOffset,
- setterFileUri: setterBuilder.fileUri,
- setterNameLength: setterBuilder.name.length);
- }
- }
-
- @override
- void checkVariance(
- SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
- sourceClassBuilder.checkVarianceInTypeParameters(
- typeEnvironment,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- sourceClassBuilder.checkVarianceInFormals(
- typeEnvironment, _fragment.declaredFormals);
- sourceClassBuilder.checkVarianceInReturnType(
- typeEnvironment, function.returnType,
- fileOffset: _fragment.nameOffset, fileUri: _fragment.fileUri);
- }
-
- @override
- List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders;
-
- @override
- // Coverage-ignore(suite): Not run.
- List<FormalParameterBuilder>? get formalsForTesting =>
- _fragment.declaredFormals;
-}
-
-class _RegularGetterEncoding extends _GetterEncoding
- with _DirectGetterEncodingMixin {
- @override
- final GetterFragment _fragment;
-
- _RegularGetterEncoding(this._fragment);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.Method;
-
- @override
- bool get _isExtensionMember => false;
-
- @override
- bool get _isExtensionTypeMember => false;
-}
-
-class _ExtensionStaticGetterEncoding extends _GetterEncoding
- with _DirectGetterEncodingMixin {
- @override
- final GetterFragment _fragment;
-
- _ExtensionStaticGetterEncoding(this._fragment);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionGetter;
-
- @override
- bool get _isExtensionMember => true;
-
- @override
- bool get _isExtensionTypeMember => false;
-}
-
-class _ExtensionTypeStaticGetterEncoding extends _GetterEncoding
- with _DirectGetterEncodingMixin {
- @override
- final GetterFragment _fragment;
-
- _ExtensionTypeStaticGetterEncoding(this._fragment);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeGetter;
-
- @override
- bool get _isExtensionMember => false;
-
- @override
- bool get _isExtensionTypeMember => true;
-}
-
-mixin _ExtensionInstanceGetterEncodingMixin implements _GetterEncoding {
- GetterFragment get _fragment;
-
- List<NominalParameterBuilder>? get _clonedDeclarationTypeParameters;
-
- FormalParameterBuilder get _thisFormal;
-
- Procedure? _procedure;
-
- @override
- void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
- {required bool isAbstractOrExternal,
- required List<TypeParameter>? classTypeParameters}) {
- List<TypeParameter>? typeParameters;
- if (_clonedDeclarationTypeParameters != null) {
- typeParameters = [];
- // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both required
- // and unnecessary.
- // ignore: unnecessary_non_null_assertion
- for (NominalParameterBuilder t in _clonedDeclarationTypeParameters!) {
- typeParameters.add(t.parameter);
- }
- }
- FunctionNode function = new FunctionNode(
- isAbstractOrExternal ? null : new EmptyStatement(),
- typeParameters: typeParameters,
- positionalParameters: [_thisFormal.build(libraryBuilder)],
- asyncMarker: _fragment.asyncModifier)
- ..fileOffset = _fragment.formalsOffset
- ..fileEndOffset = _fragment.endOffset;
- buildTypeParametersAndFormals(
- libraryBuilder,
- function,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders,
- _fragment.declaredFormals,
- classTypeParameters: classTypeParameters,
- supportsTypeParameters: true);
- if (_fragment.returnType is! InferableTypeBuilder) {
- function.returnType =
- _fragment.returnType.build(libraryBuilder, TypeUse.returnType);
- }
-
- MemberName memberName =
- nameScheme.getProcedureMemberName(ProcedureKind.Getter, _fragment.name);
- Procedure procedure = _procedure = new Procedure(
- memberName.name, ProcedureKind.Method, function,
- reference: references.getterReference, fileUri: _fragment.fileUri)
- ..fileStartOffset = _fragment.startOffset
- ..fileOffset = _fragment.nameOffset
- ..fileEndOffset = _fragment.endOffset
- ..isAbstract = _fragment.modifiers.isAbstract
- ..isExternal = _fragment.modifiers.isExternal
- ..isConst = _fragment.modifiers.isConst
- ..isStatic = true
- ..isExtensionMember = _isExtensionMember
- ..isExtensionTypeMember = _isExtensionTypeMember;
- memberName.attachMember(procedure);
-
- f(kind: _builtMemberKind, member: procedure);
- }
-
- @override
- void buildOutlineExpressions(
- ClassHierarchy classHierarchy,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- BodyBuilderContext bodyBuilderContext,
- Annotatable annotatable,
- {required bool isClassInstanceMember,
- required bool createFileUriExpression}) {
- _buildMetadataForOutlineExpressions(
- libraryBuilder,
- _fragment.enclosingScope,
- bodyBuilderContext,
- annotatable,
- _fragment.metadata,
- fileUri: _fragment.fileUri,
- createFileUriExpression: createFileUriExpression);
-
- _buildTypeParametersForOutlineExpressions(
- classHierarchy,
- libraryBuilder,
- bodyBuilderContext,
- _fragment.typeParameterScope,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- _buildFormalsForOutlineExpressions(
- libraryBuilder, declarationBuilder, _fragment.declaredFormals,
- scope: _fragment.typeParameterScope,
- isClassInstanceMember: isClassInstanceMember);
-
- _buildTypeParametersForOutlineExpressions(
- classHierarchy,
- libraryBuilder,
- bodyBuilderContext,
- _fragment.typeParameterScope,
- _clonedDeclarationTypeParameters);
- _buildFormalForOutlineExpressions(
- libraryBuilder, declarationBuilder, _thisFormal,
- scope: _fragment.typeParameterScope,
- isClassInstanceMember: isClassInstanceMember);
- }
-
- @override
- FunctionNode get function => _procedure!.function;
-
- @override
- Procedure get readTarget => _procedure!;
-
- @override
- List<TypeParameter>? get thisTypeParameters =>
- _clonedDeclarationTypeParameters != null ? function.typeParameters : null;
-
- @override
- VariableDeclaration? get thisVariable => _thisFormal.variable!;
-
- @override
- LocalScope createFormalParameterScope(LookupScope typeParameterScope) {
- Map<String, Builder> local = <String, Builder>{};
- assert(!_thisFormal.isWildcard);
- local[_thisFormal.name] = _thisFormal;
- return new FormalParameterScope(local: local, parent: typeParameterScope);
- }
-
- @override
- int computeDefaultTypes(ComputeDefaultTypeContext context) {
- bool hasErrors = context.reportSimplicityIssuesForTypeParameters(_fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
- if (_fragment.returnType is! OmittedTypeBuilder) {
- hasErrors |=
- context.reportInboundReferenceIssuesForType(_fragment.returnType);
- context.recursivelyReportGenericFunctionTypesAsBoundsForType(
- _fragment.returnType);
- }
- if (_clonedDeclarationTypeParameters != null &&
- _fragment.declaredTypeParameters != null) {
- // Coverage-ignore-block(suite): Not run.
- // We need to compute all default types together since they might be
- // interdependent.
- return context.computeDefaultTypesForVariables([
- // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both
- // required and unnecessary.
- // ignore: unnecessary_non_null_assertion
- ..._clonedDeclarationTypeParameters!,
- ..._fragment.declaredTypeParameters!.builders
- ], inErrorRecovery: hasErrors);
- } else if (_clonedDeclarationTypeParameters != null) {
- return context.computeDefaultTypesForVariables(
- _clonedDeclarationTypeParameters,
- inErrorRecovery: hasErrors);
- } else {
- return context.computeDefaultTypesForVariables(
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders,
- inErrorRecovery: hasErrors);
- }
- }
-
- BuiltMemberKind get _builtMemberKind;
-
- bool get _isExtensionMember;
-
- bool get _isExtensionTypeMember;
-
- @override
- // Coverage-ignore(suite): Not run.
- void ensureTypes(
- SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy) {
- _fragment.returnType
- .build(libraryBuilder, TypeUse.fieldType, hierarchy: hierarchy);
- _thisFormal.type
- .build(libraryBuilder, TypeUse.parameterType, hierarchy: hierarchy);
- }
-
- @override
- void onInferredType(DartType type) {
- function.returnType = type;
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- void becomeNative(SourceLoader loader) {
- loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- List<FormalParameterBuilder>? get formals =>
- [_thisFormal, ...?_fragment.declaredFormals];
-
- @override
- // Coverage-ignore(suite): Not run.
- VariableDeclaration getFormalParameter(int index) =>
- _fragment.declaredFormals![index].variable!;
-
- @override
- void checkTypes(SourceLibraryBuilder libraryBuilder,
- TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
- {required bool isAbstract, required bool isExternal}) {
- List<TypeParameterBuilder>? typeParameters = _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders;
- // Coverage-ignore(suite): Not run.
- if (typeParameters != null && typeParameters.isNotEmpty) {
- libraryBuilder.checkTypeParameterDependencies(typeParameters);
- }
- libraryBuilder.checkInitializersInFormals(
- _fragment.declaredFormals, typeEnvironment,
- isAbstract: isAbstract, isExternal: isExternal);
- if (setterBuilder != null) {
- DartType getterType = function.returnType;
- DartType setterType = SourcePropertyBuilder.getSetterType(setterBuilder,
- getterExtensionTypeParameters: function.typeParameters);
- libraryBuilder.checkGetterSetterTypes(typeEnvironment,
- getterType: getterType,
- getterName: _fragment.name,
- getterFileOffset: _fragment.nameOffset,
- getterFileUri: _fragment.fileUri,
- getterNameLength: _fragment.name.length,
- setterType: setterType,
- setterName: setterBuilder.name,
- setterFileOffset: setterBuilder.fileOffset,
- setterFileUri: setterBuilder.fileUri,
- setterNameLength: setterBuilder.name.length);
- }
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- void checkVariance(
- SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
- sourceClassBuilder.checkVarianceInTypeParameters(
- typeEnvironment, _fragment.declaredTypeParameters?.builders);
- sourceClassBuilder.checkVarianceInFormals(
- typeEnvironment, _fragment.declaredFormals);
- sourceClassBuilder.checkVarianceInReturnType(
- typeEnvironment, function.returnType,
- fileOffset: _fragment.nameOffset, fileUri: _fragment.fileUri);
- }
-
- @override
- List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
- _clonedDeclarationTypeParameters != null ||
- _fragment.declaredTypeParameters != null
- ? [
- ...?_clonedDeclarationTypeParameters,
- ...?_fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders
- ]
- : null;
-
- @override
- // Coverage-ignore(suite): Not run.
- List<FormalParameterBuilder>? get formalsForTesting =>
- [_thisFormal, ...?_fragment.declaredFormals];
-}
-
-class _ExtensionInstanceGetterEncoding extends _GetterEncoding
- with _ExtensionInstanceGetterEncodingMixin {
- @override
- final GetterFragment _fragment;
-
- @override
- final List<NominalParameterBuilder>? _clonedDeclarationTypeParameters;
-
- @override
- final FormalParameterBuilder _thisFormal;
-
- _ExtensionInstanceGetterEncoding(
- this._fragment, this._clonedDeclarationTypeParameters, this._thisFormal);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionGetter;
-
- @override
- bool get _isExtensionMember => true;
-
- @override
- bool get _isExtensionTypeMember => false;
-}
-
-class _ExtensionTypeInstanceGetterEncoding extends _GetterEncoding
- with _ExtensionInstanceGetterEncodingMixin {
- @override
- final GetterFragment _fragment;
-
- @override
- final List<NominalParameterBuilder>? _clonedDeclarationTypeParameters;
-
- @override
- final FormalParameterBuilder _thisFormal;
-
- _ExtensionTypeInstanceGetterEncoding(
- this._fragment, this._clonedDeclarationTypeParameters, this._thisFormal);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeGetter;
-
- @override
- bool get _isExtensionMember => false;
-
- @override
- bool get _isExtensionTypeMember => true;
-}
-
-class _GetterFragmentBodyBuilderContext extends BodyBuilderContext {
- final GetterFragment _fragment;
-
- _GetterFragmentBodyBuilderContext(
- this._fragment,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- {required bool isDeclarationInstanceMember})
- : super(libraryBuilder, declarationBuilder,
- isDeclarationInstanceMember: isDeclarationInstanceMember);
-
- @override
- LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
- /// Initializer formals or super parameters cannot occur in getters so
- /// we don't need to create a new scope.
- return parent;
- }
-
- @override
- FunctionNode get function => _fragment._encoding.function;
-
- @override
- bool get isExternalFunction => _fragment.modifiers.isExternal;
-
- @override
- void setAsyncModifier(AsyncMarker asyncModifier) {
- assert(
- asyncModifier == _fragment.asyncModifier,
- "Unexpected change in async modifier on $_fragment from "
- "${_fragment.asyncModifier} to $asyncModifier.");
- }
-
- @override
- int get memberNameOffset => _fragment.nameOffset;
-
- @override
- int get memberNameLength => _fragment.name.length;
-
- @override
- DartType get returnTypeContext {
- final bool isReturnTypeUndeclared =
- _fragment.returnType is OmittedTypeBuilder &&
- function.returnType is DynamicType;
- return isReturnTypeUndeclared ? const UnknownType() : function.returnType;
- }
-
- @override
- TypeBuilder get returnType => _fragment.returnType;
-
- @override
- void registerFunctionBody(Statement body) {
- function.body = body..parent = function;
- }
-
- @override
- void registerSuperCall() {
- // TODO(johnniwinther): This should be set on the member built from this
- // fragment and copied to the origin if necessary.
- _fragment.builder.readTarget!.transformerFlags |=
- TransformerFlag.superCalls;
- }
-
- @override
- List<FormalParameterBuilder>? get formals => _fragment._encoding.formals;
-
- @override
- VariableDeclaration getFormalParameter(int index) =>
- _fragment._encoding.getFormalParameter(index);
-
- @override
- VariableDeclaration? getTearOffParameter(int index) => null;
-
- @override
- // Coverage-ignore(suite): Not run.
- AugmentSuperTarget? get augmentSuperTarget {
- if (_fragment.builder.isAugmentation) {
- return _fragment.builder.augmentSuperTarget;
- }
- return null;
- }
+ VariableDeclaration? get thisVariable => _fragment.declaration.thisVariable;
}
diff --git a/pkg/front_end/lib/src/fragment/getter/body_builder_context.dart b/pkg/front_end/lib/src/fragment/getter/body_builder_context.dart
new file mode 100644
index 0000000..a1ed65f
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/getter/body_builder_context.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/transformations/flags.dart';
+
+import '../../base/local_scope.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/body_builder_context.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_member_builder.dart';
+import '../../source/source_property_builder.dart';
+import '../../type_inference/type_schema.dart';
+import 'declaration.dart';
+
+class GetterFragmentBodyBuilderContext extends BodyBuilderContext {
+ final SourcePropertyBuilder _builder;
+ final GetterDeclaration _declaration;
+
+ GetterFragmentBodyBuilderContext(
+ this._builder,
+ this._declaration,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ {required bool isDeclarationInstanceMember})
+ : super(libraryBuilder, declarationBuilder,
+ isDeclarationInstanceMember: isDeclarationInstanceMember);
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ AugmentSuperTarget? get augmentSuperTarget {
+ if (_builder.isAugmentation) {
+ return _builder.augmentSuperTarget;
+ }
+ return null;
+ }
+
+ @override
+ List<FormalParameterBuilder>? get formals => _declaration.formals;
+
+ @override
+ FunctionNode get function => _declaration.function;
+
+ @override
+ bool get isExternalFunction => _declaration.isExternal;
+
+ @override
+ int get memberNameLength => _declaration.name.length;
+
+ @override
+ int get memberNameOffset => _declaration.nameOffset;
+
+ @override
+ TypeBuilder get returnType => _declaration.returnType;
+
+ @override
+ DartType get returnTypeContext {
+ final bool isReturnTypeUndeclared =
+ _declaration.returnType is OmittedTypeBuilder &&
+ function.returnType is DynamicType;
+ return isReturnTypeUndeclared ? const UnknownType() : function.returnType;
+ }
+
+ @override
+ LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
+ /// Initializer formals or super parameters cannot occur in getters so
+ /// we don't need to create a new scope.
+ return parent;
+ }
+
+ @override
+ VariableDeclaration getFormalParameter(int index) =>
+ _declaration.getFormalParameter(index);
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) => null;
+
+ @override
+ void registerFunctionBody(Statement body) {
+ function.body = body..parent = function;
+ }
+
+ @override
+ void registerSuperCall() {
+ // TODO(johnniwinther): This should be set on the member built from this
+ // fragment and copied to the origin if necessary.
+ _builder.readTarget!.transformerFlags |= TransformerFlag.superCalls;
+ }
+
+ @override
+ void setAsyncModifier(AsyncMarker asyncModifier) {
+ assert(
+ asyncModifier == _declaration.asyncModifier,
+ "Unexpected change in async modifier on $_declaration from "
+ "${_declaration.asyncModifier} to $asyncModifier.");
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/getter/declaration.dart b/pkg/front_end/lib/src/fragment/getter/declaration.dart
new file mode 100644
index 0000000..e83c107
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/getter/declaration.dart
@@ -0,0 +1,264 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/type_environment.dart';
+
+import '../../base/local_scope.dart';
+import '../../base/messages.dart';
+import '../../base/scope.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/metadata_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/body_builder_context.dart';
+import '../../kernel/hierarchy/class_member.dart';
+import '../../kernel/hierarchy/members_builder.dart';
+import '../../kernel/type_algorithms.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_loader.dart';
+import '../../source/source_member_builder.dart';
+import '../../source/source_property_builder.dart';
+import '../fragment.dart';
+import 'body_builder_context.dart';
+import 'encoding.dart';
+
+abstract class GetterDeclaration {
+ AsyncMarker get asyncModifier;
+
+ Uri get fileUri;
+
+ List<FormalParameterBuilder>? get formals;
+
+ FunctionNode get function;
+
+ bool get isAbstract;
+
+ bool get isExternal;
+
+ List<MetadataBuilder>? get metadata;
+
+ String get name;
+
+ int get nameOffset;
+
+ Procedure get readTarget;
+
+ TypeBuilder get returnType;
+
+ List<TypeParameter>? get thisTypeParameters;
+
+ VariableDeclaration? get thisVariable;
+
+ List<NominalParameterBuilder>? get typeParametersForTesting;
+
+ void becomeNative(SourceLoader loader);
+
+ void buildOutlineExpressions(
+ {required ClassHierarchy classHierarchy,
+ required SourceLibraryBuilder libraryBuilder,
+ required DeclarationBuilder? declarationBuilder,
+ required SourcePropertyBuilder propertyBuilder,
+ required Annotatable annotatable,
+ required bool isClassInstanceMember,
+ required bool createFileUriExpression});
+
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required List<TypeParameter>? classTypeParameters});
+
+ void checkTypes(SourceLibraryBuilder libraryBuilder,
+ TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
+ {required bool isAbstract, required bool isExternal});
+
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
+
+ int computeDefaultTypes(ComputeDefaultTypeContext context);
+
+ BodyBuilderContext createBodyBuilderContext(
+ SourcePropertyBuilder propertyBuilder);
+
+ void createEncoding(
+ ProblemReporting problemReporting,
+ SourcePropertyBuilder builder,
+ PropertyEncodingStrategy encodingStrategy,
+ List<NominalParameterBuilder> unboundNominalParameters);
+
+ LocalScope createFormalParameterScope(LookupScope typeParameterScope);
+
+ void ensureTypes(
+ {required SourceLibraryBuilder libraryBuilder,
+ required DeclarationBuilder? declarationBuilder,
+ required ClassMembersBuilder membersBuilder,
+ required Set<ClassMember>? getterOverrideDependencies});
+
+ Iterable<Reference> getExportedMemberReferences(GetterReference references);
+
+ VariableDeclaration getFormalParameter(int index);
+}
+
+class GetterDeclarationImpl implements GetterDeclaration {
+ final GetterFragment _fragment;
+ late final GetterEncoding _encoding;
+
+ GetterDeclarationImpl(this._fragment) {
+ _fragment.declaration = this;
+ }
+
+ @override
+ AsyncMarker get asyncModifier => _fragment.asyncModifier;
+
+ @override
+ Uri get fileUri => _fragment.fileUri;
+
+ @override
+ List<FormalParameterBuilder>? get formals => _encoding.formals;
+
+ @override
+ FunctionNode get function => _encoding.function;
+
+ @override
+ bool get isAbstract => _fragment.modifiers.isAbstract;
+
+ @override
+ bool get isExternal => _fragment.modifiers.isExternal;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ List<MetadataBuilder>? get metadata => _fragment.metadata;
+
+ @override
+ String get name => _fragment.name;
+
+ @override
+ int get nameOffset => _fragment.nameOffset;
+
+ @override
+ Procedure get readTarget => _encoding.readTarget;
+
+ @override
+ TypeBuilder get returnType => _fragment.returnType;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters => _encoding.thisTypeParameters;
+
+ @override
+ VariableDeclaration? get thisVariable => _encoding.thisVariable;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ List<NominalParameterBuilder>? get typeParametersForTesting =>
+ _encoding.clonedAndDeclaredTypeParameters;
+
+ @override
+ void becomeNative(SourceLoader loader) {
+ _encoding.becomeNative(loader);
+ }
+
+ @override
+ void buildOutlineExpressions(
+ {required ClassHierarchy classHierarchy,
+ required SourceLibraryBuilder libraryBuilder,
+ required DeclarationBuilder? declarationBuilder,
+ required SourcePropertyBuilder propertyBuilder,
+ required Annotatable annotatable,
+ required bool isClassInstanceMember,
+ required bool createFileUriExpression}) {
+ _encoding.buildOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ declarationBuilder,
+ createBodyBuilderContext(propertyBuilder),
+ annotatable,
+ isClassInstanceMember: isClassInstanceMember,
+ createFileUriExpression: createFileUriExpression);
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required List<TypeParameter>? classTypeParameters}) {
+ _encoding.buildOutlineNode(libraryBuilder, nameScheme, f, references,
+ isAbstractOrExternal:
+ _fragment.modifiers.isAbstract || _fragment.modifiers.isExternal,
+ classTypeParameters: classTypeParameters);
+ }
+
+ @override
+ void checkTypes(SourceLibraryBuilder libraryBuilder,
+ TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
+ {required bool isAbstract, required bool isExternal}) {
+ _encoding.checkTypes(libraryBuilder, typeEnvironment, setterBuilder,
+ isAbstract: isAbstract, isExternal: isExternal);
+ }
+
+ @override
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
+ _encoding.checkVariance(sourceClassBuilder, typeEnvironment);
+ }
+
+ @override
+ int computeDefaultTypes(ComputeDefaultTypeContext context) {
+ return _encoding.computeDefaultTypes(context);
+ }
+
+ @override
+ BodyBuilderContext createBodyBuilderContext(
+ SourcePropertyBuilder propertyBuilder) {
+ return new GetterFragmentBodyBuilderContext(propertyBuilder, this,
+ propertyBuilder.libraryBuilder, propertyBuilder.declarationBuilder,
+ isDeclarationInstanceMember:
+ propertyBuilder.isDeclarationInstanceMember);
+ }
+
+ @override
+ void createEncoding(
+ ProblemReporting problemReporting,
+ SourcePropertyBuilder builder,
+ PropertyEncodingStrategy encodingStrategy,
+ List<NominalParameterBuilder> unboundNominalParameters) {
+ _encoding = encodingStrategy.createGetterEncoding(
+ builder, _fragment, unboundNominalParameters);
+ _fragment.typeParameterNameSpace.addTypeParameters(
+ problemReporting, _encoding.clonedAndDeclaredTypeParameters,
+ ownerName: _fragment.name, allowNameConflict: true);
+ returnType.registerInferredTypeListener(_encoding);
+ }
+
+ @override
+ LocalScope createFormalParameterScope(LookupScope typeParameterScope) {
+ return _encoding.createFormalParameterScope(typeParameterScope);
+ }
+
+ @override
+ void ensureTypes(
+ {required SourceLibraryBuilder libraryBuilder,
+ required DeclarationBuilder? declarationBuilder,
+ required ClassMembersBuilder membersBuilder,
+ required Set<ClassMember>? getterOverrideDependencies}) {
+ if (getterOverrideDependencies != null) {
+ membersBuilder.inferGetterType(declarationBuilder as SourceClassBuilder,
+ _fragment.returnType, getterOverrideDependencies,
+ name: _fragment.name,
+ fileUri: _fragment.fileUri,
+ nameOffset: _fragment.nameOffset,
+ nameLength: _fragment.name.length);
+ }
+ _encoding.ensureTypes(libraryBuilder, membersBuilder.hierarchyBuilder);
+ }
+
+ @override
+ Iterable<Reference> getExportedMemberReferences(GetterReference references) =>
+ [references.getterReference];
+
+ @override
+ VariableDeclaration getFormalParameter(int index) {
+ return _encoding.getFormalParameter(index);
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/getter/encoding.dart b/pkg/front_end/lib/src/fragment/getter/encoding.dart
new file mode 100644
index 0000000..68afdf5
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/getter/encoding.dart
@@ -0,0 +1,632 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/type_environment.dart';
+
+import '../../base/local_scope.dart';
+import '../../base/scope.dart';
+import '../../builder/builder.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/omitted_type_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/body_builder_context.dart';
+import '../../kernel/type_algorithms.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_function_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_loader.dart';
+import '../../source/source_member_builder.dart';
+import '../../source/source_property_builder.dart';
+import '../fragment.dart';
+
+class ExtensionInstanceGetterEncoding extends GetterEncoding
+ with _ExtensionInstanceGetterEncodingMixin {
+ @override
+ final GetterFragment _fragment;
+
+ @override
+ final List<NominalParameterBuilder>? _clonedDeclarationTypeParameters;
+
+ @override
+ final FormalParameterBuilder _thisFormal;
+
+ ExtensionInstanceGetterEncoding(
+ this._fragment, this._clonedDeclarationTypeParameters, this._thisFormal);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionGetter;
+
+ @override
+ bool get _isExtensionMember => true;
+
+ @override
+ bool get _isExtensionTypeMember => false;
+}
+
+class ExtensionStaticGetterEncoding extends GetterEncoding
+ with _DirectGetterEncodingMixin {
+ @override
+ final GetterFragment _fragment;
+
+ ExtensionStaticGetterEncoding(this._fragment);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionGetter;
+
+ @override
+ bool get _isExtensionMember => true;
+
+ @override
+ bool get _isExtensionTypeMember => false;
+}
+
+class ExtensionTypeInstanceGetterEncoding extends GetterEncoding
+ with _ExtensionInstanceGetterEncodingMixin {
+ @override
+ final GetterFragment _fragment;
+
+ @override
+ final List<NominalParameterBuilder>? _clonedDeclarationTypeParameters;
+
+ @override
+ final FormalParameterBuilder _thisFormal;
+
+ ExtensionTypeInstanceGetterEncoding(
+ this._fragment, this._clonedDeclarationTypeParameters, this._thisFormal);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeGetter;
+
+ @override
+ bool get _isExtensionMember => false;
+
+ @override
+ bool get _isExtensionTypeMember => true;
+}
+
+class ExtensionTypeStaticGetterEncoding extends GetterEncoding
+ with _DirectGetterEncodingMixin {
+ @override
+ final GetterFragment _fragment;
+
+ ExtensionTypeStaticGetterEncoding(this._fragment);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeGetter;
+
+ @override
+ bool get _isExtensionMember => false;
+
+ @override
+ bool get _isExtensionTypeMember => true;
+}
+
+sealed class GetterEncoding implements InferredTypeListener {
+ List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters;
+ List<FormalParameterBuilder>? get formals;
+ FunctionNode get function;
+
+ Procedure get readTarget;
+
+ List<TypeParameter>? get thisTypeParameters;
+
+ VariableDeclaration? get thisVariable;
+
+ void becomeNative(SourceLoader loader);
+
+ void buildOutlineExpressions(
+ ClassHierarchy classHierarchy,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ BodyBuilderContext bodyBuilderContext,
+ Annotatable annotatable,
+ {required bool isClassInstanceMember,
+ required bool createFileUriExpression});
+
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters});
+
+ void checkTypes(SourceLibraryBuilder libraryBuilder,
+ TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
+ {required bool isAbstract, required bool isExternal});
+
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
+
+ int computeDefaultTypes(ComputeDefaultTypeContext context);
+
+ LocalScope createFormalParameterScope(LookupScope typeParameterScope);
+
+ void ensureTypes(
+ SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy);
+
+ VariableDeclaration getFormalParameter(int index);
+}
+
+class RegularGetterEncoding extends GetterEncoding
+ with _DirectGetterEncodingMixin {
+ @override
+ final GetterFragment _fragment;
+
+ RegularGetterEncoding(this._fragment);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.Method;
+
+ @override
+ bool get _isExtensionMember => false;
+
+ @override
+ bool get _isExtensionTypeMember => false;
+}
+
+mixin _DirectGetterEncodingMixin implements GetterEncoding {
+ Procedure? _procedure;
+
+ @override
+ List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders;
+
+ @override
+ List<FormalParameterBuilder>? get formals => _fragment.declaredFormals;
+
+ @override
+ FunctionNode get function => _procedure!.function;
+
+ @override
+ Procedure get readTarget => _procedure!;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters => null;
+
+ @override
+ VariableDeclaration? get thisVariable => null;
+
+ BuiltMemberKind get _builtMemberKind;
+
+ GetterFragment get _fragment;
+
+ bool get _isExtensionMember;
+
+ bool get _isExtensionTypeMember;
+
+ @override
+ void becomeNative(SourceLoader loader) {
+ loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
+ }
+
+ @override
+ void buildOutlineExpressions(
+ ClassHierarchy classHierarchy,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ BodyBuilderContext bodyBuilderContext,
+ Annotatable annotatable,
+ {required bool isClassInstanceMember,
+ required bool createFileUriExpression}) {
+ buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
+ bodyBuilderContext, annotatable, _fragment.metadata,
+ fileUri: _fragment.fileUri,
+ createFileUriExpression: createFileUriExpression);
+ buildTypeParametersForOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ bodyBuilderContext,
+ _fragment.typeParameterScope,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ buildFormalsForOutlineExpressions(
+ libraryBuilder, declarationBuilder, _fragment.declaredFormals,
+ scope: _fragment.typeParameterScope,
+ isClassInstanceMember: isClassInstanceMember);
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required bool isAbstractOrExternal,
+ List<TypeParameter>? classTypeParameters}) {
+ FunctionNode function = new FunctionNode(
+ isAbstractOrExternal ? null : new EmptyStatement(),
+ asyncMarker: _fragment.asyncModifier)
+ ..fileOffset = _fragment.formalsOffset
+ ..fileEndOffset = _fragment.endOffset;
+ buildTypeParametersAndFormals(
+ libraryBuilder,
+ function,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders,
+ _fragment.declaredFormals,
+ classTypeParameters: classTypeParameters,
+ supportsTypeParameters: true);
+ if (_fragment.returnType is! InferableTypeBuilder) {
+ function.returnType =
+ _fragment.returnType.build(libraryBuilder, TypeUse.returnType);
+ }
+
+ MemberName memberName =
+ nameScheme.getProcedureMemberName(ProcedureKind.Getter, _fragment.name);
+ Procedure procedure = _procedure = new Procedure(
+ memberName.name, ProcedureKind.Getter, function,
+ reference: references.getterReference, fileUri: _fragment.fileUri)
+ ..fileStartOffset = _fragment.startOffset
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset
+ ..isAbstract = _fragment.modifiers.isAbstract
+ ..isExternal = _fragment.modifiers.isExternal
+ ..isConst = _fragment.modifiers.isConst
+ ..isStatic = _fragment.modifiers.isStatic
+ ..isExtensionMember = _isExtensionMember
+ ..isExtensionTypeMember = _isExtensionTypeMember;
+ memberName.attachMember(procedure);
+
+ f(kind: _builtMemberKind, member: procedure);
+ }
+
+ @override
+ void checkTypes(SourceLibraryBuilder libraryBuilder,
+ TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
+ {required bool isAbstract, required bool isExternal}) {
+ List<TypeParameterBuilder>? typeParameters = _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders;
+ // Coverage-ignore(suite): Not run.
+ if (typeParameters != null && typeParameters.isNotEmpty) {
+ libraryBuilder.checkTypeParameterDependencies(typeParameters);
+ }
+ libraryBuilder.checkInitializersInFormals(
+ _fragment.declaredFormals, typeEnvironment,
+ isAbstract: isAbstract, isExternal: isExternal);
+ if (setterBuilder != null) {
+ DartType getterType = function.returnType;
+ DartType setterType = SourcePropertyBuilder.getSetterType(setterBuilder,
+ getterExtensionTypeParameters: null);
+ libraryBuilder.checkGetterSetterTypes(typeEnvironment,
+ getterType: getterType,
+ getterName: _fragment.name,
+ getterFileOffset: _fragment.nameOffset,
+ getterFileUri: _fragment.fileUri,
+ getterNameLength: _fragment.name.length,
+ setterType: setterType,
+ setterName: setterBuilder.name,
+ setterFileOffset: setterBuilder.fileOffset,
+ setterFileUri: setterBuilder.fileUri,
+ setterNameLength: setterBuilder.name.length);
+ }
+ }
+
+ @override
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
+ sourceClassBuilder.checkVarianceInTypeParameters(
+ typeEnvironment,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ sourceClassBuilder.checkVarianceInFormals(
+ typeEnvironment, _fragment.declaredFormals);
+ sourceClassBuilder.checkVarianceInReturnType(
+ typeEnvironment, function.returnType,
+ fileOffset: _fragment.nameOffset, fileUri: _fragment.fileUri);
+ }
+
+ @override
+ int computeDefaultTypes(ComputeDefaultTypeContext context) {
+ bool hasErrors = context.reportSimplicityIssuesForTypeParameters(_fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
+ if (_fragment.returnType is! OmittedTypeBuilder) {
+ hasErrors |=
+ context.reportInboundReferenceIssuesForType(_fragment.returnType);
+ context.recursivelyReportGenericFunctionTypesAsBoundsForType(
+ _fragment.returnType);
+ }
+ return context.computeDefaultTypesForVariables(
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders,
+ inErrorRecovery: hasErrors);
+ }
+
+ @override
+ LocalScope createFormalParameterScope(LookupScope typeParameterScope) {
+ return new FormalParameterScope(parent: typeParameterScope);
+ }
+
+ @override
+ void ensureTypes(
+ SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy) {
+ _fragment.returnType
+ .build(libraryBuilder, TypeUse.returnType, hierarchy: hierarchy);
+ }
+
+ @override
+ VariableDeclaration getFormalParameter(int index) =>
+ _fragment.declaredFormals![index].variable!;
+
+ @override
+ void onInferredType(DartType type) {
+ function.returnType = type;
+ }
+}
+
+mixin _ExtensionInstanceGetterEncodingMixin implements GetterEncoding {
+ Procedure? _procedure;
+
+ @override
+ List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
+ _clonedDeclarationTypeParameters != null ||
+ _fragment.declaredTypeParameters != null
+ ? [
+ ...?_clonedDeclarationTypeParameters,
+ ...?_fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders
+ ]
+ : null;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ List<FormalParameterBuilder>? get formals =>
+ [_thisFormal, ...?_fragment.declaredFormals];
+
+ @override
+ FunctionNode get function => _procedure!.function;
+
+ @override
+ Procedure get readTarget => _procedure!;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters =>
+ _clonedDeclarationTypeParameters != null ? function.typeParameters : null;
+
+ @override
+ VariableDeclaration? get thisVariable => _thisFormal.variable!;
+
+ BuiltMemberKind get _builtMemberKind;
+
+ List<NominalParameterBuilder>? get _clonedDeclarationTypeParameters;
+
+ GetterFragment get _fragment;
+
+ bool get _isExtensionMember;
+
+ bool get _isExtensionTypeMember;
+
+ FormalParameterBuilder get _thisFormal;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void becomeNative(SourceLoader loader) {
+ loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
+ }
+
+ @override
+ void buildOutlineExpressions(
+ ClassHierarchy classHierarchy,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ BodyBuilderContext bodyBuilderContext,
+ Annotatable annotatable,
+ {required bool isClassInstanceMember,
+ required bool createFileUriExpression}) {
+ buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
+ bodyBuilderContext, annotatable, _fragment.metadata,
+ fileUri: _fragment.fileUri,
+ createFileUriExpression: createFileUriExpression);
+
+ buildTypeParametersForOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ bodyBuilderContext,
+ _fragment.typeParameterScope,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ buildFormalsForOutlineExpressions(
+ libraryBuilder, declarationBuilder, _fragment.declaredFormals,
+ scope: _fragment.typeParameterScope,
+ isClassInstanceMember: isClassInstanceMember);
+
+ buildTypeParametersForOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ bodyBuilderContext,
+ _fragment.typeParameterScope,
+ _clonedDeclarationTypeParameters);
+ buildFormalForOutlineExpressions(
+ libraryBuilder, declarationBuilder, _thisFormal,
+ scope: _fragment.typeParameterScope,
+ isClassInstanceMember: isClassInstanceMember);
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters}) {
+ List<TypeParameter>? typeParameters;
+ if (_clonedDeclarationTypeParameters != null) {
+ typeParameters = [];
+ // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both required
+ // and unnecessary.
+ // ignore: unnecessary_non_null_assertion
+ for (NominalParameterBuilder t in _clonedDeclarationTypeParameters!) {
+ typeParameters.add(t.parameter);
+ }
+ }
+ FunctionNode function = new FunctionNode(
+ isAbstractOrExternal ? null : new EmptyStatement(),
+ typeParameters: typeParameters,
+ positionalParameters: [_thisFormal.build(libraryBuilder)],
+ asyncMarker: _fragment.asyncModifier)
+ ..fileOffset = _fragment.formalsOffset
+ ..fileEndOffset = _fragment.endOffset;
+ buildTypeParametersAndFormals(
+ libraryBuilder,
+ function,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders,
+ _fragment.declaredFormals,
+ classTypeParameters: classTypeParameters,
+ supportsTypeParameters: true);
+ if (_fragment.returnType is! InferableTypeBuilder) {
+ function.returnType =
+ _fragment.returnType.build(libraryBuilder, TypeUse.returnType);
+ }
+
+ MemberName memberName =
+ nameScheme.getProcedureMemberName(ProcedureKind.Getter, _fragment.name);
+ Procedure procedure = _procedure = new Procedure(
+ memberName.name, ProcedureKind.Method, function,
+ reference: references.getterReference, fileUri: _fragment.fileUri)
+ ..fileStartOffset = _fragment.startOffset
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset
+ ..isAbstract = _fragment.modifiers.isAbstract
+ ..isExternal = _fragment.modifiers.isExternal
+ ..isConst = _fragment.modifiers.isConst
+ ..isStatic = true
+ ..isExtensionMember = _isExtensionMember
+ ..isExtensionTypeMember = _isExtensionTypeMember;
+ memberName.attachMember(procedure);
+
+ f(kind: _builtMemberKind, member: procedure);
+ }
+
+ @override
+ void checkTypes(SourceLibraryBuilder libraryBuilder,
+ TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
+ {required bool isAbstract, required bool isExternal}) {
+ List<TypeParameterBuilder>? typeParameters = _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders;
+ // Coverage-ignore(suite): Not run.
+ if (typeParameters != null && typeParameters.isNotEmpty) {
+ libraryBuilder.checkTypeParameterDependencies(typeParameters);
+ }
+ libraryBuilder.checkInitializersInFormals(
+ _fragment.declaredFormals, typeEnvironment,
+ isAbstract: isAbstract, isExternal: isExternal);
+ if (setterBuilder != null) {
+ DartType getterType = function.returnType;
+ DartType setterType = SourcePropertyBuilder.getSetterType(setterBuilder,
+ getterExtensionTypeParameters: function.typeParameters);
+ libraryBuilder.checkGetterSetterTypes(typeEnvironment,
+ getterType: getterType,
+ getterName: _fragment.name,
+ getterFileOffset: _fragment.nameOffset,
+ getterFileUri: _fragment.fileUri,
+ getterNameLength: _fragment.name.length,
+ setterType: setterType,
+ setterName: setterBuilder.name,
+ setterFileOffset: setterBuilder.fileOffset,
+ setterFileUri: setterBuilder.fileUri,
+ setterNameLength: setterBuilder.name.length);
+ }
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
+ sourceClassBuilder.checkVarianceInTypeParameters(
+ typeEnvironment, _fragment.declaredTypeParameters?.builders);
+ sourceClassBuilder.checkVarianceInFormals(
+ typeEnvironment, _fragment.declaredFormals);
+ sourceClassBuilder.checkVarianceInReturnType(
+ typeEnvironment, function.returnType,
+ fileOffset: _fragment.nameOffset, fileUri: _fragment.fileUri);
+ }
+
+ @override
+ int computeDefaultTypes(ComputeDefaultTypeContext context) {
+ bool hasErrors = context.reportSimplicityIssuesForTypeParameters(_fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
+ if (_fragment.returnType is! OmittedTypeBuilder) {
+ hasErrors |=
+ context.reportInboundReferenceIssuesForType(_fragment.returnType);
+ context.recursivelyReportGenericFunctionTypesAsBoundsForType(
+ _fragment.returnType);
+ }
+ if (_clonedDeclarationTypeParameters != null &&
+ _fragment.declaredTypeParameters != null) {
+ // Coverage-ignore-block(suite): Not run.
+ // We need to compute all default types together since they might be
+ // interdependent.
+ return context.computeDefaultTypesForVariables([
+ // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both
+ // required and unnecessary.
+ // ignore: unnecessary_non_null_assertion
+ ..._clonedDeclarationTypeParameters!,
+ ..._fragment.declaredTypeParameters!.builders
+ ], inErrorRecovery: hasErrors);
+ } else if (_clonedDeclarationTypeParameters != null) {
+ return context.computeDefaultTypesForVariables(
+ _clonedDeclarationTypeParameters,
+ inErrorRecovery: hasErrors);
+ } else {
+ return context.computeDefaultTypesForVariables(
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders,
+ inErrorRecovery: hasErrors);
+ }
+ }
+
+ @override
+ LocalScope createFormalParameterScope(LookupScope typeParameterScope) {
+ Map<String, Builder> local = <String, Builder>{};
+ assert(!_thisFormal.isWildcard);
+ local[_thisFormal.name] = _thisFormal;
+ return new FormalParameterScope(local: local, parent: typeParameterScope);
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void ensureTypes(
+ SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy) {
+ _fragment.returnType
+ .build(libraryBuilder, TypeUse.fieldType, hierarchy: hierarchy);
+ _thisFormal.type
+ .build(libraryBuilder, TypeUse.parameterType, hierarchy: hierarchy);
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ VariableDeclaration getFormalParameter(int index) =>
+ _fragment.declaredFormals![index].variable!;
+
+ @override
+ void onInferredType(DartType type) {
+ function.returnType = type;
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/method.dart b/pkg/front_end/lib/src/fragment/method.dart
index 7ee30ed..a3208b9 100644
--- a/pkg/front_end/lib/src/fragment/method.dart
+++ b/pkg/front_end/lib/src/fragment/method.dart
@@ -468,21 +468,17 @@
Annotatable annotatable,
{required bool isClassInstanceMember,
required bool createFileUriExpression}) {
- _buildMetadataForOutlineExpressions(
- libraryBuilder,
- _fragment.enclosingScope,
- bodyBuilderContext,
- annotatable,
- _fragment.metadata,
+ buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
+ bodyBuilderContext, annotatable, _fragment.metadata,
fileUri: _fragment.fileUri,
createFileUriExpression: createFileUriExpression);
- _buildTypeParametersForOutlineExpressions(
+ buildTypeParametersForOutlineExpressions(
classHierarchy,
libraryBuilder,
bodyBuilderContext,
_fragment.typeParameterScope,
_fragment.declaredTypeParameters);
- _buildFormalsForOutlineExpressions(
+ buildFormalsForOutlineExpressions(
libraryBuilder, declarationBuilder, _fragment.declaredFormals,
scope: _fragment.typeParameterScope,
isClassInstanceMember: isClassInstanceMember);
@@ -965,33 +961,29 @@
Annotatable annotatable,
{required bool isClassInstanceMember,
required bool createFileUriExpression}) {
- _buildMetadataForOutlineExpressions(
- libraryBuilder,
- _fragment.enclosingScope,
- bodyBuilderContext,
- annotatable,
- _fragment.metadata,
+ buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
+ bodyBuilderContext, annotatable, _fragment.metadata,
fileUri: _fragment.fileUri,
createFileUriExpression: createFileUriExpression);
- _buildTypeParametersForOutlineExpressions(
+ buildTypeParametersForOutlineExpressions(
classHierarchy,
libraryBuilder,
bodyBuilderContext,
_fragment.typeParameterScope,
_fragment.declaredTypeParameters);
- _buildFormalsForOutlineExpressions(
+ buildFormalsForOutlineExpressions(
libraryBuilder, declarationBuilder, _fragment.declaredFormals,
scope: _fragment.typeParameterScope,
isClassInstanceMember: isClassInstanceMember);
- _buildTypeParametersForOutlineExpressions(
+ buildTypeParametersForOutlineExpressions(
classHierarchy,
libraryBuilder,
bodyBuilderContext,
_fragment.typeParameterScope,
_clonedDeclarationTypeParameters);
- _buildFormalForOutlineExpressions(
+ buildFormalForOutlineExpressions(
libraryBuilder, declarationBuilder, _thisFormal,
scope: _fragment.typeParameterScope,
isClassInstanceMember: isClassInstanceMember);
diff --git a/pkg/front_end/lib/src/fragment/setter.dart b/pkg/front_end/lib/src/fragment/setter.dart
index 85a1037..d9f2aeb 100644
--- a/pkg/front_end/lib/src/fragment/setter.dart
+++ b/pkg/front_end/lib/src/fragment/setter.dart
@@ -58,8 +58,7 @@
final LibraryFragment enclosingCompilationUnit;
SourcePropertyBuilder? _builder;
-
- late final _SetterEncoding _encoding;
+ SetterDeclaration? _declaration;
SetterFragment({
required this.name,
@@ -89,109 +88,37 @@
return _builder!;
}
- void setBuilder(
- ProblemReporting problemReporting,
- SourcePropertyBuilder value,
- PropertyEncodingStrategy encodingStrategy,
- List<NominalParameterBuilder> unboundNominalParameters) {
+ void set builder(SourcePropertyBuilder value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
- _encoding = encodingStrategy.createSetterEncoding(
- value, this, unboundNominalParameters);
- typeParameterNameSpace.addTypeParameters(
- problemReporting, _encoding.clonedAndDeclaredTypeParameters,
- ownerName: name, allowNameConflict: true);
}
- void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
- {required List<TypeParameter>? classTypeParameters}) {
- _encoding.buildOutlineNode(libraryBuilder, nameScheme, f, references,
- isAbstractOrExternal: modifiers.isAbstract || modifiers.isExternal,
- classTypeParameters: classTypeParameters);
+ SetterDeclaration get declaration {
+ assert(
+ _declaration != null, "Declaration has not been computed for $this.");
+ return _declaration!;
}
- void buildOutlineExpressions(
- ClassHierarchy classHierarchy,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- Annotatable annotatable,
- {required bool isClassInstanceMember,
- required bool createFileUriExpression}) {
- _encoding.buildOutlineExpressions(classHierarchy, libraryBuilder,
- declarationBuilder, createBodyBuilderContext(), annotatable,
- isClassInstanceMember: isClassInstanceMember,
- createFileUriExpression: createFileUriExpression);
+ void set declaration(SetterDeclaration value) {
+ assert(_declaration == null,
+ "Declaration has already been computed for $this.");
+ _declaration = value;
}
- Iterable<Reference> getExportedMemberReferences(SetterReference references) =>
- [references.setterReference];
-
- void ensureTypes(ClassMembersBuilder membersBuilder,
- Set<ClassMember>? setterOverrideDependencies) {
- if (setterOverrideDependencies != null) {
- membersBuilder.inferSetterType(
- builder.declarationBuilder as SourceClassBuilder,
- declaredFormals,
- setterOverrideDependencies,
- name: name,
- fileUri: fileUri,
- nameOffset: nameOffset,
- nameLength: name.length);
- }
- _encoding.ensureTypes(
- builder.libraryBuilder, membersBuilder.hierarchyBuilder);
- }
-
- void checkTypes(
- SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
- {required bool isAbstract, required bool isExternal}) {
- _encoding.checkTypes(libraryBuilder, typeEnvironment,
- isAbstract: isAbstract, isExternal: isExternal);
- }
-
- void checkVariance(
- SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
- _encoding.checkVariance(sourceClassBuilder, typeEnvironment);
- }
-
- int computeDefaultTypes(ComputeDefaultTypeContext context) {
- return _encoding.computeDefaultTypes(context);
- }
-
- Procedure get writeTarget => _encoding.writeTarget;
-
- // Coverage-ignore(suite): Not run.
- List<NominalParameterBuilder>? get typeParametersForTesting =>
- _encoding.clonedAndDeclaredTypeParameters;
-
- // Coverage-ignore(suite): Not run.
- List<FormalParameterBuilder>? get formalsForTesting =>
- _encoding.formalsForTesting;
-
@override
FunctionBodyBuildingContext createFunctionBodyBuildingContext() {
- return new _SetterBodyBuildingContext(this);
- }
-
- BodyBuilderContext createBodyBuilderContext() {
- return new _SetterFragmentBodyBuilderContext(
- this, builder.libraryBuilder, builder.declarationBuilder,
- isDeclarationInstanceMember: builder.isDeclarationInstanceMember);
- }
-
- void becomeNative(SourceLoader loader) {
- _encoding.becomeNative(loader);
+ return new _SetterFunctionBodyBuildingContext(this);
}
@override
String toString() => '$runtimeType($name,$fileUri,$nameOffset)';
}
-class _SetterBodyBuildingContext implements FunctionBodyBuildingContext {
+class _SetterFunctionBodyBuildingContext
+ implements FunctionBodyBuildingContext {
SetterFragment _fragment;
- _SetterBodyBuildingContext(this._fragment);
+ _SetterFunctionBodyBuildingContext(this._fragment);
@override
MemberKind get memberKind => _fragment.isTopLevel
@@ -205,7 +132,7 @@
@override
LocalScope computeFormalParameterScope(LookupScope typeParameterScope) {
- return _fragment._encoding.createFormalParameterScope(typeParameterScope);
+ return _fragment.declaration.createFormalParameterScope(typeParameterScope);
}
@override
@@ -215,7 +142,7 @@
@override
BodyBuilderContext createBodyBuilderContext() {
- return _fragment.createBodyBuilderContext();
+ return _fragment.declaration.createBodyBuilderContext(_fragment.builder);
}
@override
@@ -227,740 +154,8 @@
@override
List<TypeParameter>? get thisTypeParameters =>
- _fragment._encoding.thisTypeParameters;
+ _fragment.declaration.thisTypeParameters;
@override
- VariableDeclaration? get thisVariable => _fragment._encoding.thisVariable;
-}
-
-sealed class _SetterEncoding {
- List<TypeParameter>? get thisTypeParameters;
- VariableDeclaration? get thisVariable;
- FunctionNode get function;
- Procedure get writeTarget;
-
- void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
- {required bool isAbstractOrExternal,
- required List<TypeParameter>? classTypeParameters});
-
- void buildOutlineExpressions(
- ClassHierarchy classHierarchy,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- BodyBuilderContext bodyBuilderContext,
- Annotatable annotatable,
- {required bool isClassInstanceMember,
- required bool createFileUriExpression});
-
- LocalScope createFormalParameterScope(LookupScope typeParameterScope);
-
- int computeDefaultTypes(ComputeDefaultTypeContext context);
-
- void ensureTypes(
- SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy);
-
- void becomeNative(SourceLoader loader);
-
- List<FormalParameterBuilder>? get formals;
-
- VariableDeclaration getFormalParameter(int index);
-
- void checkTypes(
- SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
- {required bool isAbstract, required bool isExternal});
-
- void checkVariance(
- SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
-
- List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters;
-
- List<FormalParameterBuilder>? get formalsForTesting;
-}
-
-mixin _DirectSetterEncodingMixin implements _SetterEncoding {
- SetterFragment get _fragment;
-
- Procedure? _procedure;
-
- @override
- VariableDeclaration? get thisVariable => null;
-
- @override
- List<TypeParameter>? get thisTypeParameters => null;
-
- @override
- LocalScope createFormalParameterScope(LookupScope parent) {
- Map<String, Builder> local = <String, Builder>{};
- List<FormalParameterBuilder>? formals = _fragment.declaredFormals;
- if (formals != null) {
- for (FormalParameterBuilder formal in formals) {
- if (formal.isWildcard) {
- continue;
- }
- local[formal.name] = formal;
- }
- }
- return new FormalParameterScope(local: local, parent: parent);
- }
-
- @override
- List<FormalParameterBuilder>? get formals => _fragment.declaredFormals;
-
- @override
- VariableDeclaration getFormalParameter(int index) =>
- _fragment.declaredFormals![index].variable!;
-
- BuiltMemberKind get _builtMemberKind;
-
- bool get _isExtensionMember;
-
- bool get _isExtensionTypeMember;
-
- @override
- FunctionNode get function => _procedure!.function;
-
- @override
- Procedure get writeTarget => _procedure!;
-
- @override
- void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
- {required bool isAbstractOrExternal,
- List<TypeParameter>? classTypeParameters}) {
- FunctionNode function = new FunctionNode(
- isAbstractOrExternal ? null : new EmptyStatement(),
- asyncMarker: _fragment.asyncModifier)
- ..fileOffset = _fragment.formalsOffset
- ..fileEndOffset = _fragment.endOffset;
- buildTypeParametersAndFormals(
- libraryBuilder,
- function,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders,
- _fragment.declaredFormals,
- classTypeParameters: classTypeParameters,
- supportsTypeParameters: true);
- if (_fragment.returnType is! InferableTypeBuilder) {
- function.returnType =
- _fragment.returnType.build(libraryBuilder, TypeUse.returnType);
- }
- if (_fragment.declaredFormals?.length != 1 ||
- _fragment.declaredFormals![0].isOptionalPositional) {
- // Replace illegal parameters by single dummy parameter.
- // Do this after building the parameters, since the diet listener
- // assumes that parameters are built, even if illegal in number.
- VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
- function.positionalParameters.clear();
- function.positionalParameters.add(parameter);
- parameter.parent = function;
- function.namedParameters.clear();
- function.requiredParameterCount = 1;
- }
- MemberName memberName =
- nameScheme.getProcedureMemberName(ProcedureKind.Setter, _fragment.name);
- Procedure procedure = _procedure = new Procedure(
- memberName.name, ProcedureKind.Setter, function,
- reference: references.setterReference, fileUri: _fragment.fileUri)
- ..fileStartOffset = _fragment.startOffset
- ..fileOffset = _fragment.nameOffset
- ..fileEndOffset = _fragment.endOffset
- ..isAbstract = _fragment.modifiers.isAbstract
- ..isExternal = _fragment.modifiers.isExternal
- ..isConst = _fragment.modifiers.isConst
- ..isStatic = _fragment.modifiers.isStatic
- ..isExtensionMember = _isExtensionMember
- ..isExtensionTypeMember = _isExtensionTypeMember;
- memberName.attachMember(procedure);
-
- f(kind: _builtMemberKind, member: procedure);
- }
-
- @override
- void buildOutlineExpressions(
- ClassHierarchy classHierarchy,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- BodyBuilderContext bodyBuilderContext,
- Annotatable annotatable,
- {required bool isClassInstanceMember,
- required bool createFileUriExpression}) {
- _buildMetadataForOutlineExpressions(
- libraryBuilder,
- _fragment.enclosingScope,
- bodyBuilderContext,
- annotatable,
- _fragment.metadata,
- fileUri: _fragment.fileUri,
- createFileUriExpression: createFileUriExpression);
-
- _buildTypeParametersForOutlineExpressions(
- classHierarchy,
- libraryBuilder,
- bodyBuilderContext,
- _fragment.typeParameterScope,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- _buildFormalsForOutlineExpressions(
- libraryBuilder, declarationBuilder, _fragment.declaredFormals,
- scope: _fragment.typeParameterScope,
- isClassInstanceMember: isClassInstanceMember);
- }
-
- @override
- void becomeNative(SourceLoader loader) {
- loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
- }
-
- @override
- void checkTypes(
- SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
- {required bool isAbstract, required bool isExternal}) {
- List<TypeParameterBuilder>? typeParameters = _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders;
- // Coverage-ignore(suite): Not run.
- if (typeParameters != null && typeParameters.isNotEmpty) {
- libraryBuilder.checkTypeParameterDependencies(typeParameters);
- }
- libraryBuilder.checkInitializersInFormals(
- _fragment.declaredFormals, typeEnvironment,
- isAbstract: isAbstract, isExternal: isExternal);
- }
-
- @override
- void checkVariance(
- SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
- sourceClassBuilder.checkVarianceInTypeParameters(
- typeEnvironment,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- sourceClassBuilder.checkVarianceInFormals(
- typeEnvironment, _fragment.declaredFormals);
- sourceClassBuilder.checkVarianceInReturnType(
- typeEnvironment, function.returnType,
- fileOffset: _fragment.nameOffset, fileUri: _fragment.fileUri);
- }
-
- @override
- int computeDefaultTypes(ComputeDefaultTypeContext context) {
- bool hasErrors = context.reportSimplicityIssuesForTypeParameters(_fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
- if (_fragment.returnType is! OmittedTypeBuilder) {
- hasErrors |=
- context.reportInboundReferenceIssuesForType(_fragment.returnType);
- context.recursivelyReportGenericFunctionTypesAsBoundsForType(
- _fragment.returnType);
- }
- return context.computeDefaultTypesForVariables(
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders,
- inErrorRecovery: hasErrors);
- }
-
- @override
- void ensureTypes(
- SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy) {
- _fragment.returnType
- .build(libraryBuilder, TypeUse.returnType, hierarchy: hierarchy);
- List<FormalParameterBuilder>? declaredFormals = _fragment.declaredFormals;
- if (declaredFormals != null) {
- for (FormalParameterBuilder formal in declaredFormals) {
- formal.type
- .build(libraryBuilder, TypeUse.parameterType, hierarchy: hierarchy);
- }
- }
- }
-
- @override
- List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders;
-
- @override
- // Coverage-ignore(suite): Not run.
- List<FormalParameterBuilder>? get formalsForTesting =>
- _fragment.declaredFormals;
-}
-
-class _RegularSetterEncoding extends _SetterEncoding
- with _DirectSetterEncodingMixin {
- @override
- final SetterFragment _fragment;
-
- _RegularSetterEncoding(this._fragment);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.Method;
-
- @override
- bool get _isExtensionMember => false;
-
- @override
- bool get _isExtensionTypeMember => false;
-}
-
-class _ExtensionStaticSetterEncoding extends _SetterEncoding
- with _DirectSetterEncodingMixin {
- @override
- final SetterFragment _fragment;
-
- _ExtensionStaticSetterEncoding(this._fragment);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionSetter;
-
- @override
- bool get _isExtensionMember => true;
-
- @override
- bool get _isExtensionTypeMember => false;
-}
-
-class _ExtensionTypeStaticSetterEncoding extends _SetterEncoding
- with _DirectSetterEncodingMixin {
- @override
- final SetterFragment _fragment;
-
- _ExtensionTypeStaticSetterEncoding(this._fragment);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeSetter;
-
- @override
- bool get _isExtensionMember => false;
-
- @override
- bool get _isExtensionTypeMember => true;
-}
-
-mixin _ExtensionInstanceSetterEncodingMixin implements _SetterEncoding {
- SetterFragment get _fragment;
-
- Procedure? _procedure;
-
- List<NominalParameterBuilder>? get _clonedDeclarationTypeParameters;
-
- FormalParameterBuilder get _thisFormal;
-
- @override
- List<TypeParameter>? get thisTypeParameters =>
- _clonedDeclarationTypeParameters != null ? function.typeParameters : null;
-
- @override
- VariableDeclaration? get thisVariable => _thisFormal.variable!;
-
- BuiltMemberKind get _builtMemberKind;
-
- bool get _isExtensionMember;
-
- bool get _isExtensionTypeMember;
-
- @override
- FunctionNode get function => _procedure!.function;
-
- @override
- Procedure get writeTarget => _procedure!;
-
- @override
- void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
- {required bool isAbstractOrExternal,
- required List<TypeParameter>? classTypeParameters}) {
- List<TypeParameter>? typeParameters;
- if (_clonedDeclarationTypeParameters != null) {
- typeParameters = [];
- // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both required
- // and unnecessary.
- // ignore: unnecessary_non_null_assertion
- for (NominalParameterBuilder t in _clonedDeclarationTypeParameters!) {
- typeParameters.add(t.parameter);
- }
- }
- FunctionNode function = new FunctionNode(
- isAbstractOrExternal ? null : new EmptyStatement(),
- typeParameters: typeParameters,
- positionalParameters: [_thisFormal.build(libraryBuilder)],
- asyncMarker: _fragment.asyncModifier)
- ..fileOffset = _fragment.formalsOffset
- ..fileEndOffset = _fragment.endOffset;
- buildTypeParametersAndFormals(
- libraryBuilder,
- function,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders,
- _fragment.declaredFormals,
- classTypeParameters: classTypeParameters,
- supportsTypeParameters: true);
- // TODO(johnniwinther): We should have a consistent normalization strategy.
- // We ensure that setters have 1 parameter, but for getters we include all
- // declared parameters.
- if ((_fragment.declaredFormals?.length != 1 ||
- _fragment.declaredFormals![0].isOptionalPositional)) {
- // Replace illegal parameters by single dummy parameter (after #this).
- // Do this after building the parameters, since the diet listener
- // assumes that parameters are built, even if illegal in number.
- VariableDeclaration thisParameter = function.positionalParameters[0];
- VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
- function.positionalParameters.clear();
- function.positionalParameters.add(thisParameter);
- function.positionalParameters.add(parameter);
- parameter.parent = function;
- function.namedParameters.clear();
- function.requiredParameterCount = 2;
- }
- if (_fragment.returnType is! InferableTypeBuilder) {
- function.returnType =
- _fragment.returnType.build(libraryBuilder, TypeUse.returnType);
- }
-
- MemberName memberName =
- nameScheme.getProcedureMemberName(ProcedureKind.Setter, _fragment.name);
- Procedure procedure = _procedure = new Procedure(
- memberName.name, ProcedureKind.Method, function,
- reference: references.setterReference, fileUri: _fragment.fileUri)
- ..fileStartOffset = _fragment.startOffset
- ..fileOffset = _fragment.nameOffset
- ..fileEndOffset = _fragment.endOffset
- ..isAbstract = _fragment.modifiers.isAbstract
- ..isExternal = _fragment.modifiers.isExternal
- ..isConst = _fragment.modifiers.isConst
- ..isStatic = true
- ..isExtensionMember = _isExtensionMember
- ..isExtensionTypeMember = _isExtensionTypeMember;
- memberName.attachMember(procedure);
-
- f(kind: _builtMemberKind, member: procedure);
- }
-
- @override
- void buildOutlineExpressions(
- ClassHierarchy classHierarchy,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- BodyBuilderContext bodyBuilderContext,
- Annotatable annotatable,
- {required bool isClassInstanceMember,
- required bool createFileUriExpression}) {
- _buildMetadataForOutlineExpressions(
- libraryBuilder,
- _fragment.enclosingScope,
- bodyBuilderContext,
- annotatable,
- _fragment.metadata,
- fileUri: _fragment.fileUri,
- createFileUriExpression: createFileUriExpression);
-
- _buildTypeParametersForOutlineExpressions(
- classHierarchy,
- libraryBuilder,
- bodyBuilderContext,
- _fragment.typeParameterScope,
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- _buildFormalsForOutlineExpressions(
- libraryBuilder, declarationBuilder, _fragment.declaredFormals,
- scope: _fragment.typeParameterScope,
- isClassInstanceMember: isClassInstanceMember);
-
- _buildTypeParametersForOutlineExpressions(
- classHierarchy,
- libraryBuilder,
- bodyBuilderContext,
- _fragment.typeParameterScope,
- _clonedDeclarationTypeParameters);
- _buildFormalForOutlineExpressions(
- libraryBuilder, declarationBuilder, _thisFormal,
- scope: _fragment.typeParameterScope,
- isClassInstanceMember: isClassInstanceMember);
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- void becomeNative(SourceLoader loader) {
- loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
- }
-
- @override
- void checkTypes(
- SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
- {required bool isAbstract, required bool isExternal}) {
- List<TypeParameterBuilder>? typeParameters = _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders;
- // Coverage-ignore(suite): Not run.
- if (typeParameters != null && typeParameters.isNotEmpty) {
- libraryBuilder.checkTypeParameterDependencies(typeParameters);
- }
- libraryBuilder.checkInitializersInFormals(
- _fragment.declaredFormals, typeEnvironment,
- isAbstract: isAbstract, isExternal: isExternal);
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- void checkVariance(
- SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
- sourceClassBuilder.checkVarianceInTypeParameters(
- typeEnvironment, _fragment.declaredTypeParameters?.builders);
- sourceClassBuilder.checkVarianceInFormals(
- typeEnvironment, _fragment.declaredFormals);
- sourceClassBuilder.checkVarianceInReturnType(
- typeEnvironment, function.returnType,
- fileOffset: _fragment.nameOffset, fileUri: _fragment.fileUri);
- }
-
- @override
- LocalScope createFormalParameterScope(LookupScope parent) {
- Map<String, Builder> local = <String, Builder>{};
-
- assert(!_thisFormal.isWildcard);
- local[_thisFormal.name] = _thisFormal;
-
- List<FormalParameterBuilder>? formals = _fragment.declaredFormals;
- if (formals != null) {
- for (FormalParameterBuilder formal in formals) {
- if (formal.isWildcard) {
- continue;
- }
- local[formal.name] = formal;
- }
- }
- return new FormalParameterScope(local: local, parent: parent);
- }
-
- @override
- int computeDefaultTypes(ComputeDefaultTypeContext context) {
- bool hasErrors = context.reportSimplicityIssuesForTypeParameters(_fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders);
- context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
- if (_fragment.returnType is! OmittedTypeBuilder) {
- hasErrors |=
- context.reportInboundReferenceIssuesForType(_fragment.returnType);
- context.recursivelyReportGenericFunctionTypesAsBoundsForType(
- _fragment.returnType);
- }
- if (_clonedDeclarationTypeParameters != null &&
- _fragment.declaredTypeParameters != null) {
- // Coverage-ignore-block(suite): Not run.
- // We need to compute all default types together since they might be
- // interdependent.
- return context.computeDefaultTypesForVariables([
- // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both
- // required and unnecessary.
- // ignore: unnecessary_non_null_assertion
- ..._clonedDeclarationTypeParameters!,
- ..._fragment.declaredTypeParameters!.builders
- ], inErrorRecovery: hasErrors);
- } else if (_clonedDeclarationTypeParameters != null) {
- return context.computeDefaultTypesForVariables(
- _clonedDeclarationTypeParameters,
- inErrorRecovery: hasErrors);
- } else {
- return context.computeDefaultTypesForVariables(
- _fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders,
- inErrorRecovery: hasErrors);
- }
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- void ensureTypes(
- SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy) {
- _fragment.returnType
- .build(libraryBuilder, TypeUse.fieldType, hierarchy: hierarchy);
- _thisFormal.type
- .build(libraryBuilder, TypeUse.parameterType, hierarchy: hierarchy);
- List<FormalParameterBuilder>? declaredFormals = _fragment.declaredFormals;
- if (declaredFormals != null) {
- for (FormalParameterBuilder formal in declaredFormals) {
- formal.type
- .build(libraryBuilder, TypeUse.parameterType, hierarchy: hierarchy);
- }
- }
- }
-
- @override
- List<FormalParameterBuilder>? get formals =>
- [_thisFormal, ...?_fragment.declaredFormals];
-
- @override
- VariableDeclaration getFormalParameter(int index) =>
- _fragment.declaredFormals![index].variable!;
-
- @override
- List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
- _clonedDeclarationTypeParameters != null ||
- _fragment.declaredTypeParameters != null
- ? [
- ...?_clonedDeclarationTypeParameters,
- ...?_fragment
- .declaredTypeParameters
- // Coverage-ignore(suite): Not run.
- ?.builders
- ]
- : null;
-
- @override
- // Coverage-ignore(suite): Not run.
- List<FormalParameterBuilder>? get formalsForTesting =>
- [_thisFormal, ...?_fragment.declaredFormals];
-}
-
-class _ExtensionInstanceSetterEncoding extends _SetterEncoding
- with _ExtensionInstanceSetterEncodingMixin {
- @override
- final SetterFragment _fragment;
-
- @override
- final List<NominalParameterBuilder>? _clonedDeclarationTypeParameters;
-
- @override
- final FormalParameterBuilder _thisFormal;
-
- _ExtensionInstanceSetterEncoding(
- this._fragment, this._clonedDeclarationTypeParameters, this._thisFormal);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionSetter;
-
- @override
- bool get _isExtensionMember => true;
-
- @override
- bool get _isExtensionTypeMember => false;
-}
-
-class _ExtensionTypeInstanceSetterEncoding extends _SetterEncoding
- with _ExtensionInstanceSetterEncodingMixin {
- @override
- final SetterFragment _fragment;
-
- @override
- final List<NominalParameterBuilder>? _clonedDeclarationTypeParameters;
-
- @override
- final FormalParameterBuilder _thisFormal;
-
- _ExtensionTypeInstanceSetterEncoding(
- this._fragment, this._clonedDeclarationTypeParameters, this._thisFormal);
-
- @override
- BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeSetter;
-
- @override
- bool get _isExtensionMember => false;
-
- @override
- bool get _isExtensionTypeMember => true;
-}
-
-class _SetterFragmentBodyBuilderContext extends BodyBuilderContext {
- final SetterFragment _fragment;
-
- _SetterFragmentBodyBuilderContext(
- this._fragment,
- SourceLibraryBuilder libraryBuilder,
- DeclarationBuilder? declarationBuilder,
- {required bool isDeclarationInstanceMember})
- : super(libraryBuilder, declarationBuilder,
- isDeclarationInstanceMember: isDeclarationInstanceMember);
-
- @override
- bool get isSetter => true;
-
- @override
- LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
- /// Initializer formals or super parameters cannot occur in getters so
- /// we don't need to create a new scope.
- return parent;
- }
-
- @override
- FunctionNode get function => _fragment._encoding.function;
-
- @override
- bool get isExternalFunction => _fragment.modifiers.isExternal;
-
- @override
- void setAsyncModifier(AsyncMarker asyncModifier) {
- assert(
- asyncModifier == _fragment.asyncModifier,
- "Unexpected change in async modifier on $_fragment from "
- "${_fragment.asyncModifier} to $asyncModifier.");
- }
-
- @override
- int get memberNameOffset => _fragment.nameOffset;
-
- @override
- int get memberNameLength => _fragment.name.length;
-
- @override
- DartType get returnTypeContext {
- final bool isReturnTypeUndeclared =
- _fragment.returnType is OmittedTypeBuilder &&
- // Coverage-ignore(suite): Not run.
- function.returnType is DynamicType;
- return isReturnTypeUndeclared ? const UnknownType() : function.returnType;
- }
-
- @override
- TypeBuilder get returnType => _fragment.returnType;
-
- @override
- void registerFunctionBody(Statement body) {
- function.body = body..parent = function;
- }
-
- @override
- void registerSuperCall() {
- // TODO(johnniwinther): This should be set on the member built from this
- // fragment and copied to the origin if necessary.
- _fragment.builder.writeTarget!.transformerFlags |=
- TransformerFlag.superCalls;
- }
-
- @override
- List<FormalParameterBuilder>? get formals => _fragment._encoding.formals;
-
- @override
- VariableDeclaration getFormalParameter(int index) =>
- _fragment._encoding.getFormalParameter(index);
-
- @override
- VariableDeclaration? getTearOffParameter(int index) => null;
-
- @override
- // Coverage-ignore(suite): Not run.
- AugmentSuperTarget? get augmentSuperTarget {
- if (_fragment.builder.isAugmentation) {
- return _fragment.builder.augmentSuperTarget;
- }
- return null;
- }
+ VariableDeclaration? get thisVariable => _fragment.declaration.thisVariable;
}
diff --git a/pkg/front_end/lib/src/fragment/setter/body_builder_context.dart b/pkg/front_end/lib/src/fragment/setter/body_builder_context.dart
new file mode 100644
index 0000000..f8953db
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/setter/body_builder_context.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/transformations/flags.dart';
+
+import '../../base/local_scope.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/body_builder_context.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_member_builder.dart';
+import '../../source/source_property_builder.dart';
+import '../../type_inference/type_schema.dart';
+import 'declaration.dart';
+
+class SetterBodyBuilderContext extends BodyBuilderContext {
+ final SourcePropertyBuilder _builder;
+ final SetterDeclaration _declaration;
+
+ SetterBodyBuilderContext(
+ this._builder,
+ this._declaration,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ {required bool isDeclarationInstanceMember})
+ : super(libraryBuilder, declarationBuilder,
+ isDeclarationInstanceMember: isDeclarationInstanceMember);
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ AugmentSuperTarget? get augmentSuperTarget {
+ if (_builder.isAugmentation) {
+ return _builder.augmentSuperTarget;
+ }
+ return null;
+ }
+
+ @override
+ List<FormalParameterBuilder>? get formals => _declaration.formals;
+
+ @override
+ FunctionNode get function => _declaration.function;
+
+ @override
+ bool get isExternalFunction => _declaration.isExternal;
+
+ @override
+ bool get isSetter => true;
+
+ @override
+ int get memberNameLength => _declaration.name.length;
+
+ @override
+ int get memberNameOffset => _declaration.nameOffset;
+
+ @override
+ TypeBuilder get returnType => _declaration.returnType;
+
+ @override
+ DartType get returnTypeContext {
+ final bool isReturnTypeUndeclared =
+ _declaration.returnType is OmittedTypeBuilder &&
+ // Coverage-ignore(suite): Not run.
+ function.returnType is DynamicType;
+ return isReturnTypeUndeclared ? const UnknownType() : function.returnType;
+ }
+
+ @override
+ LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
+ /// Initializer formals or super parameters cannot occur in getters so
+ /// we don't need to create a new scope.
+ return parent;
+ }
+
+ @override
+ VariableDeclaration getFormalParameter(int index) =>
+ _declaration.getFormalParameter(index);
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) => null;
+
+ @override
+ void registerFunctionBody(Statement body) {
+ function.body = body..parent = function;
+ }
+
+ @override
+ void registerSuperCall() {
+ // TODO(johnniwinther): This should be set on the member built from this
+ // fragment and copied to the origin if necessary.
+ _builder.writeTarget!.transformerFlags |= TransformerFlag.superCalls;
+ }
+
+ @override
+ void setAsyncModifier(AsyncMarker asyncModifier) {
+ assert(
+ asyncModifier == _declaration.asyncModifier,
+ "Unexpected change in async modifier on $_declaration from "
+ "${_declaration.asyncModifier} to $asyncModifier.");
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/setter/declaration.dart b/pkg/front_end/lib/src/fragment/setter/declaration.dart
new file mode 100644
index 0000000..74fcf57
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/setter/declaration.dart
@@ -0,0 +1,263 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/type_environment.dart';
+
+import '../../base/local_scope.dart';
+import '../../base/messages.dart';
+import '../../base/scope.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/metadata_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/body_builder_context.dart';
+import '../../kernel/hierarchy/class_member.dart';
+import '../../kernel/hierarchy/members_builder.dart';
+import '../../kernel/type_algorithms.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_loader.dart';
+import '../../source/source_member_builder.dart';
+import '../../source/source_property_builder.dart';
+import '../fragment.dart';
+import 'body_builder_context.dart';
+import 'encoding.dart';
+
+abstract class SetterDeclaration {
+ AsyncMarker get asyncModifier;
+
+ Uri get fileUri;
+
+ List<FormalParameterBuilder>? get formals;
+
+ FunctionNode get function;
+
+ bool get isAbstract;
+
+ bool get isExternal;
+
+ List<MetadataBuilder>? get metadata;
+
+ String get name;
+
+ int get nameOffset;
+
+ TypeBuilder get returnType;
+
+ List<TypeParameter>? get thisTypeParameters;
+
+ VariableDeclaration? get thisVariable;
+
+ List<NominalParameterBuilder>? get typeParametersForTesting;
+
+ Procedure get writeTarget;
+
+ void becomeNative(SourceLoader loader);
+
+ void buildOutlineExpressions(
+ {required ClassHierarchy classHierarchy,
+ required SourceLibraryBuilder libraryBuilder,
+ required DeclarationBuilder? declarationBuilder,
+ required SourcePropertyBuilder propertyBuilder,
+ required Annotatable annotatable,
+ required bool isClassInstanceMember,
+ required bool createFileUriExpression});
+
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required List<TypeParameter>? classTypeParameters});
+
+ void checkTypes(
+ SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
+ {required bool isAbstract, required bool isExternal});
+
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
+
+ int computeDefaultTypes(ComputeDefaultTypeContext context);
+
+ BodyBuilderContext createBodyBuilderContext(
+ SourcePropertyBuilder propertyBuilder);
+
+ void createEncoding(
+ ProblemReporting problemReporting,
+ SourcePropertyBuilder builder,
+ PropertyEncodingStrategy encodingStrategy,
+ List<NominalParameterBuilder> unboundNominalParameters);
+
+ LocalScope createFormalParameterScope(LookupScope typeParameterScope);
+
+ void ensureTypes(
+ {required SourceLibraryBuilder libraryBuilder,
+ required DeclarationBuilder? declarationBuilder,
+ required ClassMembersBuilder membersBuilder,
+ required Set<ClassMember>? setterOverrideDependencies});
+
+ Iterable<Reference> getExportedMemberReferences(SetterReference references);
+
+ VariableDeclaration getFormalParameter(int index);
+}
+
+class SetterDeclarationImpl implements SetterDeclaration {
+ final SetterFragment _fragment;
+ late final SetterEncoding _encoding;
+
+ SetterDeclarationImpl(this._fragment) {
+ _fragment.declaration = this;
+ }
+
+ @override
+ AsyncMarker get asyncModifier => _fragment.asyncModifier;
+
+ @override
+ Uri get fileUri => _fragment.fileUri;
+
+ @override
+ List<FormalParameterBuilder>? get formals => _encoding.formals;
+
+ @override
+ FunctionNode get function => _encoding.function;
+
+ @override
+ bool get isAbstract => _fragment.modifiers.isAbstract;
+
+ @override
+ bool get isExternal => _fragment.modifiers.isExternal;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ List<MetadataBuilder>? get metadata => _fragment.metadata;
+
+ @override
+ String get name => _fragment.name;
+
+ @override
+ int get nameOffset => _fragment.nameOffset;
+
+ @override
+ TypeBuilder get returnType => _fragment.returnType;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters => _encoding.thisTypeParameters;
+
+ @override
+ VariableDeclaration? get thisVariable => _encoding.thisVariable;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ List<NominalParameterBuilder>? get typeParametersForTesting =>
+ _encoding.clonedAndDeclaredTypeParameters;
+
+ @override
+ Procedure get writeTarget => _encoding.writeTarget;
+
+ @override
+ void becomeNative(SourceLoader loader) {
+ _encoding.becomeNative(loader);
+ }
+
+ @override
+ void buildOutlineExpressions(
+ {required ClassHierarchy classHierarchy,
+ required SourceLibraryBuilder libraryBuilder,
+ required DeclarationBuilder? declarationBuilder,
+ required SourcePropertyBuilder propertyBuilder,
+ required Annotatable annotatable,
+ required bool isClassInstanceMember,
+ required bool createFileUriExpression}) {
+ _encoding.buildOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ declarationBuilder,
+ createBodyBuilderContext(propertyBuilder),
+ annotatable,
+ isClassInstanceMember: isClassInstanceMember,
+ createFileUriExpression: createFileUriExpression);
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required List<TypeParameter>? classTypeParameters}) {
+ _encoding.buildOutlineNode(libraryBuilder, nameScheme, f, references,
+ isAbstractOrExternal:
+ _fragment.modifiers.isAbstract || _fragment.modifiers.isExternal,
+ classTypeParameters: classTypeParameters);
+ }
+
+ @override
+ void checkTypes(
+ SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
+ {required bool isAbstract, required bool isExternal}) {
+ _encoding.checkTypes(libraryBuilder, typeEnvironment,
+ isAbstract: isAbstract, isExternal: isExternal);
+ }
+
+ @override
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
+ _encoding.checkVariance(sourceClassBuilder, typeEnvironment);
+ }
+
+ @override
+ int computeDefaultTypes(ComputeDefaultTypeContext context) {
+ return _encoding.computeDefaultTypes(context);
+ }
+
+ @override
+ BodyBuilderContext createBodyBuilderContext(
+ SourcePropertyBuilder propertyBuilder) {
+ return new SetterBodyBuilderContext(propertyBuilder, this,
+ propertyBuilder.libraryBuilder, propertyBuilder.declarationBuilder,
+ isDeclarationInstanceMember:
+ propertyBuilder.isDeclarationInstanceMember);
+ }
+
+ @override
+ void createEncoding(
+ ProblemReporting problemReporting,
+ SourcePropertyBuilder builder,
+ PropertyEncodingStrategy encodingStrategy,
+ List<NominalParameterBuilder> unboundNominalParameters) {
+ _encoding = encodingStrategy.createSetterEncoding(
+ builder, _fragment, unboundNominalParameters);
+ _fragment.typeParameterNameSpace.addTypeParameters(
+ problemReporting, _encoding.clonedAndDeclaredTypeParameters,
+ ownerName: _fragment.name, allowNameConflict: true);
+ }
+
+ @override
+ LocalScope createFormalParameterScope(LookupScope typeParameterScope) {
+ return _encoding.createFormalParameterScope(typeParameterScope);
+ }
+
+ @override
+ void ensureTypes(
+ {required SourceLibraryBuilder libraryBuilder,
+ required DeclarationBuilder? declarationBuilder,
+ required ClassMembersBuilder membersBuilder,
+ required Set<ClassMember>? setterOverrideDependencies}) {
+ if (setterOverrideDependencies != null) {
+ membersBuilder.inferSetterType(declarationBuilder as SourceClassBuilder,
+ _fragment.declaredFormals, setterOverrideDependencies,
+ name: _fragment.name,
+ fileUri: _fragment.fileUri,
+ nameOffset: _fragment.nameOffset,
+ nameLength: _fragment.name.length);
+ }
+ _encoding.ensureTypes(libraryBuilder, membersBuilder.hierarchyBuilder);
+ }
+
+ @override
+ Iterable<Reference> getExportedMemberReferences(SetterReference references) =>
+ [references.setterReference];
+
+ @override
+ VariableDeclaration getFormalParameter(int index) {
+ return _encoding.getFormalParameter(index);
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/setter/encoding.dart b/pkg/front_end/lib/src/fragment/setter/encoding.dart
new file mode 100644
index 0000000..6abce30
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/setter/encoding.dart
@@ -0,0 +1,653 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/type_environment.dart';
+
+import '../../base/local_scope.dart';
+import '../../base/scope.dart';
+import '../../builder/builder.dart';
+import '../../builder/declaration_builders.dart';
+import '../../builder/formal_parameter_builder.dart';
+import '../../builder/omitted_type_builder.dart';
+import '../../builder/type_builder.dart';
+import '../../kernel/body_builder_context.dart';
+import '../../kernel/internal_ast.dart';
+import '../../kernel/type_algorithms.dart';
+import '../../source/name_scheme.dart';
+import '../../source/source_class_builder.dart';
+import '../../source/source_function_builder.dart';
+import '../../source/source_library_builder.dart';
+import '../../source/source_loader.dart';
+import '../../source/source_member_builder.dart';
+import '../../source/source_property_builder.dart';
+import '../fragment.dart';
+
+class ExtensionInstanceSetterEncoding extends SetterEncoding
+ with _ExtensionInstanceSetterEncodingMixin {
+ @override
+ final SetterFragment _fragment;
+
+ @override
+ final List<NominalParameterBuilder>? _clonedDeclarationTypeParameters;
+
+ @override
+ final FormalParameterBuilder _thisFormal;
+
+ ExtensionInstanceSetterEncoding(
+ this._fragment, this._clonedDeclarationTypeParameters, this._thisFormal);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionSetter;
+
+ @override
+ bool get _isExtensionMember => true;
+
+ @override
+ bool get _isExtensionTypeMember => false;
+}
+
+class ExtensionStaticSetterEncoding extends SetterEncoding
+ with _DirectSetterEncodingMixin {
+ @override
+ final SetterFragment _fragment;
+
+ ExtensionStaticSetterEncoding(this._fragment);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionSetter;
+
+ @override
+ bool get _isExtensionMember => true;
+
+ @override
+ bool get _isExtensionTypeMember => false;
+}
+
+class ExtensionTypeInstanceSetterEncoding extends SetterEncoding
+ with _ExtensionInstanceSetterEncodingMixin {
+ @override
+ final SetterFragment _fragment;
+
+ @override
+ final List<NominalParameterBuilder>? _clonedDeclarationTypeParameters;
+
+ @override
+ final FormalParameterBuilder _thisFormal;
+
+ ExtensionTypeInstanceSetterEncoding(
+ this._fragment, this._clonedDeclarationTypeParameters, this._thisFormal);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeSetter;
+
+ @override
+ bool get _isExtensionMember => false;
+
+ @override
+ bool get _isExtensionTypeMember => true;
+}
+
+class ExtensionTypeStaticSetterEncoding extends SetterEncoding
+ with _DirectSetterEncodingMixin {
+ @override
+ final SetterFragment _fragment;
+
+ ExtensionTypeStaticSetterEncoding(this._fragment);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeSetter;
+
+ @override
+ bool get _isExtensionMember => false;
+
+ @override
+ bool get _isExtensionTypeMember => true;
+}
+
+class RegularSetterEncoding extends SetterEncoding
+ with _DirectSetterEncodingMixin {
+ @override
+ final SetterFragment _fragment;
+
+ RegularSetterEncoding(this._fragment);
+
+ @override
+ BuiltMemberKind get _builtMemberKind => BuiltMemberKind.Method;
+
+ @override
+ bool get _isExtensionMember => false;
+
+ @override
+ bool get _isExtensionTypeMember => false;
+}
+
+sealed class SetterEncoding {
+ List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters;
+ List<FormalParameterBuilder>? get formals;
+ FunctionNode get function;
+
+ List<TypeParameter>? get thisTypeParameters;
+
+ VariableDeclaration? get thisVariable;
+
+ Procedure get writeTarget;
+
+ void becomeNative(SourceLoader loader);
+
+ void buildOutlineExpressions(
+ ClassHierarchy classHierarchy,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ BodyBuilderContext bodyBuilderContext,
+ Annotatable annotatable,
+ {required bool isClassInstanceMember,
+ required bool createFileUriExpression});
+
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters});
+
+ void checkTypes(
+ SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
+ {required bool isAbstract, required bool isExternal});
+
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
+
+ int computeDefaultTypes(ComputeDefaultTypeContext context);
+
+ LocalScope createFormalParameterScope(LookupScope typeParameterScope);
+
+ void ensureTypes(
+ SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy);
+
+ VariableDeclaration getFormalParameter(int index);
+}
+
+mixin _DirectSetterEncodingMixin implements SetterEncoding {
+ Procedure? _procedure;
+
+ @override
+ List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders;
+
+ @override
+ List<FormalParameterBuilder>? get formals => _fragment.declaredFormals;
+
+ @override
+ FunctionNode get function => _procedure!.function;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters => null;
+
+ @override
+ VariableDeclaration? get thisVariable => null;
+
+ @override
+ Procedure get writeTarget => _procedure!;
+
+ BuiltMemberKind get _builtMemberKind;
+
+ SetterFragment get _fragment;
+
+ bool get _isExtensionMember;
+
+ bool get _isExtensionTypeMember;
+
+ @override
+ void becomeNative(SourceLoader loader) {
+ loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
+ }
+
+ @override
+ void buildOutlineExpressions(
+ ClassHierarchy classHierarchy,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ BodyBuilderContext bodyBuilderContext,
+ Annotatable annotatable,
+ {required bool isClassInstanceMember,
+ required bool createFileUriExpression}) {
+ buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
+ bodyBuilderContext, annotatable, _fragment.metadata,
+ fileUri: _fragment.fileUri,
+ createFileUriExpression: createFileUriExpression);
+
+ buildTypeParametersForOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ bodyBuilderContext,
+ _fragment.typeParameterScope,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ buildFormalsForOutlineExpressions(
+ libraryBuilder, declarationBuilder, _fragment.declaredFormals,
+ scope: _fragment.typeParameterScope,
+ isClassInstanceMember: isClassInstanceMember);
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required bool isAbstractOrExternal,
+ List<TypeParameter>? classTypeParameters}) {
+ FunctionNode function = new FunctionNode(
+ isAbstractOrExternal ? null : new EmptyStatement(),
+ asyncMarker: _fragment.asyncModifier)
+ ..fileOffset = _fragment.formalsOffset
+ ..fileEndOffset = _fragment.endOffset;
+ buildTypeParametersAndFormals(
+ libraryBuilder,
+ function,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders,
+ _fragment.declaredFormals,
+ classTypeParameters: classTypeParameters,
+ supportsTypeParameters: true);
+ if (_fragment.returnType is! InferableTypeBuilder) {
+ function.returnType =
+ _fragment.returnType.build(libraryBuilder, TypeUse.returnType);
+ }
+ if (_fragment.declaredFormals?.length != 1 ||
+ _fragment.declaredFormals![0].isOptionalPositional) {
+ // Replace illegal parameters by single dummy parameter.
+ // Do this after building the parameters, since the diet listener
+ // assumes that parameters are built, even if illegal in number.
+ VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
+ function.positionalParameters.clear();
+ function.positionalParameters.add(parameter);
+ parameter.parent = function;
+ function.namedParameters.clear();
+ function.requiredParameterCount = 1;
+ }
+ MemberName memberName =
+ nameScheme.getProcedureMemberName(ProcedureKind.Setter, _fragment.name);
+ Procedure procedure = _procedure = new Procedure(
+ memberName.name, ProcedureKind.Setter, function,
+ reference: references.setterReference, fileUri: _fragment.fileUri)
+ ..fileStartOffset = _fragment.startOffset
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset
+ ..isAbstract = _fragment.modifiers.isAbstract
+ ..isExternal = _fragment.modifiers.isExternal
+ ..isConst = _fragment.modifiers.isConst
+ ..isStatic = _fragment.modifiers.isStatic
+ ..isExtensionMember = _isExtensionMember
+ ..isExtensionTypeMember = _isExtensionTypeMember;
+ memberName.attachMember(procedure);
+
+ f(kind: _builtMemberKind, member: procedure);
+ }
+
+ @override
+ void checkTypes(
+ SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
+ {required bool isAbstract, required bool isExternal}) {
+ List<TypeParameterBuilder>? typeParameters = _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders;
+ // Coverage-ignore(suite): Not run.
+ if (typeParameters != null && typeParameters.isNotEmpty) {
+ libraryBuilder.checkTypeParameterDependencies(typeParameters);
+ }
+ libraryBuilder.checkInitializersInFormals(
+ _fragment.declaredFormals, typeEnvironment,
+ isAbstract: isAbstract, isExternal: isExternal);
+ }
+
+ @override
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
+ sourceClassBuilder.checkVarianceInTypeParameters(
+ typeEnvironment,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ sourceClassBuilder.checkVarianceInFormals(
+ typeEnvironment, _fragment.declaredFormals);
+ sourceClassBuilder.checkVarianceInReturnType(
+ typeEnvironment, function.returnType,
+ fileOffset: _fragment.nameOffset, fileUri: _fragment.fileUri);
+ }
+
+ @override
+ int computeDefaultTypes(ComputeDefaultTypeContext context) {
+ bool hasErrors = context.reportSimplicityIssuesForTypeParameters(_fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
+ if (_fragment.returnType is! OmittedTypeBuilder) {
+ hasErrors |=
+ context.reportInboundReferenceIssuesForType(_fragment.returnType);
+ context.recursivelyReportGenericFunctionTypesAsBoundsForType(
+ _fragment.returnType);
+ }
+ return context.computeDefaultTypesForVariables(
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders,
+ inErrorRecovery: hasErrors);
+ }
+
+ @override
+ LocalScope createFormalParameterScope(LookupScope parent) {
+ Map<String, Builder> local = <String, Builder>{};
+ List<FormalParameterBuilder>? formals = _fragment.declaredFormals;
+ if (formals != null) {
+ for (FormalParameterBuilder formal in formals) {
+ if (formal.isWildcard) {
+ continue;
+ }
+ local[formal.name] = formal;
+ }
+ }
+ return new FormalParameterScope(local: local, parent: parent);
+ }
+
+ @override
+ void ensureTypes(
+ SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy) {
+ _fragment.returnType
+ .build(libraryBuilder, TypeUse.returnType, hierarchy: hierarchy);
+ List<FormalParameterBuilder>? declaredFormals = _fragment.declaredFormals;
+ if (declaredFormals != null) {
+ for (FormalParameterBuilder formal in declaredFormals) {
+ formal.type
+ .build(libraryBuilder, TypeUse.parameterType, hierarchy: hierarchy);
+ }
+ }
+ }
+
+ @override
+ VariableDeclaration getFormalParameter(int index) =>
+ _fragment.declaredFormals![index].variable!;
+}
+
+mixin _ExtensionInstanceSetterEncodingMixin implements SetterEncoding {
+ Procedure? _procedure;
+
+ @override
+ List<NominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
+ _clonedDeclarationTypeParameters != null ||
+ _fragment.declaredTypeParameters != null
+ ? [
+ ...?_clonedDeclarationTypeParameters,
+ ...?_fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders
+ ]
+ : null;
+
+ @override
+ List<FormalParameterBuilder>? get formals =>
+ [_thisFormal, ...?_fragment.declaredFormals];
+
+ @override
+ FunctionNode get function => _procedure!.function;
+
+ @override
+ List<TypeParameter>? get thisTypeParameters =>
+ _clonedDeclarationTypeParameters != null ? function.typeParameters : null;
+
+ @override
+ VariableDeclaration? get thisVariable => _thisFormal.variable!;
+
+ @override
+ Procedure get writeTarget => _procedure!;
+
+ BuiltMemberKind get _builtMemberKind;
+
+ List<NominalParameterBuilder>? get _clonedDeclarationTypeParameters;
+
+ SetterFragment get _fragment;
+
+ bool get _isExtensionMember;
+
+ bool get _isExtensionTypeMember;
+
+ FormalParameterBuilder get _thisFormal;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void becomeNative(SourceLoader loader) {
+ loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
+ }
+
+ @override
+ void buildOutlineExpressions(
+ ClassHierarchy classHierarchy,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ BodyBuilderContext bodyBuilderContext,
+ Annotatable annotatable,
+ {required bool isClassInstanceMember,
+ required bool createFileUriExpression}) {
+ buildMetadataForOutlineExpressions(libraryBuilder, _fragment.enclosingScope,
+ bodyBuilderContext, annotatable, _fragment.metadata,
+ fileUri: _fragment.fileUri,
+ createFileUriExpression: createFileUriExpression);
+
+ buildTypeParametersForOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ bodyBuilderContext,
+ _fragment.typeParameterScope,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ buildFormalsForOutlineExpressions(
+ libraryBuilder, declarationBuilder, _fragment.declaredFormals,
+ scope: _fragment.typeParameterScope,
+ isClassInstanceMember: isClassInstanceMember);
+
+ buildTypeParametersForOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ bodyBuilderContext,
+ _fragment.typeParameterScope,
+ _clonedDeclarationTypeParameters);
+ buildFormalForOutlineExpressions(
+ libraryBuilder, declarationBuilder, _thisFormal,
+ scope: _fragment.typeParameterScope,
+ isClassInstanceMember: isClassInstanceMember);
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters}) {
+ List<TypeParameter>? typeParameters;
+ if (_clonedDeclarationTypeParameters != null) {
+ typeParameters = [];
+ // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both required
+ // and unnecessary.
+ // ignore: unnecessary_non_null_assertion
+ for (NominalParameterBuilder t in _clonedDeclarationTypeParameters!) {
+ typeParameters.add(t.parameter);
+ }
+ }
+ FunctionNode function = new FunctionNode(
+ isAbstractOrExternal ? null : new EmptyStatement(),
+ typeParameters: typeParameters,
+ positionalParameters: [_thisFormal.build(libraryBuilder)],
+ asyncMarker: _fragment.asyncModifier)
+ ..fileOffset = _fragment.formalsOffset
+ ..fileEndOffset = _fragment.endOffset;
+ buildTypeParametersAndFormals(
+ libraryBuilder,
+ function,
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders,
+ _fragment.declaredFormals,
+ classTypeParameters: classTypeParameters,
+ supportsTypeParameters: true);
+ // TODO(johnniwinther): We should have a consistent normalization strategy.
+ // We ensure that setters have 1 parameter, but for getters we include all
+ // declared parameters.
+ if ((_fragment.declaredFormals?.length != 1 ||
+ _fragment.declaredFormals![0].isOptionalPositional)) {
+ // Replace illegal parameters by single dummy parameter (after #this).
+ // Do this after building the parameters, since the diet listener
+ // assumes that parameters are built, even if illegal in number.
+ VariableDeclaration thisParameter = function.positionalParameters[0];
+ VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
+ function.positionalParameters.clear();
+ function.positionalParameters.add(thisParameter);
+ function.positionalParameters.add(parameter);
+ parameter.parent = function;
+ function.namedParameters.clear();
+ function.requiredParameterCount = 2;
+ }
+ if (_fragment.returnType is! InferableTypeBuilder) {
+ function.returnType =
+ _fragment.returnType.build(libraryBuilder, TypeUse.returnType);
+ }
+
+ MemberName memberName =
+ nameScheme.getProcedureMemberName(ProcedureKind.Setter, _fragment.name);
+ Procedure procedure = _procedure = new Procedure(
+ memberName.name, ProcedureKind.Method, function,
+ reference: references.setterReference, fileUri: _fragment.fileUri)
+ ..fileStartOffset = _fragment.startOffset
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset
+ ..isAbstract = _fragment.modifiers.isAbstract
+ ..isExternal = _fragment.modifiers.isExternal
+ ..isConst = _fragment.modifiers.isConst
+ ..isStatic = true
+ ..isExtensionMember = _isExtensionMember
+ ..isExtensionTypeMember = _isExtensionTypeMember;
+ memberName.attachMember(procedure);
+
+ f(kind: _builtMemberKind, member: procedure);
+ }
+
+ @override
+ void checkTypes(
+ SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment,
+ {required bool isAbstract, required bool isExternal}) {
+ List<TypeParameterBuilder>? typeParameters = _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders;
+ // Coverage-ignore(suite): Not run.
+ if (typeParameters != null && typeParameters.isNotEmpty) {
+ libraryBuilder.checkTypeParameterDependencies(typeParameters);
+ }
+ libraryBuilder.checkInitializersInFormals(
+ _fragment.declaredFormals, typeEnvironment,
+ isAbstract: isAbstract, isExternal: isExternal);
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
+ sourceClassBuilder.checkVarianceInTypeParameters(
+ typeEnvironment, _fragment.declaredTypeParameters?.builders);
+ sourceClassBuilder.checkVarianceInFormals(
+ typeEnvironment, _fragment.declaredFormals);
+ sourceClassBuilder.checkVarianceInReturnType(
+ typeEnvironment, function.returnType,
+ fileOffset: _fragment.nameOffset, fileUri: _fragment.fileUri);
+ }
+
+ @override
+ int computeDefaultTypes(ComputeDefaultTypeContext context) {
+ bool hasErrors = context.reportSimplicityIssuesForTypeParameters(_fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders);
+ context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
+ if (_fragment.returnType is! OmittedTypeBuilder) {
+ hasErrors |=
+ context.reportInboundReferenceIssuesForType(_fragment.returnType);
+ context.recursivelyReportGenericFunctionTypesAsBoundsForType(
+ _fragment.returnType);
+ }
+ if (_clonedDeclarationTypeParameters != null &&
+ _fragment.declaredTypeParameters != null) {
+ // Coverage-ignore-block(suite): Not run.
+ // We need to compute all default types together since they might be
+ // interdependent.
+ return context.computeDefaultTypesForVariables([
+ // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both
+ // required and unnecessary.
+ // ignore: unnecessary_non_null_assertion
+ ..._clonedDeclarationTypeParameters!,
+ ..._fragment.declaredTypeParameters!.builders
+ ], inErrorRecovery: hasErrors);
+ } else if (_clonedDeclarationTypeParameters != null) {
+ return context.computeDefaultTypesForVariables(
+ _clonedDeclarationTypeParameters,
+ inErrorRecovery: hasErrors);
+ } else {
+ return context.computeDefaultTypesForVariables(
+ _fragment
+ .declaredTypeParameters
+ // Coverage-ignore(suite): Not run.
+ ?.builders,
+ inErrorRecovery: hasErrors);
+ }
+ }
+
+ @override
+ LocalScope createFormalParameterScope(LookupScope parent) {
+ Map<String, Builder> local = <String, Builder>{};
+
+ assert(!_thisFormal.isWildcard);
+ local[_thisFormal.name] = _thisFormal;
+
+ List<FormalParameterBuilder>? formals = _fragment.declaredFormals;
+ if (formals != null) {
+ for (FormalParameterBuilder formal in formals) {
+ if (formal.isWildcard) {
+ continue;
+ }
+ local[formal.name] = formal;
+ }
+ }
+ return new FormalParameterScope(local: local, parent: parent);
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void ensureTypes(
+ SourceLibraryBuilder libraryBuilder, ClassHierarchyBase hierarchy) {
+ _fragment.returnType
+ .build(libraryBuilder, TypeUse.fieldType, hierarchy: hierarchy);
+ _thisFormal.type
+ .build(libraryBuilder, TypeUse.parameterType, hierarchy: hierarchy);
+ List<FormalParameterBuilder>? declaredFormals = _fragment.declaredFormals;
+ if (declaredFormals != null) {
+ for (FormalParameterBuilder formal in declaredFormals) {
+ formal.type
+ .build(libraryBuilder, TypeUse.parameterType, hierarchy: hierarchy);
+ }
+ }
+ }
+
+ @override
+ VariableDeclaration getFormalParameter(int index) =>
+ _fragment.declaredFormals![index].variable!;
+}
diff --git a/pkg/front_end/lib/src/fragment/util.dart b/pkg/front_end/lib/src/fragment/util.dart
index 902c1b6..c7d39fe 100644
--- a/pkg/front_end/lib/src/fragment/util.dart
+++ b/pkg/front_end/lib/src/fragment/util.dart
@@ -45,7 +45,7 @@
: assert(name != 'new');
}
-void _buildMetadataForOutlineExpressions(
+void buildMetadataForOutlineExpressions(
SourceLibraryBuilder libraryBuilder,
LookupScope parentScope,
BodyBuilderContext bodyBuilderContext,
@@ -58,7 +58,7 @@
createFileUriExpression: createFileUriExpression);
}
-void _buildTypeParametersForOutlineExpressions(
+void buildTypeParametersForOutlineExpressions(
ClassHierarchy classHierarchy,
SourceLibraryBuilder libraryBuilder,
BodyBuilderContext bodyBuilderContext,
@@ -72,7 +72,7 @@
}
}
-void _buildFormalsForOutlineExpressions(
+void buildFormalsForOutlineExpressions(
SourceLibraryBuilder libraryBuilder,
DeclarationBuilder? declarationBuilder,
List<FormalParameterBuilder>? formals,
@@ -80,14 +80,14 @@
required bool isClassInstanceMember}) {
if (formals != null) {
for (FormalParameterBuilder formal in formals) {
- _buildFormalForOutlineExpressions(
+ buildFormalForOutlineExpressions(
libraryBuilder, declarationBuilder, formal,
scope: scope, isClassInstanceMember: isClassInstanceMember);
}
}
}
-void _buildFormalForOutlineExpressions(SourceLibraryBuilder libraryBuilder,
+void buildFormalForOutlineExpressions(SourceLibraryBuilder libraryBuilder,
DeclarationBuilder? declarationBuilder, FormalParameterBuilder formal,
{required LookupScope scope, required bool isClassInstanceMember}) {
// For const constructors we need to include default parameter values
@@ -321,12 +321,12 @@
}
}
- _GetterEncoding createGetterEncoding(
+ GetterEncoding createGetterEncoding(
SourcePropertyBuilder builder,
GetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters);
- _SetterEncoding createSetterEncoding(
+ SetterEncoding createSetterEncoding(
SourcePropertyBuilder builder,
SetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters);
@@ -336,19 +336,19 @@
const RegularPropertyEncodingStrategy();
@override
- _GetterEncoding createGetterEncoding(
+ GetterEncoding createGetterEncoding(
SourcePropertyBuilder builder,
GetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
- return new _RegularGetterEncoding(fragment);
+ return new RegularGetterEncoding(fragment);
}
@override
- _SetterEncoding createSetterEncoding(
+ SetterEncoding createSetterEncoding(
SourcePropertyBuilder builder,
SetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
- return new _RegularSetterEncoding(fragment);
+ return new RegularSetterEncoding(fragment);
}
}
@@ -357,7 +357,7 @@
const ExtensionInstancePropertyEncodingStrategy();
@override
- _GetterEncoding createGetterEncoding(
+ GetterEncoding createGetterEncoding(
SourcePropertyBuilder builder,
GetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
@@ -371,12 +371,12 @@
onTypeBuilder: declarationBuilder.onType,
fileUri: fragment.fileUri,
fileOffset: fragment.nameOffset);
- return new _ExtensionInstanceGetterEncoding(fragment,
+ return new ExtensionInstanceGetterEncoding(fragment,
signature.clonedDeclarationTypeParameters, signature.thisFormal);
}
@override
- _SetterEncoding createSetterEncoding(
+ SetterEncoding createSetterEncoding(
SourcePropertyBuilder builder,
SetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
@@ -390,7 +390,7 @@
onTypeBuilder: declarationBuilder.onType,
fileUri: fragment.fileUri,
fileOffset: fragment.nameOffset);
- return new _ExtensionInstanceSetterEncoding(fragment,
+ return new ExtensionInstanceSetterEncoding(fragment,
signature.clonedDeclarationTypeParameters, signature.thisFormal);
}
}
@@ -400,19 +400,19 @@
const ExtensionStaticPropertyEncodingStrategy();
@override
- _GetterEncoding createGetterEncoding(
+ GetterEncoding createGetterEncoding(
SourcePropertyBuilder builder,
GetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
- return new _ExtensionStaticGetterEncoding(fragment);
+ return new ExtensionStaticGetterEncoding(fragment);
}
@override
- _SetterEncoding createSetterEncoding(
+ SetterEncoding createSetterEncoding(
SourcePropertyBuilder builder,
SetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
- return new _ExtensionStaticSetterEncoding(fragment);
+ return new ExtensionStaticSetterEncoding(fragment);
}
}
@@ -421,7 +421,7 @@
const ExtensionTypeInstancePropertyEncodingStrategy();
@override
- _GetterEncoding createGetterEncoding(
+ GetterEncoding createGetterEncoding(
SourcePropertyBuilder builder,
GetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
@@ -435,12 +435,12 @@
unboundNominalParameters: unboundNominalParameters,
fileUri: fragment.fileUri,
fileOffset: fragment.nameOffset);
- return new _ExtensionTypeInstanceGetterEncoding(fragment,
+ return new ExtensionTypeInstanceGetterEncoding(fragment,
signature.clonedDeclarationTypeParameters, signature.thisFormal);
}
@override
- _SetterEncoding createSetterEncoding(
+ SetterEncoding createSetterEncoding(
SourcePropertyBuilder builder,
SetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
@@ -454,7 +454,7 @@
unboundNominalParameters: unboundNominalParameters,
fileUri: fragment.fileUri,
fileOffset: fragment.nameOffset);
- return new _ExtensionTypeInstanceSetterEncoding(fragment,
+ return new ExtensionTypeInstanceSetterEncoding(fragment,
signature.clonedDeclarationTypeParameters, signature.thisFormal);
}
}
@@ -464,18 +464,18 @@
const ExtensionTypeStaticPropertyEncodingStrategy();
@override
- _GetterEncoding createGetterEncoding(
+ GetterEncoding createGetterEncoding(
SourcePropertyBuilder builder,
GetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
- return new _ExtensionTypeStaticGetterEncoding(fragment);
+ return new ExtensionTypeStaticGetterEncoding(fragment);
}
@override
- _SetterEncoding createSetterEncoding(
+ SetterEncoding createSetterEncoding(
SourcePropertyBuilder builder,
SetterFragment fragment,
List<NominalParameterBuilder> unboundNominalParameters) {
- return new _ExtensionTypeStaticSetterEncoding(fragment);
+ return new ExtensionTypeStaticSetterEncoding(fragment);
}
}
diff --git a/pkg/front_end/lib/src/source/source_builder_factory.dart b/pkg/front_end/lib/src/source/source_builder_factory.dart
index fbde17f..8b89d19 100644
--- a/pkg/front_end/lib/src/source/source_builder_factory.dart
+++ b/pkg/front_end/lib/src/source/source_builder_factory.dart
@@ -2197,10 +2197,10 @@
fragment.builder.becomeNative(loader);
}
for (GetterFragment fragment in _nativeGetterFragments) {
- fragment.becomeNative(loader);
+ fragment.declaration.becomeNative(loader);
}
for (SetterFragment fragment in _nativeSetterFragments) {
- fragment.becomeNative(loader);
+ fragment.declaration.becomeNative(loader);
}
for (MethodFragment fragment in _nativeMethodFragments) {
fragment.becomeNative(loader);
diff --git a/pkg/front_end/lib/src/source/source_property_builder.dart b/pkg/front_end/lib/src/source/source_property_builder.dart
index 9ffe851..21bf172 100644
--- a/pkg/front_end/lib/src/source/source_property_builder.dart
+++ b/pkg/front_end/lib/src/source/source_property_builder.dart
@@ -18,6 +18,8 @@
import '../builder/property_builder.dart';
import '../builder/type_builder.dart';
import '../fragment/fragment.dart';
+import '../fragment/getter/declaration.dart';
+import '../fragment/setter/declaration.dart';
import '../kernel/augmentation_lowering.dart';
import '../kernel/hierarchy/class_member.dart';
import '../kernel/hierarchy/members_builder.dart';
@@ -54,8 +56,8 @@
/// same name must be augmentations.
// TODO(johnniwinther): Add [_augmentations] field.
FieldDeclaration? _introductoryField;
- GetterFragment? _introductoryGetable;
- SetterFragment? _introductorySetable;
+ GetterDeclaration? _introductoryGetable;
+ SetterDeclaration? _introductorySetable;
Modifiers _modifiers;
@@ -87,11 +89,12 @@
required this.libraryBuilder,
required this.declarationBuilder,
required NameScheme nameScheme,
- required GetterFragment fragment,
+ required GetterDeclaration declaration,
+ required Modifiers modifiers,
required PropertyReferences references})
: _nameScheme = nameScheme,
- _introductoryGetable = fragment,
- _modifiers = fragment.modifiers,
+ _introductoryGetable = declaration,
+ _modifiers = modifiers,
_references = references,
_memberName = nameScheme.getDeclaredName(name);
@@ -102,11 +105,12 @@
required this.libraryBuilder,
required this.declarationBuilder,
required NameScheme nameScheme,
- required SetterFragment fragment,
+ required SetterDeclaration declaration,
+ required Modifiers modifiers,
required PropertyReferences references})
: _nameScheme = nameScheme,
- _introductorySetable = fragment,
- _modifiers = fragment.modifiers,
+ _introductorySetable = declaration,
+ _modifiers = modifiers,
_references = references,
_memberName = nameScheme.getDeclaredName(name);
@@ -435,12 +439,20 @@
],
isClassInstanceMember: isClassInstanceMember,
createFileUriExpression: isAugmented);
- _introductoryGetable?.buildOutlineExpressions(classHierarchy,
- libraryBuilder, declarationBuilder, readTarget as Annotatable,
+ _introductoryGetable?.buildOutlineExpressions(
+ classHierarchy: classHierarchy,
+ libraryBuilder: libraryBuilder,
+ declarationBuilder: declarationBuilder,
+ propertyBuilder: this,
+ annotatable: readTarget as Annotatable,
isClassInstanceMember: isClassInstanceMember,
createFileUriExpression: isAugmented);
- _introductorySetable?.buildOutlineExpressions(classHierarchy,
- libraryBuilder, declarationBuilder, writeTarget as Annotatable,
+ _introductorySetable?.buildOutlineExpressions(
+ classHierarchy: classHierarchy,
+ libraryBuilder: libraryBuilder,
+ declarationBuilder: declarationBuilder,
+ propertyBuilder: this,
+ annotatable: writeTarget as Annotatable,
isClassInstanceMember: isClassInstanceMember,
createFileUriExpression: isAugmented);
List<SourcePropertyBuilder>? getterAugmentations = _getterAugmentations;
@@ -619,8 +631,7 @@
// Coverage-ignore(suite): Not run.
List<FormalParameterBuilder>? get formalsForTesting =>
- _introductoryGetable?.formalsForTesting ??
- _introductorySetable?.formalsForTesting;
+ _introductoryGetable?.formals ?? _introductorySetable?.formals;
// Coverage-ignore(suite): Not run.
TypeBuilder? get returnTypeForTesting =>
@@ -684,9 +695,15 @@
_introductoryField?.ensureTypes(_classMembersBuilder!,
_getterOverrideDependencies, _setterOverrideDependencies);
_introductoryGetable?.ensureTypes(
- _classMembersBuilder!, _getterOverrideDependencies);
+ libraryBuilder: libraryBuilder,
+ declarationBuilder: declarationBuilder,
+ membersBuilder: _classMembersBuilder!,
+ getterOverrideDependencies: _getterOverrideDependencies);
_introductorySetable?.ensureTypes(
- _classMembersBuilder!, _setterOverrideDependencies);
+ libraryBuilder: libraryBuilder,
+ declarationBuilder: declarationBuilder,
+ membersBuilder: _classMembersBuilder!,
+ setterOverrideDependencies: _setterOverrideDependencies);
_getterOverrideDependencies = null;
_setterOverrideDependencies = null;
_classMembersBuilder = null;
@@ -793,12 +810,12 @@
class _GetterClassMember implements ClassMember {
final SourcePropertyBuilder _builder;
- final GetterFragment _fragment;
+ final GetterDeclaration _declaration;
- _GetterClassMember(this._builder, this._fragment);
+ _GetterClassMember(this._builder, this._declaration);
@override
- int get charOffset => _fragment.nameOffset;
+ int get charOffset => _declaration.nameOffset;
@override
DeclarationBuilder get declarationBuilder => _builder.declarationBuilder!;
@@ -809,7 +826,7 @@
throw new UnsupportedError('$runtimeType.declarations');
@override
- Uri get fileUri => _fragment.fileUri;
+ Uri get fileUri => _declaration.fileUri;
@override
bool get forSetter => false;
@@ -872,7 +889,7 @@
// property can have a non-abstract getter and an abstract setter or the
// reverse. With augmentations, abstract introductory declarations might even
// be implemented by augmentations.
- bool get isAbstract => _fragment.modifiers.isAbstract;
+ bool get isAbstract => _declaration.isAbstract;
@override
bool get isDuplicate => _builder.isDuplicate;
@@ -915,7 +932,7 @@
bool get isSourceDeclaration => true;
@override
- bool get isStatic => _fragment.modifiers.isStatic;
+ bool get isStatic => _builder.isStatic;
@override
bool get isSynthesized => false;
@@ -939,14 +956,14 @@
class _SetterClassMember implements ClassMember {
final SourcePropertyBuilder _builder;
- final SetterFragment _fragment;
+ final SetterDeclaration _declaration;
late final Covariance _covariance =
new Covariance.fromSetter(_builder.writeTarget as Procedure);
- _SetterClassMember(this._builder, this._fragment);
+ _SetterClassMember(this._builder, this._declaration);
@override
- int get charOffset => _fragment.nameOffset;
+ int get charOffset => _declaration.nameOffset;
@override
DeclarationBuilder get declarationBuilder => _builder.declarationBuilder!;
@@ -957,7 +974,7 @@
throw new UnsupportedError('$runtimeType.declarations');
@override
- Uri get fileUri => _fragment.fileUri;
+ Uri get fileUri => _declaration.fileUri;
@override
bool get forSetter => true;
@@ -1020,7 +1037,7 @@
// property can have a non-abstract getter and an abstract setter or the
// reverse. With augmentations, abstract introductory declarations might even
// be implemented by augmentations.
- bool get isAbstract => _fragment.modifiers.isAbstract;
+ bool get isAbstract => _declaration.isAbstract;
@override
bool get isDuplicate => _builder.isDuplicate;
@@ -1062,7 +1079,7 @@
bool get isSourceDeclaration => true;
@override
- bool get isStatic => _fragment.modifiers.isStatic;
+ bool get isStatic => _builder.isStatic;
@override
bool get isSynthesized => false;
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index d61c459..5058aac 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
+import 'package:front_end/src/fragment/getter/declaration.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/reference_from_index.dart';
@@ -22,6 +23,7 @@
import '../builder/type_builder.dart';
import '../fragment/constructor/declaration.dart';
import '../fragment/fragment.dart';
+import '../fragment/setter/declaration.dart';
import 'builder_factory.dart';
import 'name_scheme.dart';
import 'source_class_builder.dart';
@@ -1546,6 +1548,8 @@
final bool isInstanceMember = containerType != ContainerType.Library &&
!fragment.modifiers.isStatic;
+ Modifiers modifiers = fragment.modifiers;
+
PropertyEncodingStrategy propertyEncodingStrategy =
new PropertyEncodingStrategy(declarationBuilder,
isInstanceMember: isInstanceMember);
@@ -1568,6 +1572,8 @@
name, nameScheme, indexedContainer,
isAugmentation: isAugmentation);
+ GetterDeclaration declaration = new GetterDeclarationImpl(fragment);
+
SourcePropertyBuilder propertyBuilder =
new SourcePropertyBuilder.forGetter(
fileUri: fragment.fileUri,
@@ -1575,10 +1581,12 @@
name: name,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
- fragment: fragment,
+ declaration: declaration,
+ modifiers: modifiers,
nameScheme: nameScheme,
references: references);
- fragment.setBuilder(problemReporting, propertyBuilder,
+ fragment.builder = propertyBuilder;
+ declaration.createEncoding(problemReporting, propertyBuilder,
propertyEncodingStrategy, unboundNominalParameters);
builders.add(new _AddBuilder(fragment.name, propertyBuilder,
fragment.fileUri, fragment.nameOffset,
@@ -1590,6 +1598,8 @@
final bool isInstanceMember = containerType != ContainerType.Library &&
!fragment.modifiers.isStatic;
+ Modifiers modifiers = fragment.modifiers;
+
PropertyEncodingStrategy propertyEncodingStrategy =
new PropertyEncodingStrategy(declarationBuilder,
isInstanceMember: isInstanceMember);
@@ -1612,6 +1622,8 @@
name, nameScheme, indexedContainer,
isAugmentation: isAugmentation);
+ SetterDeclaration declaration = new SetterDeclarationImpl(fragment);
+
SourcePropertyBuilder propertyBuilder =
new SourcePropertyBuilder.forSetter(
fileUri: fragment.fileUri,
@@ -1619,10 +1631,12 @@
name: name,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
- fragment: fragment,
+ declaration: declaration,
+ modifiers: modifiers,
nameScheme: nameScheme,
references: references);
- fragment.setBuilder(problemReporting, propertyBuilder,
+ fragment.builder = propertyBuilder;
+ declaration.createEncoding(problemReporting, propertyBuilder,
propertyEncodingStrategy, unboundNominalParameters);
builders.add(new _AddBuilder(fragment.name, propertyBuilder,
fragment.fileUri, fragment.nameOffset,
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index 823e946..d5bb70f 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -540,7 +540,22 @@
),
// 100.0%.
"package:front_end/src/fragment/getter.dart": (
- hitCount: 530,
+ hitCount: 48,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/getter/body_builder_context.dart": (
+ hitCount: 50,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/getter/declaration.dart": (
+ hitCount: 110,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/getter/encoding.dart": (
+ hitCount: 374,
missCount: 0,
),
// 100.0%.
@@ -565,7 +580,22 @@
),
// 100.0%.
"package:front_end/src/fragment/setter.dart": (
- hitCount: 550,
+ hitCount: 48,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/setter/body_builder_context.dart": (
+ hitCount: 48,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/setter/declaration.dart": (
+ hitCount: 107,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/setter/encoding.dart": (
+ hitCount: 399,
missCount: 0,
),
// 100.0%.
@@ -855,7 +885,7 @@
),
// 100.0%.
"package:front_end/src/source/source_builder_factory.dart": (
- hitCount: 1191,
+ hitCount: 1193,
missCount: 0,
),
// 100.0%.
@@ -926,7 +956,7 @@
),
// 100.0%.
"package:front_end/src/source/source_property_builder.dart": (
- hitCount: 698,
+ hitCount: 696,
missCount: 0,
),
// 100.0%.
@@ -946,7 +976,7 @@
),
// 100.0%.
"package:front_end/src/source/type_parameter_scope_builder.dart": (
- hitCount: 1591,
+ hitCount: 1597,
missCount: 0,
),
// 100.0%.
diff --git a/pkg/vm/lib/transformations/dynamic_interface_annotator.dart b/pkg/vm/lib/transformations/dynamic_interface_annotator.dart
index c143487..c8582e9 100644
--- a/pkg/vm/lib/transformations/dynamic_interface_annotator.dart
+++ b/pkg/vm/lib/transformations/dynamic_interface_annotator.dart
@@ -152,6 +152,16 @@
c.accept(this);
}
}
+ for (final ext in node.extensions) {
+ if (ext.name[0] != '_') {
+ ext.accept(this);
+ }
+ }
+ for (final extensionType in node.extensionTypeDeclarations) {
+ if (extensionType.name[0] != '_') {
+ extensionType.accept(this);
+ }
+ }
for (final exportRef in node.additionalExports) {
exportRef.node!.accept(this);
}
@@ -207,6 +217,34 @@
node.addAnnotation(ConstantExpression(pragma));
}
}
+
+ @override
+ void visitExtension(Extension node) {
+ for (final md in node.memberDescriptors) {
+ final member = md.memberReference?.node;
+ if (member != null) {
+ annotateMember(member as Member);
+ }
+ final tearOff = md.tearOffReference?.node;
+ if (tearOff != null) {
+ annotateMember(tearOff as Member);
+ }
+ }
+ }
+
+ @override
+ void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) {
+ for (final md in node.memberDescriptors) {
+ final member = md.memberReference?.node;
+ if (member != null) {
+ annotateMember(member as Member);
+ }
+ final tearOff = md.tearOffReference?.node;
+ if (tearOff != null) {
+ annotateMember(tearOff as Member);
+ }
+ }
+ }
}
class _ImplicitExtendableAnnotator {
diff --git a/pkg/vm/testcases/transformations/dynamic_interface_annotator/dynamic_interface.yaml b/pkg/vm/testcases/transformations/dynamic_interface_annotator/dynamic_interface.yaml
index fb9265b..8215721 100644
--- a/pkg/vm/testcases/transformations/dynamic_interface_annotator/dynamic_interface.yaml
+++ b/pkg/vm/testcases/transformations/dynamic_interface_annotator/dynamic_interface.yaml
@@ -9,12 +9,14 @@
member: sfield9
- library: 'lib3.dart'
class: ['A', 'B']
+ - library: 'lib4.dart'
- library: 'prefix/lib*'
extendable:
- library: 'lib1.dart'
class: ['A', 'O', 'Q', 'S', 'T', 'V']
- library: 'lib2.dart'
+ - library: 'lib4.dart'
can-be-overridden:
- library: 'lib1.dart'
@@ -22,3 +24,4 @@
- library: 'lib2.dart'
class: 'D'
member: 'build'
+ - library: 'lib4.dart'
diff --git a/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib4.dart b/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib4.dart
new file mode 100644
index 0000000..c122b97
--- /dev/null
+++ b/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib4.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'lib5.dart';
+
+extension type E3(int _info) {
+ int get info => _info;
+}
+
+extension type _E4(int _info) {
+ int get info => _info;
+}
+
+extension E5 on String {
+ String addSuffix1(String suffix) => this + suffix;
+}
+
+extension _E6 on String {
+ String addSuffix2(String suffix) => this + suffix;
+}
+
+extension on String {
+ String addSuffix3(String suffix) => this + suffix;
+}
diff --git a/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib4.dart.expect b/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib4.dart.expect
new file mode 100644
index 0000000..e706547
--- /dev/null
+++ b/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib4.dart.expect
@@ -0,0 +1,71 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "lib5.dart" as lib5;
+additionalExports = (lib5::E1,
+ lib5::E2)
+
+export "file:pkg/vm/testcases/transformations/dynamic_interface_annotator/lib5.dart";
+
+extension E5 on core::String {
+ method addSuffix1 = self::E5|addSuffix1;
+ method tearoff addSuffix1 = self::E5|get#addSuffix1;
+}
+extension _E6 on core::String {
+ method addSuffix2 = self::_E6|addSuffix2;
+ method tearoff addSuffix2 = self::_E6|get#addSuffix2;
+}
+extension /* unnamed */ _extension#2 on core::String {
+ method addSuffix3 = self::_extension#2|addSuffix3;
+ method tearoff addSuffix3 = self::_extension#2|get#addSuffix3;
+}
+extension type E3(core::int _info) {
+ abstract extension-type-member representation-field get _info() → core::int;
+ get info = self::E3|get#info;
+ constructor • = self::E3|constructor#;
+ constructor tearoff • = self::E3|constructor#_#new#tearOff;
+}
+extension type _E4(core::int _info) {
+ abstract extension-type-member representation-field get _info() → core::int;
+ get info = self::_E4|get#info;
+ constructor • = self::_E4|constructor#;
+ constructor tearoff • = self::_E4|constructor#_#new#tearOff;
+}
+@#C3
+static extension-type-member method E3|constructor#(core::int _info) → self::E3% /* erasure=core::int, declared=! */ {
+ lowered final self::E3% /* erasure=core::int, declared=! */ #this = _info;
+ return #this;
+}
+@#C3
+static extension-type-member method E3|constructor#_#new#tearOff(core::int _info) → self::E3% /* erasure=core::int, declared=! */
+ return self::E3|constructor#(_info);
+@#C3
+static extension-type-member method E3|get#info(lowered final self::E3% /* erasure=core::int, declared=! */ #this) → core::int
+ return #this as{Unchecked} core::int;
+static extension-type-member method _E4|constructor#(core::int _info) → self::_E4% /* erasure=core::int, declared=! */ {
+ lowered final self::_E4% /* erasure=core::int, declared=! */ #this = _info;
+ return #this;
+}
+static extension-type-member method _E4|constructor#_#new#tearOff(core::int _info) → self::_E4% /* erasure=core::int, declared=! */
+ return self::_E4|constructor#(_info);
+static extension-type-member method _E4|get#info(lowered final self::_E4% /* erasure=core::int, declared=! */ #this) → core::int
+ return #this as{Unchecked} core::int;
+@#C3
+static extension-member method E5|addSuffix1(lowered final core::String #this, core::String suffix) → core::String
+ return #this.{core::String::+}(suffix){(core::String) → core::String};
+@#C3
+static extension-member method E5|get#addSuffix1(lowered final core::String #this) → (core::String) → core::String
+ return (core::String suffix) → core::String => self::E5|addSuffix1(#this, suffix);
+static extension-member method _E6|addSuffix2(lowered final core::String #this, core::String suffix) → core::String
+ return #this.{core::String::+}(suffix){(core::String) → core::String};
+static extension-member method _E6|get#addSuffix2(lowered final core::String #this) → (core::String) → core::String
+ return (core::String suffix) → core::String => self::_E6|addSuffix2(#this, suffix);
+static extension-member method _extension#2|addSuffix3(lowered final core::String #this, core::String suffix) → core::String
+ return #this.{core::String::+}(suffix){(core::String) → core::String};
+static extension-member method _extension#2|get#addSuffix3(lowered final core::String #this) → (core::String) → core::String
+ return (core::String suffix) → core::String => self::_extension#2|addSuffix3(#this, suffix);
+constants {
+ #C1 = "dyn-module:callable"
+ #C2 = null
+ #C3 = core::pragma {name:#C1, options:#C2}
+}
diff --git a/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib5.dart b/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib5.dart
new file mode 100644
index 0000000..260a269
--- /dev/null
+++ b/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib5.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension type E1._(int _info) {
+ int get info => _info;
+}
+
+extension E2 on String {
+ int get lastChar => codeUnitAt(length - 1);
+}
diff --git a/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib5.dart.expect b/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib5.dart.expect
new file mode 100644
index 0000000..14b118a
--- /dev/null
+++ b/pkg/vm/testcases/transformations/dynamic_interface_annotator/lib5.dart.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+extension E2 on core::String {
+ get lastChar = self::E2|get#lastChar;
+}
+extension type E1(core::int _info) {
+ abstract extension-type-member representation-field get _info() → core::int;
+ get info = self::E1|get#info;
+ constructor _ = self::E1|constructor#_;
+ constructor tearoff _ = self::E1|constructor#_#_#tearOff;
+}
+@#C3
+static extension-type-member method E1|constructor#_(core::int _info) → self::E1% /* erasure=core::int, declared=! */ {
+ lowered final self::E1% /* erasure=core::int, declared=! */ #this = _info;
+ return #this;
+}
+@#C3
+static extension-type-member method E1|constructor#_#_#tearOff(core::int _info) → self::E1% /* erasure=core::int, declared=! */
+ return self::E1|constructor#_(_info);
+@#C3
+static extension-type-member method E1|get#info(lowered final self::E1% /* erasure=core::int, declared=! */ #this) → core::int
+ return #this as{Unchecked} core::int;
+@#C3
+static extension-member method E2|get#lastChar(lowered final core::String #this) → core::int
+ return #this.{core::String::codeUnitAt}(#this.{core::String::length}{core::int}.{core::num::-}(1){(core::num) → core::int}){(core::int) → core::int};
+constants {
+ #C1 = "dyn-module:callable"
+ #C2 = null
+ #C3 = core::pragma {name:#C1, options:#C2}
+}
diff --git a/pkg/vm/testcases/transformations/dynamic_interface_annotator/main.dart b/pkg/vm/testcases/transformations/dynamic_interface_annotator/main.dart
index b97c769..a3b8a2f 100644
--- a/pkg/vm/testcases/transformations/dynamic_interface_annotator/main.dart
+++ b/pkg/vm/testcases/transformations/dynamic_interface_annotator/main.dart
@@ -5,6 +5,7 @@
import 'lib1.dart';
import 'lib2.dart';
import 'lib3.dart';
+import 'lib4.dart';
import 'prefix/lib1.dart';
import 'prefix/lib2.dart';
diff --git a/pkg/vm/testcases/transformations/dynamic_interface_annotator/main.dart.expect b/pkg/vm/testcases/transformations/dynamic_interface_annotator/main.dart.expect
index 7693a91..0795e10 100644
--- a/pkg/vm/testcases/transformations/dynamic_interface_annotator/main.dart.expect
+++ b/pkg/vm/testcases/transformations/dynamic_interface_annotator/main.dart.expect
@@ -4,6 +4,7 @@
import "file:pkg/vm/testcases/transformations/dynamic_interface_annotator/lib1.dart";
import "file:pkg/vm/testcases/transformations/dynamic_interface_annotator/lib2.dart";
import "file:pkg/vm/testcases/transformations/dynamic_interface_annotator/lib3.dart";
+import "file:pkg/vm/testcases/transformations/dynamic_interface_annotator/lib4.dart";
import "file:pkg/vm/testcases/transformations/dynamic_interface_annotator/prefix/lib1.dart";
import "file:pkg/vm/testcases/transformations/dynamic_interface_annotator/prefix/lib2.dart";
diff --git a/tools/VERSION b/tools/VERSION
index 8e22385..2984863 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 3
MINOR 8
PATCH 0
-PRERELEASE 206
+PRERELEASE 207
PRERELEASE_PATCH 0