[cfe] Patch declarations through fragments
Change-Id: I942f2b0b08e69012140d4671722411c86b073504
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/413681
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/base/name_space.dart b/pkg/front_end/lib/src/base/name_space.dart
index 0410f0a..0f06f34 100644
--- a/pkg/front_end/lib/src/base/name_space.dart
+++ b/pkg/front_end/lib/src/base/name_space.dart
@@ -172,6 +172,7 @@
}
@override
+ // Coverage-ignore(suite): Not run.
void forEachLocalMember(void Function(String name, Builder member) f) {
if (_getables != null) {
for (MapEntry<String, Builder> entry in _getables!.entries) {
@@ -181,6 +182,7 @@
}
@override
+ // Coverage-ignore(suite): Not run.
void forEachLocalSetter(void Function(String name, MemberBuilder member) f) {
if (_setables != null) {
for (MapEntry<String, MemberBuilder> entry in _setables!.entries) {
diff --git a/pkg/front_end/lib/src/base/scope.dart b/pkg/front_end/lib/src/base/scope.dart
index 0fe5faa..f59d26a 100644
--- a/pkg/front_end/lib/src/base/scope.dart
+++ b/pkg/front_end/lib/src/base/scope.dart
@@ -19,12 +19,8 @@
import '../kernel/type_algorithms.dart';
import '../source/source_class_builder.dart';
import '../source/source_extension_builder.dart';
-import '../source/source_extension_type_declaration_builder.dart';
-import '../source/source_function_builder.dart';
import '../source/source_library_builder.dart';
import '../source/source_member_builder.dart';
-import '../source/source_method_builder.dart';
-import '../source/source_property_builder.dart';
import 'messages.dart';
import 'name_space.dart';
import 'uri_offset.dart';
@@ -1228,354 +1224,7 @@
}
}
-abstract class MergedScope<T extends Builder> {
- final T _origin;
- final NameSpace _originNameSpace;
- Map<T, NameSpace> _augmentationNameSpaces = {};
-
- MergedScope(this._origin, this._originNameSpace);
-
- SourceLibraryBuilder get originLibrary;
-
- // Coverage-ignore(suite): Not run.
- void _addBuilderToMergedScope(
- String name, Builder newBuilder, Builder? existingBuilder,
- {required bool setter, required bool inPatchLibrary}) {
- bool isAugmentationBuilder = inPatchLibrary
- ? newBuilder.hasPatchAnnotation
- : newBuilder.isAugmentation;
- if (existingBuilder != null) {
- if (isAugmentationBuilder) {
- existingBuilder.applyAugmentation(newBuilder);
- } else {
- newBuilder.isConflictingAugmentationMember = true;
- Message message;
- Message context;
- if (newBuilder is SourceMemberBuilder &&
- existingBuilder is SourceMemberBuilder) {
- if (_origin is SourceLibraryBuilder) {
- message = inPatchLibrary
- ? templateNonPatchLibraryMemberConflict.withArguments(name)
- : templateNonAugmentationLibraryMemberConflict
- .withArguments(name);
- } else {
- message = inPatchLibrary
- ? templateNonPatchClassMemberConflict.withArguments(name)
- : templateNonAugmentationClassMemberConflict
- .withArguments(name);
- }
- context = messageNonAugmentationMemberConflictCause;
- } else if (newBuilder is SourceClassBuilder &&
- existingBuilder is SourceClassBuilder) {
- message = inPatchLibrary
- ? templateNonPatchClassConflict.withArguments(name)
- : templateNonAugmentationClassConflict.withArguments(name);
- context = messageNonAugmentationClassConflictCause;
- } else {
- if (_origin is SourceLibraryBuilder) {
- message = inPatchLibrary
- ? templateNonPatchLibraryConflict.withArguments(name)
- : templateNonAugmentationLibraryConflict.withArguments(name);
- } else {
- message = inPatchLibrary
- ? templateNonPatchClassMemberConflict.withArguments(name)
- : templateNonAugmentationClassMemberConflict
- .withArguments(name);
- }
- context = messageNonAugmentationMemberConflictCause;
- }
- originLibrary.addProblem(
- message, newBuilder.fileOffset, name.length, newBuilder.fileUri,
- context: [
- context.withLocation(existingBuilder.fileUri!,
- existingBuilder.fileOffset, name.length)
- ]);
- }
- } else {
- if (isAugmentationBuilder) {
- Message message;
- if (newBuilder is SourceMemberBuilder) {
- if (_origin is SourceLibraryBuilder) {
- message = inPatchLibrary
- ? templateUnmatchedPatchLibraryMember.withArguments(name)
- : templateUnmatchedAugmentationLibraryMember
- .withArguments(name);
- } else {
- message = inPatchLibrary
- ? templateUnmatchedPatchClassMember.withArguments(name)
- : templateUnmatchedAugmentationClassMember.withArguments(name);
- }
- } else if (newBuilder is SourceClassBuilder) {
- message = inPatchLibrary
- ? templateUnmatchedPatchClass.withArguments(name)
- : templateUnmatchedAugmentationClass.withArguments(name);
- } else {
- message = inPatchLibrary
- ? templateUnmatchedPatchDeclaration.withArguments(name)
- : templateUnmatchedAugmentationDeclaration.withArguments(name);
- }
- originLibrary.addProblem(
- message, newBuilder.fileOffset, name.length, newBuilder.fileUri);
- } else {
- if (inPatchLibrary &&
- !name.startsWith('_') &&
- !_allowInjectedPublicMember(newBuilder)) {
- originLibrary.addProblem(
- templatePatchInjectionFailed.withArguments(
- name, originLibrary.importUri),
- newBuilder.fileOffset,
- noLength,
- newBuilder.fileUri);
- }
- _originNameSpace.addLocalMember(name, newBuilder, setter: setter);
- if (newBuilder is ExtensionBuilder) {
- _originNameSpace.addExtension(newBuilder);
- }
- for (NameSpace augmentationNameSpace
- in _augmentationNameSpaces.values) {
- _addBuilderToAugmentationNameSpace(
- augmentationNameSpace, name, newBuilder,
- setter: setter);
- }
- }
- }
- }
-
- void _addBuilderToAugmentationNameSpace(
- NameSpace augmentationNameSpace, String name, Builder member,
- {required bool setter}) {
- Builder? augmentationMember =
- augmentationNameSpace.lookupLocalMember(name, setter: setter);
- if (augmentationMember == null) {
- augmentationNameSpace.addLocalMember(name, member, setter: setter);
- if (member is ExtensionBuilder) {
- // Coverage-ignore-block(suite): Not run.
- augmentationNameSpace.addExtension(member);
- }
- }
- }
-
- void _addAugmentationScope(T parentBuilder, NameSpace nameSpace,
- {required Map<String, List<Builder>>? augmentations,
- required Map<String, List<Builder>>? setterAugmentations,
- required bool inPatchLibrary}) {
- // TODO(johnniwinther): Use `scope.filteredNameIterator` instead of
- // `scope.forEachLocalMember`/`scope.forEachLocalSetter`.
-
- // Include all augmentation scope members to the origin scope.
- nameSpace.forEachLocalMember(
- // Coverage-ignore(suite): Not run.
- (String name, Builder member) {
- // In case of duplicates we use the first declaration.
- while (member.isDuplicate) {
- member = member.next!;
- }
- _addBuilderToMergedScope(
- name, member, _originNameSpace.lookupLocalMember(name, setter: false),
- setter: false, inPatchLibrary: inPatchLibrary);
- });
- if (augmentations != null) {
- // Coverage-ignore-block(suite): Not run.
- for (String augmentedName in augmentations.keys) {
- for (Builder augmentation in augmentations[augmentedName]!) {
- _addBuilderToMergedScope(augmentedName, augmentation,
- _originNameSpace.lookupLocalMember(augmentedName, setter: false),
- setter: false, inPatchLibrary: inPatchLibrary);
- }
- }
- }
- nameSpace.forEachLocalSetter(
- // Coverage-ignore(suite): Not run.
- (String name, Builder member) {
- // In case of duplicates we use the first declaration.
- while (member.isDuplicate) {
- member = member.next!;
- }
- _addBuilderToMergedScope(
- name, member, _originNameSpace.lookupLocalMember(name, setter: true),
- setter: true, inPatchLibrary: inPatchLibrary);
- });
- if (setterAugmentations != null) {
- // Coverage-ignore-block(suite): Not run.
- for (String augmentedName in setterAugmentations.keys) {
- for (Builder augmentation in setterAugmentations[augmentedName]!) {
- _addBuilderToMergedScope(augmentedName, augmentation,
- _originNameSpace.lookupLocalMember(augmentedName, setter: true),
- setter: true, inPatchLibrary: inPatchLibrary);
- }
- }
- }
- nameSpace.forEachLocalExtension(
- // Coverage-ignore(suite): Not run.
- (ExtensionBuilder extensionBuilder) {
- if (extensionBuilder is SourceExtensionBuilder &&
- extensionBuilder.isUnnamedExtension) {
- _originNameSpace.addExtension(extensionBuilder);
- for (NameSpace augmentationNameSpace
- in _augmentationNameSpaces.values) {
- augmentationNameSpace.addExtension(extensionBuilder);
- }
- }
- });
-
- // Include all origin scope members in the augmentation scope.
- _originNameSpace.forEachLocalMember((String name, Builder originMember) {
- _addBuilderToAugmentationNameSpace(nameSpace, name, originMember,
- setter: false);
- });
- _originNameSpace.forEachLocalSetter((String name, Builder originMember) {
- _addBuilderToAugmentationNameSpace(nameSpace, name, originMember,
- setter: true);
- });
- _originNameSpace.forEachLocalExtension(
- // Coverage-ignore(suite): Not run.
- (ExtensionBuilder extensionBuilder) {
- if (extensionBuilder is SourceExtensionBuilder &&
- extensionBuilder.isUnnamedExtension) {
- nameSpace.addExtension(extensionBuilder);
- }
- });
-
- _augmentationNameSpaces[parentBuilder] = nameSpace;
- }
-
- bool _allowInjectedPublicMember(Builder newBuilder);
-}
-
-class MergedClassMemberScope extends MergedScope<SourceClassBuilder> {
- final DeclarationNameSpace _originConstructorNameSpace;
- Map<SourceClassBuilder, DeclarationNameSpace>
- _augmentationConstructorNameSpaces = {};
-
- MergedClassMemberScope(SourceClassBuilder origin)
- : _originConstructorNameSpace = origin.nameSpace,
- super(origin, origin.nameSpace);
-
- @override
- // Coverage-ignore(suite): Not run.
- SourceLibraryBuilder get originLibrary => _origin.libraryBuilder;
-
- void _addAugmentationConstructorScope(DeclarationNameSpace nameSpace,
- {required bool inPatchLibrary}) {
- nameSpace.forEachConstructor(
- // Coverage-ignore(suite): Not run.
- (String name, MemberBuilder newConstructor) {
- MemberBuilder? existingConstructor =
- _originConstructorNameSpace.lookupConstructor(name);
- bool isAugmentationBuilder = inPatchLibrary
- ? newConstructor.hasPatchAnnotation
- : newConstructor.isAugmentation;
- if (existingConstructor != null) {
- if (isAugmentationBuilder) {
- existingConstructor.applyAugmentation(newConstructor);
- } else {
- newConstructor.isConflictingAugmentationMember = true;
- originLibrary.addProblem(
- inPatchLibrary
- ? templateNonPatchConstructorConflict
- .withArguments(newConstructor.fullNameForErrors)
- : templateNonAugmentationConstructorConflict
- .withArguments(newConstructor.fullNameForErrors),
- newConstructor.fileOffset,
- noLength,
- newConstructor.fileUri,
- context: [
- messageNonAugmentationConstructorConflictCause.withLocation(
- existingConstructor.fileUri!,
- existingConstructor.fileOffset,
- noLength)
- ]);
- }
- } else {
- if (isAugmentationBuilder) {
- originLibrary.addProblem(
- inPatchLibrary
- ? templateUnmatchedPatchConstructor
- .withArguments(newConstructor.fullNameForErrors)
- : templateUnmatchedAugmentationConstructor
- .withArguments(newConstructor.fullNameForErrors),
- newConstructor.fileOffset,
- noLength,
- newConstructor.fileUri);
- } else {
- _originConstructorNameSpace.addConstructor(name, newConstructor);
- for (DeclarationNameSpace augmentationConstructorNameSpace
- in _augmentationConstructorNameSpaces.values) {
- _addConstructorToAugmentationScope(
- augmentationConstructorNameSpace, name, newConstructor);
- }
- }
- if (inPatchLibrary &&
- !name.startsWith('_') &&
- !_allowInjectedPublicMember(newConstructor)) {
- originLibrary.addProblem(
- templatePatchInjectionFailed.withArguments(
- name, originLibrary.importUri),
- newConstructor.fileOffset,
- noLength,
- newConstructor.fileUri);
- }
- }
- });
- _originConstructorNameSpace
- .forEachConstructor((String name, MemberBuilder originConstructor) {
- _addConstructorToAugmentationScope(nameSpace, name, originConstructor);
- });
- }
-
- void _addConstructorToAugmentationScope(
- DeclarationNameSpace augmentationConstructorNameSpace,
- String name,
- MemberBuilder constructor) {
- Builder? augmentationConstructor =
- augmentationConstructorNameSpace.lookupConstructor(name);
- if (augmentationConstructor == null) {
- augmentationConstructorNameSpace.addConstructor(name, constructor);
- }
- }
-
- // TODO(johnniwinther): Check for conflicts between constructors and class
- // members.
- void addAugmentationScope(SourceClassBuilder builder) {
- _addAugmentationScope(builder, builder.nameSpace,
- augmentations: null,
- setterAugmentations: null,
- inPatchLibrary: builder.libraryBuilder.isPatchLibrary);
- _addAugmentationConstructorScope(builder.nameSpace,
- inPatchLibrary: builder.libraryBuilder.isPatchLibrary);
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- bool _allowInjectedPublicMember(Builder newBuilder) {
- if (originLibrary.importUri.isScheme("dart") &&
- originLibrary.importUri.path.startsWith("_")) {
- return true;
- }
- if (newBuilder.isStatic) {
- return _origin.name.startsWith('_');
- }
- // TODO(johnniwinther): Restrict the use of injected public class members.
- return true;
- }
-}
-
extension on Builder {
- // Coverage-ignore(suite): Not run.
- bool get isAugmentation {
- Builder self = this;
- if (self is SourceLibraryBuilder) {
- return self.isAugmentationLibrary;
- } else if (self is SourceClassBuilder) {
- return self.isAugmentation;
- } else if (self is SourceMemberBuilder) {
- return self.isAugmentation;
- } else {
- // TODO(johnniwinther): Handle all cases here.
- return false;
- }
- }
-
bool get isConflictingAugmentationMember {
Builder self = this;
if (self is SourceMemberBuilder) {
@@ -1586,49 +1235,6 @@
// TODO(johnniwinther): Handle all cases here.
return false;
}
-
- // Coverage-ignore(suite): Not run.
- void set isConflictingAugmentationMember(bool value) {
- Builder self = this;
- if (self is SourceMemberBuilder) {
- self.isConflictingAugmentationMember = value;
- } else if (self is SourceClassBuilder) {
- self.isConflictingAugmentationMember = value;
- }
- // TODO(johnniwinther): Handle all cases here.
- }
-
- // Coverage-ignore(suite): Not run.
- bool _hasPatchAnnotation(Iterable<MetadataBuilder>? metadata) {
- if (metadata == null) {
- return false;
- }
- for (MetadataBuilder metadataBuilder in metadata) {
- if (metadataBuilder.hasPatch) {
- return true;
- }
- }
- return false;
- }
-
- // Coverage-ignore(suite): Not run.
- bool get hasPatchAnnotation {
- Builder self = this;
- if (self is SourceFunctionBuilder) {
- return _hasPatchAnnotation(self.metadata);
- } else if (self is SourceClassBuilder) {
- return _hasPatchAnnotation(self.metadata);
- } else if (self is SourceExtensionBuilder) {
- return _hasPatchAnnotation(self.metadata);
- } else if (self is SourcePropertyBuilder) {
- return _hasPatchAnnotation(self.metadata);
- } else if (self is SourceMethodBuilder) {
- return _hasPatchAnnotation(self.metadata);
- } else if (self is SourceExtensionTypeDeclarationBuilder) {
- return _hasPatchAnnotation(self.metadata);
- }
- return false;
- }
}
class IteratorSequence<T> implements Iterator<T> {
diff --git a/pkg/front_end/lib/src/fragment/class/declaration.dart b/pkg/front_end/lib/src/fragment/class/declaration.dart
index 6d867e5..e5b0616 100644
--- a/pkg/front_end/lib/src/fragment/class/declaration.dart
+++ b/pkg/front_end/lib/src/fragment/class/declaration.dart
@@ -23,8 +23,11 @@
void buildOutlineExpressions(
{required Annotatable annotatable,
required SourceLibraryBuilder libraryBuilder,
+ required ClassHierarchy classHierarchy,
required BodyBuilderContext bodyBuilderContext,
required bool createFileUriExpression});
+
+ int resolveConstructorReferences(SourceLibraryBuilder libraryBuilder);
}
class RegularClassDeclaration implements ClassDeclaration {
@@ -77,6 +80,7 @@
void buildOutlineExpressions(
{required Annotatable annotatable,
required SourceLibraryBuilder libraryBuilder,
+ required ClassHierarchy classHierarchy,
required BodyBuilderContext bodyBuilderContext,
required bool createFileUriExpression}) {
MetadataBuilder.buildAnnotations(
@@ -87,6 +91,21 @@
_fragment.fileUri,
_fragment.enclosingScope,
createFileUriExpression: createFileUriExpression);
+
+ if (typeParameters != null) {
+ for (int i = 0; i < typeParameters!.length; i++) {
+ typeParameters![i].buildOutlineExpressions(libraryBuilder,
+ bodyBuilderContext, classHierarchy, _fragment.typeParameterScope);
+ }
+ }
+ }
+
+ @override
+ int resolveConstructorReferences(SourceLibraryBuilder libraryBuilder) {
+ for (ConstructorReferenceBuilder ref in _fragment.constructorReferences) {
+ ref.resolveIn(bodyScope, libraryBuilder);
+ }
+ return _fragment.constructorReferences.length;
}
}
@@ -140,6 +159,7 @@
void buildOutlineExpressions(
{required Annotatable annotatable,
required SourceLibraryBuilder libraryBuilder,
+ required ClassHierarchy classHierarchy,
required BodyBuilderContext bodyBuilderContext,
required bool createFileUriExpression}) {
MetadataBuilder.buildAnnotations(
@@ -150,6 +170,21 @@
_fragment.fileUri,
_fragment.enclosingScope,
createFileUriExpression: createFileUriExpression);
+
+ if (typeParameters != null) {
+ for (int i = 0; i < typeParameters!.length; i++) {
+ typeParameters![i].buildOutlineExpressions(libraryBuilder,
+ bodyBuilderContext, classHierarchy, _fragment.typeParameterScope);
+ }
+ }
+ }
+
+ @override
+ int resolveConstructorReferences(SourceLibraryBuilder libraryBuilder) {
+ for (ConstructorReferenceBuilder ref in _fragment.constructorReferences) {
+ ref.resolveIn(bodyScope, libraryBuilder);
+ }
+ return _fragment.constructorReferences.length;
}
}
@@ -204,6 +239,7 @@
void buildOutlineExpressions(
{required Annotatable annotatable,
required SourceLibraryBuilder libraryBuilder,
+ required ClassHierarchy classHierarchy,
required BodyBuilderContext bodyBuilderContext,
required bool createFileUriExpression}) {
MetadataBuilder.buildAnnotations(
@@ -214,6 +250,18 @@
_fragment.fileUri,
_fragment.enclosingScope,
createFileUriExpression: createFileUriExpression);
+
+ if (typeParameters != null) {
+ for (int i = 0; i < typeParameters!.length; i++) {
+ typeParameters![i].buildOutlineExpressions(libraryBuilder,
+ bodyBuilderContext, classHierarchy, _fragment.typeParameterScope);
+ }
+ }
+ }
+
+ @override
+ int resolveConstructorReferences(SourceLibraryBuilder libraryBuilder) {
+ return 0;
}
}
@@ -274,8 +322,14 @@
void buildOutlineExpressions(
{required Annotatable annotatable,
required SourceLibraryBuilder libraryBuilder,
+ required ClassHierarchy classHierarchy,
required BodyBuilderContext bodyBuilderContext,
required bool createFileUriExpression}) {}
+
+ @override
+ int resolveConstructorReferences(SourceLibraryBuilder libraryBuilder) {
+ return 0;
+ }
}
class MixinDeclaration implements ClassDeclaration {
@@ -329,6 +383,7 @@
void buildOutlineExpressions(
{required Annotatable annotatable,
required SourceLibraryBuilder libraryBuilder,
+ required ClassHierarchy classHierarchy,
required BodyBuilderContext bodyBuilderContext,
required bool createFileUriExpression}) {
MetadataBuilder.buildAnnotations(
@@ -339,5 +394,21 @@
_fragment.fileUri,
_fragment.enclosingScope,
createFileUriExpression: createFileUriExpression);
+
+ if (typeParameters != null) {
+ for (int i = 0; i < typeParameters!.length; i++) {
+ typeParameters![i].buildOutlineExpressions(libraryBuilder,
+ bodyBuilderContext, classHierarchy, _fragment.typeParameterScope);
+ }
+ }
+ }
+
+ @override
+ int resolveConstructorReferences(SourceLibraryBuilder libraryBuilder) {
+ for (ConstructorReferenceBuilder ref in _fragment.constructorReferences) {
+ // Coverage-ignore-block(suite): Not run.
+ ref.resolveIn(bodyScope, libraryBuilder);
+ }
+ return _fragment.constructorReferences.length;
}
}
diff --git a/pkg/front_end/lib/src/fragment/named_mixin_application.dart b/pkg/front_end/lib/src/fragment/named_mixin_application.dart
index 49dc3e1..a1c1ca5 100644
--- a/pkg/front_end/lib/src/fragment/named_mixin_application.dart
+++ b/pkg/front_end/lib/src/fragment/named_mixin_application.dart
@@ -15,6 +15,7 @@
final Modifiers modifiers;
final List<MetadataBuilder>? metadata;
final List<TypeParameterFragment>? typeParameters;
+ final LookupScope typeParameterScope;
final TypeBuilder? supertype;
final List<TypeBuilder> mixins;
final List<TypeBuilder>? interfaces;
@@ -32,6 +33,7 @@
required this.modifiers,
required this.metadata,
required this.typeParameters,
+ required this.typeParameterScope,
required this.supertype,
required this.mixins,
required this.interfaces,
diff --git a/pkg/front_end/lib/src/source/builder_factory.dart b/pkg/front_end/lib/src/source/builder_factory.dart
index 521d669..21cbb25 100644
--- a/pkg/front_end/lib/src/source/builder_factory.dart
+++ b/pkg/front_end/lib/src/source/builder_factory.dart
@@ -13,6 +13,7 @@
import '../base/identifiers.dart' show Identifier;
import '../base/import.dart';
import '../base/modifiers.dart';
+import '../base/scope.dart';
import '../builder/constructor_reference_builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/formal_parameter_builder.dart';
@@ -97,7 +98,10 @@
void beginNamedMixinApplication(
String name, int charOffset, List<TypeParameterFragment>? typeParameters);
- void endNamedMixinApplication(String name);
+ // TODO(johnniwinther): Avoid returning the type parameter scope here. Should
+ // named mixin applications be created in the begin method, similar to the
+ // other declarations?
+ LookupScope endNamedMixinApplication(String name);
void endNamedMixinApplicationForParserRecovery(
List<TypeParameterFragment>? typeParameters);
diff --git a/pkg/front_end/lib/src/source/class_declaration.dart b/pkg/front_end/lib/src/source/class_declaration.dart
index 8a61f11..478c841 100644
--- a/pkg/front_end/lib/src/source/class_declaration.dart
+++ b/pkg/front_end/lib/src/source/class_declaration.dart
@@ -2,14 +2,10 @@
// 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 '../base/problems.dart';
-import '../base/scope.dart';
import '../builder/builder.dart';
-import '../builder/constructor_reference_builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/member_builder.dart';
import '../builder/name_iterator.dart';
-import 'source_factory_builder.dart';
import 'source_library_builder.dart';
/// Common interface for builders for a class declarations in source code, such
@@ -83,52 +79,6 @@
Iterator<T> localConstructorIterator<T extends MemberBuilder>();
}
-mixin ClassDeclarationBuilderMixin implements ClassDeclarationBuilder {
- List<ConstructorReferenceBuilder> get constructorReferences;
-
- List<ClassDeclarationBuilderMixin>? get augmentations;
-
- LookupScope get bodyScope;
-
- int resolveConstructorReferences(SourceLibraryBuilder library) {
- int count = 0;
- if (constructorReferences.isNotEmpty) {
- for (ConstructorReferenceBuilder ref in constructorReferences) {
- ref.resolveIn(bodyScope, library);
- }
- }
- List<ClassDeclarationBuilderMixin>? augmentations = this.augmentations;
- if (augmentations != null) {
- for (ClassDeclarationBuilderMixin augmentation in augmentations) {
- count += augmentation.resolveConstructorReferences(library);
- }
- }
- return count;
- }
-
- void resolveConstructorRedirections() {
- Iterator<MemberBuilder> iterator = nameSpace.filteredConstructorIterator(
- parent: null, includeDuplicates: true, includeAugmentations: false);
- while (iterator.moveNext()) {
- MemberBuilder declaration = iterator.current;
- if (declaration.declarationBuilder?.origin != origin) {
- unexpected("$fileUri", "${declaration.declarationBuilder!.fileUri}",
- fileOffset, fileUri);
- }
- if (declaration is SourceFactoryBuilder) {
- declaration.resolveRedirectingFactory();
- }
- }
- }
-
- @override
- int resolveConstructors(SourceLibraryBuilder library) {
- int count = resolveConstructorReferences(library);
- resolveConstructorRedirections();
- return count;
- }
-}
-
abstract class ClassDeclarationAugmentationAccess<
D extends ClassDeclarationBuilder> {
D getOrigin(D classDeclaration);
@@ -145,8 +95,12 @@
factory ClassDeclarationMemberIterator.full(
ClassDeclarationAugmentationAccess<D> access, D classBuilder,
{required bool includeDuplicates}) {
- return new ClassDeclarationMemberIterator._(access.getOrigin(classBuilder),
- access.getAugmentations(classBuilder)?.iterator,
+ return new ClassDeclarationMemberIterator._(
+ access.getOrigin(classBuilder),
+ access
+ .getAugmentations(classBuilder)
+ // Coverage-ignore(suite): Not run.
+ ?.iterator,
includeDuplicates: includeDuplicates);
}
@@ -172,7 +126,10 @@
return true;
}
}
- if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
+ if (augmentationBuilders != null &&
+ // Coverage-ignore(suite): Not run.
+ augmentationBuilders!.moveNext()) {
+ // Coverage-ignore-block(suite): Not run.
D augmentationClassDeclaration = augmentationBuilders!.current;
_iterator = augmentationClassDeclaration.nameSpace.filteredIterator<T>(
parent: augmentationClassDeclaration,
@@ -258,7 +215,10 @@
{required bool includeDuplicates}) {
return new ClassDeclarationConstructorIterator._(
access.getOrigin(classBuilder),
- access.getAugmentations(classBuilder)?.iterator,
+ access
+ .getAugmentations(classBuilder)
+ // Coverage-ignore(suite): Not run.
+ ?.iterator,
includeDuplicates: includeDuplicates);
}
@@ -284,7 +244,10 @@
return true;
}
}
- if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
+ if (augmentationBuilders != null &&
+ // Coverage-ignore(suite): Not run.
+ augmentationBuilders!.moveNext()) {
+ // Coverage-ignore-block(suite): Not run.
D augmentationClassDeclaration = augmentationBuilders!.current;
_iterator = augmentationClassDeclaration.nameSpace
.filteredConstructorIterator<T>(
@@ -317,7 +280,10 @@
{required bool includeDuplicates}) {
return new ClassDeclarationConstructorNameIterator._(
access.getOrigin(classDeclaration),
- access.getAugmentations(classDeclaration)?.iterator,
+ access
+ .getAugmentations(classDeclaration)
+ // Coverage-ignore(suite): Not run.
+ ?.iterator,
includeDuplicates: includeDuplicates);
}
@@ -336,7 +302,10 @@
return true;
}
}
- if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
+ if (augmentationBuilders != null &&
+ // Coverage-ignore(suite): Not run.
+ augmentationBuilders!.moveNext()) {
+ // Coverage-ignore-block(suite): Not run.
D augmentationClassDeclaration = augmentationBuilders!.current;
_iterator = augmentationClassDeclaration.nameSpace
.filteredConstructorNameIterator<T>(
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 fc9ed2d..fbde17f 100644
--- a/pkg/front_end/lib/src/source/source_builder_factory.dart
+++ b/pkg/front_end/lib/src/source/source_builder_factory.dart
@@ -245,10 +245,11 @@
List<TypeParameterFragment>? typeParameters) {}
@override
- void endNamedMixinApplication(String name) {
+ LookupScope endNamedMixinApplication(String name) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
+ return typeParameterScope.lookupScope;
}
@override
@@ -991,12 +992,14 @@
required int nameOffset,
required int endOffset}) {
// Nested declaration began in `OutlineBuilder.beginNamedMixinApplication`.
- endNamedMixinApplication(name);
+ LookupScope typeParameterScope = endNamedMixinApplication(name);
assert(
_mixinApplications != null, "Late registration of mixin application.");
- _nominalParameterNameSpaces.pop().addTypeParameters(
+ NominalParameterNameSpace typeParameterNameSpace =
+ _nominalParameterNameSpaces.pop();
+ typeParameterNameSpace.addTypeParameters(
_problemReporting, typeParameters?.builders,
ownerName: name, allowNameConflict: false);
@@ -1009,6 +1012,7 @@
modifiers: modifiers,
metadata: metadata,
typeParameters: typeParameters,
+ typeParameterScope: typeParameterScope,
supertype: supertype,
mixins: mixins,
interfaces: interfaces,
diff --git a/pkg/front_end/lib/src/source/source_builder_mixins.dart b/pkg/front_end/lib/src/source/source_builder_mixins.dart
index cd25fde..ce6dd4f 100644
--- a/pkg/front_end/lib/src/source/source_builder_mixins.dart
+++ b/pkg/front_end/lib/src/source/source_builder_mixins.dart
@@ -15,8 +15,6 @@
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/type_builder.dart';
-import '../kernel/body_builder_context.dart';
-import '../kernel/kernel_helper.dart';
import '../kernel/type_algorithms.dart';
import 'source_library_builder.dart';
import 'source_loader.dart';
@@ -161,25 +159,6 @@
});
}
- BodyBuilderContext createBodyBuilderContext();
-
- void buildOutlineExpressions(ClassHierarchy classHierarchy,
- List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
- if (typeParameters != null) {
- for (int i = 0; i < typeParameters!.length; i++) {
- typeParameters![i].buildOutlineExpressions(libraryBuilder,
- createBodyBuilderContext(), classHierarchy, typeParameterScope);
- }
- }
-
- Iterator<SourceMemberBuilder> iterator = nameSpace.filteredIterator(
- parent: this, includeDuplicates: false, includeAugmentations: true);
- while (iterator.moveNext()) {
- iterator.current
- .buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
- }
- }
-
void _buildMember(SourceMemberBuilder memberBuilder, Member member,
Member? tearOff, BuiltMemberKind memberKind,
{required bool addMembersToLibrary}) {
@@ -229,9 +208,6 @@
Reference memberReference,
Reference? tearOffReference);
- /// The scope in which the [typeParameters] are declared.
- LookupScope get typeParameterScope;
-
@override
List<DartType> buildAliasedTypeArguments(LibraryBuilder library,
List<TypeBuilder>? arguments, ClassHierarchyBase? hierarchy) {
diff --git a/pkg/front_end/lib/src/source/source_class_builder.dart b/pkg/front_end/lib/src/source/source_class_builder.dart
index dd50324..6a2aacd 100644
--- a/pkg/front_end/lib/src/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/source/source_class_builder.dart
@@ -27,7 +27,6 @@
import '../base/scope.dart';
import '../builder/augmentation_iterator.dart';
import '../builder/builder.dart';
-import '../builder/constructor_reference_builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/library_builder.dart';
@@ -90,7 +89,6 @@
}
class SourceClassBuilder extends ClassBuilderImpl
- with ClassDeclarationBuilderMixin
implements
Comparable<SourceClassBuilder>,
ClassDeclarationBuilder,
@@ -108,7 +106,8 @@
final Modifiers _modifiers;
- final Class actualCls;
+ @override
+ final Class cls;
final DeclarationNameSpaceBuilder nameSpaceBuilder;
@@ -124,9 +123,6 @@
List<TypeBuilder>? _interfaceBuilders;
- @override
- final List<ConstructorReferenceBuilder> constructorReferences;
-
TypeBuilder? _mixedInTypeBuilder;
final IndexedClass? indexedClass;
@@ -146,11 +142,8 @@
_isConflictingAugmentationMember = value;
}
- List<SourceClassBuilder>? _augmentations;
-
- MergedClassMemberScope? _mergedScope;
-
final ClassDeclaration _introductory;
+ List<ClassDeclaration> _augmentations;
SourceClassBuilder(
{required Modifiers modifiers,
@@ -159,36 +152,50 @@
required this.typeParameterScope,
required this.nameSpaceBuilder,
required this.libraryBuilder,
- required this.constructorReferences,
required this.fileUri,
required this.nameOffset,
this.indexedClass,
TypeBuilder? mixedInTypeBuilder,
- required ClassDeclaration classDeclaration})
+ required ClassDeclaration introductory,
+ List<ClassDeclaration> augmentations = const []})
: _modifiers = modifiers,
- _introductory = classDeclaration,
+ _introductory = introductory,
+ _augmentations = augmentations,
_mixedInTypeBuilder = mixedInTypeBuilder,
- actualCls = initializeClass(
+ cls = initializeClass(
typeParameters,
name,
fileUri,
- classDeclaration.startOffset,
- classDeclaration.nameOffset,
- classDeclaration.endOffset,
+ introductory.startOffset,
+ introductory.nameOffset,
+ introductory.endOffset,
indexedClass,
isAugmentation: modifiers.isAugment) {
- actualCls.hasConstConstructor = declaresConstConstructor;
+ cls.hasConstConstructor = declaresConstConstructor;
}
- // TODO(johnniwinther): Remove this when augmentations are handled through
- // fragments.
@override
- List<SourceClassBuilder>? get augmentations => _augmentations;
-
- // TODO(johnniwinther): Remove this when augmentations are handled through
- // fragments.
- @override
- LookupScope get bodyScope => _introductory.bodyScope;
+ int resolveConstructors(SourceLibraryBuilder libraryBuilder) {
+ int count = _introductory.resolveConstructorReferences(libraryBuilder);
+ for (ClassDeclaration augmentation in _augmentations) {
+ count += augmentation.resolveConstructorReferences(libraryBuilder);
+ }
+ if (count > 0) {
+ Iterator<MemberBuilder> iterator = nameSpace.filteredConstructorIterator(
+ parent: null, includeDuplicates: true, includeAugmentations: false);
+ while (iterator.moveNext()) {
+ MemberBuilder declaration = iterator.current;
+ if (declaration.declarationBuilder?.origin != origin) {
+ unexpected("$fileUri", "${declaration.declarationBuilder!.fileUri}",
+ fileOffset, fileUri);
+ }
+ if (declaration is SourceFactoryBuilder) {
+ declaration.resolveRedirectingFactory();
+ }
+ }
+ }
+ return count;
+ }
@override
int get fileOffset => nameOffset;
@@ -244,12 +251,6 @@
@override
void buildScopes(LibraryBuilder coreLibrary) {
- List<SourceClassBuilder>? augmentations = _augmentations;
- if (augmentations != null) {
- for (SourceClassBuilder augmentation in augmentations) {
- nameSpaceBuilder.includeBuilders(augmentation.nameSpaceBuilder);
- }
- }
_nameSpace = nameSpaceBuilder.buildNameSpace(
loader: libraryBuilder.loader,
problemReporting: libraryBuilder,
@@ -259,25 +260,8 @@
indexedContainer: indexedClass,
containerType: ContainerType.Class,
containerName: new ClassName(name));
- if (augmentations != null) {
- for (SourceClassBuilder augmentation in augmentations) {
- augmentation.buildScopes(coreLibrary);
- _applyAugmentation(augmentation);
- }
- }
}
- MergedClassMemberScope get mergedScope => _mergedScope ??= isAugmenting
- ?
- // Coverage-ignore(suite): Not run.
- origin.mergedScope
- : new MergedClassMemberScope(this);
-
- // Coverage-ignore(suite): Not run.
- List<SourceClassBuilder>? get augmentationsForTesting => _augmentations;
-
- SourceClassBuilder? actualOrigin;
-
bool _hasComputedSupertypes = false;
void computeSupertypeBuilder({
@@ -382,10 +366,7 @@
}
@override
- SourceClassBuilder get origin => actualOrigin ?? this;
-
- @override
- Class get cls => origin.actualCls;
+ SourceClassBuilder get origin => this;
@override
SourceLibraryBuilder get parent => libraryBuilder;
@@ -436,16 +417,16 @@
Supertype? supertype = supertypeBuilder?.buildSupertype(libraryBuilder,
isMixinDeclaration ? TypeUse.mixinOnType : TypeUse.classExtendsType);
if (!isMixinDeclaration &&
- actualCls.supertype != null &&
+ cls.supertype != null &&
// Coverage-ignore(suite): Not run.
- actualCls.superclass!.isMixinDeclaration) {
+ cls.superclass!.isMixinDeclaration) {
// Coverage-ignore-block(suite): Not run.
// Declared mixins have interfaces that can be implemented, but they
// cannot be extended. However, a mixin declaration with a single
// superclass constraint is encoded with the constraint as the supertype,
// and that is allowed to be a mixin's interface.
libraryBuilder.addProblem(
- templateSupertypeIsIllegal.withArguments(actualCls.superclass!.name),
+ templateSupertypeIsIllegal.withArguments(cls.superclass!.name),
fileOffset,
noLength,
fileUri);
@@ -454,7 +435,7 @@
if (supertype == null && _supertypeBuilder is! NamedTypeBuilder) {
_supertypeBuilder = null;
}
- actualCls.supertype = supertype;
+ cls.supertype = supertype;
if (_mixedInTypeBuilder != null) {
_mixedInTypeBuilder = _checkSupertype(_mixedInTypeBuilder!);
@@ -463,13 +444,13 @@
_mixedInTypeBuilder?.computeUnaliasedDeclaration(isUsedAsClass: false);
if (LibraryBuilder.isFunction(mixedInDeclaration, coreLibrary)) {
_mixedInTypeBuilder = null;
- actualCls.isAnonymousMixin = false;
+ cls.isAnonymousMixin = false;
}
Supertype? mixedInType =
_mixedInTypeBuilder?.buildMixedInType(libraryBuilder);
- actualCls.isMixinDeclaration = isMixinDeclaration;
- actualCls.mixedInType = mixedInType;
+ cls.isMixinDeclaration = isMixinDeclaration;
+ cls.mixedInType = mixedInType;
// TODO(ahe): If `cls.supertype` is null, and this isn't Object, report a
// compile-time error.
@@ -495,7 +476,7 @@
.buildSupertype(libraryBuilder, TypeUse.classImplementsType);
if (supertype != null) {
// TODO(ahe): Report an error if supertype is null.
- actualCls.implementedTypes.add(supertype);
+ cls.implementedTypes.add(supertype);
}
}
}
@@ -540,17 +521,20 @@
classHierarchy, delayedDefaultValueCloners);
}
+ BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
_introductory.buildOutlineExpressions(
- annotatable: isAugmenting ? origin.cls : cls,
- bodyBuilderContext: createBodyBuilderContext(),
+ annotatable: cls,
+ bodyBuilderContext: bodyBuilderContext,
libraryBuilder: libraryBuilder,
+ classHierarchy: classHierarchy,
createFileUriExpression: isAugmenting);
-
- if (typeParameters != null) {
- for (int i = 0; i < typeParameters!.length; i++) {
- typeParameters![i].buildOutlineExpressions(libraryBuilder,
- createBodyBuilderContext(), classHierarchy, typeParameterScope);
- }
+ for (ClassDeclaration augmentation in _augmentations) {
+ augmentation.buildOutlineExpressions(
+ annotatable: cls,
+ bodyBuilderContext: bodyBuilderContext,
+ classHierarchy: classHierarchy,
+ libraryBuilder: libraryBuilder,
+ createFileUriExpression: true);
}
nameSpace
@@ -561,14 +545,6 @@
.filteredIterator(
parent: this, includeDuplicates: false, includeAugmentations: true)
.forEach(build);
-
- List<SourceClassBuilder>? augmentations = _augmentations;
- if (augmentations != null) {
- for (SourceClassBuilder augmentation in augmentations) {
- augmentation.buildOutlineExpressions(
- classHierarchy, delayedDefaultValueCloners);
- }
- }
}
@override
@@ -737,55 +713,6 @@
return substitutionMap;
}
- @override
- void addAugmentation(Builder augmentation) {
- _addAugmentation(augmentation);
- }
-
- SourceClassBuilder? _addAugmentation(Builder augmentation) {
- if (augmentation is SourceClassBuilder) {
- augmentation.actualOrigin = this;
- (_augmentations ??= []).add(augmentation);
- return augmentation;
- } else {
- // Coverage-ignore-block(suite): Not run.
- libraryBuilder.addProblem(messagePatchDeclarationMismatch,
- augmentation.fileOffset, noLength, augmentation.fileUri, context: [
- messagePatchDeclarationOrigin.withLocation(
- fileUri, fileOffset, noLength)
- ]);
- return null;
- }
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- void applyAugmentation(Builder augmentation) {
- SourceClassBuilder? classBuilder = _addAugmentation(augmentation);
- if (classBuilder != null) {
- _applyAugmentation(classBuilder);
- }
- }
-
- void _applyAugmentation(SourceClassBuilder augmentation) {
- mergedScope.addAugmentationScope(augmentation);
-
- int originLength = typeParameters?.length ?? 0;
- int augmentationLength = augmentation.typeParameters?.length ?? 0;
- if (originLength != augmentationLength) {
- // Coverage-ignore-block(suite): Not run.
- augmentation.addProblem(messagePatchClassTypeParametersMismatch,
- augmentation.fileOffset, noLength, context: [
- messagePatchClassOrigin.withLocation(fileUri, fileOffset, noLength)
- ]);
- } else if (typeParameters != null) {
- int count = 0;
- for (NominalParameterBuilder t in augmentation.typeParameters!) {
- typeParameters![count++].applyAugmentation(t);
- }
- }
- }
-
void checkSupertypes(
CoreTypes coreTypes,
ClassHierarchyBuilder hierarchyBuilder,
@@ -1402,9 +1329,7 @@
// Coverage-ignore-block(suite): Not run.
if (member is Field && member.isStatic ||
member is Procedure && member.isStatic) {
- member.name = new Name(
- '${member.name}',
- member.name.library);
+ member.name = new Name('${member.name}', member.name.library);
} else {
return;
}
@@ -2169,8 +2094,7 @@
/// Returns an iterator the origin class and all augmentations in application
/// order.
Iterator<SourceClassBuilder> get declarationIterator =>
- new AugmentationIterator<SourceClassBuilder>(
- origin, origin._augmentations);
+ new AugmentationIterator<SourceClassBuilder>(origin, null);
@override
// Coverage-ignore(suite): Not run.
@@ -2219,7 +2143,7 @@
@override
Iterable<SourceClassBuilder>? getAugmentations(
SourceClassBuilder classDeclaration) =>
- classDeclaration._augmentations;
+ null;
}
TypeBuilder? _applyMixins(
@@ -2403,12 +2327,11 @@
typeParameterScope: typeParameterScope,
nameSpaceBuilder: nameSpaceBuilder,
libraryBuilder: enclosingLibraryBuilder,
- constructorReferences: [],
fileUri: fileUri,
nameOffset: nameOffset,
indexedClass: indexedClass,
mixedInTypeBuilder: isMixinDeclaration ? null : mixin,
- classDeclaration: classDeclaration);
+ introductory: classDeclaration);
// TODO(ahe, kmillikin): Should always be true?
// pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart can't
// handle that :(
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart
index 8eb6e25..376ef3b 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -15,7 +15,6 @@
import '../base/modifiers.dart' show Modifiers;
import '../base/scope.dart';
import '../builder/builder.dart';
-import '../builder/constructor_reference_builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/library_builder.dart';
@@ -80,7 +79,6 @@
required DeclarationNameSpaceBuilder nameSpaceBuilder,
required List<EnumElementFragment> enumElements,
required SourceLibraryBuilder libraryBuilder,
- required List<ConstructorReferenceBuilder> constructorReferences,
required Uri fileUri,
required this.startOffset,
required int nameOffset,
@@ -97,11 +95,10 @@
typeParameterScope: typeParameterScope,
nameSpaceBuilder: nameSpaceBuilder,
libraryBuilder: libraryBuilder,
- constructorReferences: constructorReferences,
fileUri: fileUri,
nameOffset: nameOffset,
indexedClass: indexedClass,
- classDeclaration: classDeclaration);
+ introductory: classDeclaration);
factory SourceEnumBuilder(
{required String name,
@@ -110,7 +107,6 @@
required List<TypeBuilder>? interfaceBuilders,
required List<EnumElementFragment> enumElements,
required SourceLibraryBuilder libraryBuilder,
- required List<ConstructorReferenceBuilder> constructorReferences,
required Uri fileUri,
required int startOffset,
required int nameOffset,
@@ -127,7 +123,6 @@
nameSpaceBuilder: nameSpaceBuilder,
enumElements: enumElements,
libraryBuilder: libraryBuilder,
- constructorReferences: constructorReferences,
fileUri: fileUri,
startOffset: startOffset,
nameOffset: nameOffset,
diff --git a/pkg/front_end/lib/src/source/source_extension_builder.dart b/pkg/front_end/lib/src/source/source_extension_builder.dart
index a16a8ad..a673fd0 100644
--- a/pkg/front_end/lib/src/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_builder.dart
@@ -8,19 +8,10 @@
import '../base/modifiers.dart';
import '../base/name_space.dart';
import '../base/problems.dart';
-import '../base/scope.dart';
-import '../builder/builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/library_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/type_builder.dart';
-import '../codes/cfe_codes.dart'
- show
- messagePatchDeclarationMismatch,
- messagePatchDeclarationOrigin,
- messagePatchExtensionOrigin,
- messagePatchExtensionTypeParametersMismatch,
- noLength;
import '../fragment/fragment.dart';
import '../kernel/body_builder_context.dart';
import '../kernel/kernel_helper.dart';
@@ -33,7 +24,7 @@
class SourceExtensionBuilder extends ExtensionBuilderImpl
with SourceDeclarationBuilderMixin {
@override
- final SourceLibraryBuilder parent;
+ final SourceLibraryBuilder libraryBuilder;
final int _nameOffset;
@@ -44,11 +35,6 @@
late final Extension _extension;
- SourceExtensionBuilder? _origin;
- SourceExtensionBuilder? _augmentation;
-
- MergedClassMemberScope? _mergedScope;
-
final DeclarationNameSpaceBuilder _nameSpaceBuilder;
late final DeclarationNameSpace _nameSpace;
@@ -57,9 +43,6 @@
final List<NominalParameterBuilder>? typeParameters;
@override
- final LookupScope typeParameterScope;
-
- @override
final TypeBuilder onType;
final ExtensionName extensionName;
@@ -68,29 +51,36 @@
/// The `extension` declaration that introduces this extension. Subsequent
/// extensions of the same name must be augmentations.
- // TODO(johnniwinther): Add [_augmentations] field.
final ExtensionFragment _introductory;
+ final List<ExtensionFragment> _augmentations;
+
SourceExtensionBuilder(
{required SourceLibraryBuilder enclosingLibraryBuilder,
required this.fileUri,
required int startOffset,
required int nameOffset,
required int endOffset,
- required ExtensionFragment fragment,
+ required DeclarationNameSpaceBuilder nameSpaceBuilder,
+ required ExtensionFragment introductory,
+ required List<ExtensionFragment> augmentations,
required Reference? reference})
- : _introductory = fragment,
+ : _introductory = introductory,
+ _augmentations = augmentations,
_reference = reference ?? new Reference(),
_nameOffset = nameOffset,
- parent = enclosingLibraryBuilder,
- _modifiers = fragment.modifiers,
- extensionName = fragment.extensionName,
- typeParameters = fragment.typeParameters?.builders,
- typeParameterScope = fragment.typeParameterScope,
- onType = fragment.onType,
- _nameSpaceBuilder = fragment.toDeclarationNameSpaceBuilder() {
+ libraryBuilder = enclosingLibraryBuilder,
+ _modifiers = introductory.modifiers,
+ extensionName = introductory.extensionName,
+ typeParameters = introductory.typeParameters?.builders,
+ onType = introductory.onType,
+ _nameSpaceBuilder = nameSpaceBuilder {
_introductory.builder = this;
_introductory.bodyScope.declarationBuilder = this;
+ for (ExtensionFragment augmentation in _augmentations) {
+ augmentation.builder = this;
+ augmentation.bodyScope.declarationBuilder = this;
+ }
// TODO(johnniwinther): Move this to the [build] once augmentations are
// handled through fragments.
@@ -130,15 +120,8 @@
@override
bool get isAugment => _modifiers.isAugment;
- // Coverage-ignore(suite): Not run.
- SourceExtensionBuilder? get augmentationForTesting => _augmentation;
-
@override
void buildScopes(LibraryBuilder coreLibrary) {
- SourceExtensionBuilder? augmentation = _augmentation;
- if (augmentation != null) {
- _nameSpaceBuilder.includeBuilders(augmentation._nameSpaceBuilder);
- }
_nameSpace = _nameSpaceBuilder.buildNameSpace(
loader: libraryBuilder.loader,
problemReporting: libraryBuilder,
@@ -151,37 +134,23 @@
containerType: ContainerType.Extension,
containerName: extensionName,
includeConstructors: false);
- if (augmentation != null) {
- augmentation.buildScopes(coreLibrary);
- _applyAugmentation(augmentation);
- }
}
@override
- SourceLibraryBuilder get libraryBuilder =>
- super.libraryBuilder as SourceLibraryBuilder;
+ SourceLibraryBuilder get parent => libraryBuilder;
bool get isUnnamedExtension => extensionName.isUnnamedExtension;
@override
- SourceExtensionBuilder get origin => _origin ?? this;
-
- // Coverage-ignore(suite): Not run.
- // TODO(johnniwinther): Add merged scope for extensions.
- MergedClassMemberScope get mergedScope => _mergedScope ??= isAugmenting
- ? origin.mergedScope
- : throw new UnimplementedError("SourceExtensionBuilder.mergedScope");
+ SourceExtensionBuilder get origin => this;
@override
Reference get reference => _reference;
@override
- Extension get extension {
- return isAugmenting ? origin.extension : _extension;
- }
+ Extension get extension => _extension;
- @override
- BodyBuilderContext createBodyBuilderContext() {
+ BodyBuilderContext _createBodyBuilderContext() {
return new ExtensionBodyBuilderContext(this);
}
@@ -204,23 +173,42 @@
return _extension;
}
- @override
- void buildOutlineExpressions(ClassHierarchy classHierarchy,
- List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
+ void _buildOutlineExpressionsForFragment(ExtensionFragment fragment,
+ ClassHierarchy classHierarchy, BodyBuilderContext bodyBuilderContext) {
MetadataBuilder.buildAnnotations(
annotatable,
- _introductory.metadata,
- createBodyBuilderContext(),
+ fragment.metadata,
+ bodyBuilderContext,
libraryBuilder,
- _introductory.fileUri,
- _introductory.enclosingScope);
+ fragment.fileUri,
+ fragment.enclosingScope);
- super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
+ if (fragment.typeParameters != null) {
+ for (int i = 0; i < fragment.typeParameters!.length; i++) {
+ fragment.typeParameters![i].builder.buildOutlineExpressions(
+ libraryBuilder,
+ bodyBuilderContext,
+ classHierarchy,
+ fragment.typeParameterScope);
+ }
+ }
+ }
- SourceExtensionBuilder? augmentation = _augmentation;
- if (augmentation != null) {
- augmentation.buildOutlineExpressions(
- classHierarchy, delayedDefaultValueCloners);
+ void buildOutlineExpressions(ClassHierarchy classHierarchy,
+ List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
+ BodyBuilderContext bodyBuilderContext = _createBodyBuilderContext();
+ _buildOutlineExpressionsForFragment(
+ _introductory, classHierarchy, bodyBuilderContext);
+ for (ExtensionFragment augmentation in _augmentations) {
+ _buildOutlineExpressionsForFragment(
+ augmentation, classHierarchy, bodyBuilderContext);
+ }
+
+ Iterator<SourceMemberBuilder> iterator = nameSpace.filteredIterator(
+ parent: this, includeDuplicates: false, includeAugmentations: true);
+ while (iterator.moveNext()) {
+ iterator.current
+ .buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
}
}
@@ -286,69 +274,4 @@
isStatic: memberBuilder.isStatic,
kind: kind));
}
-
- @override
- void addAugmentation(Builder augmentation) {
- _addAugmentation(augmentation);
- }
-
- SourceExtensionBuilder? _addAugmentation(Builder augmentation) {
- if (augmentation is SourceExtensionBuilder) {
- augmentation._origin = this;
- _augmentation = augmentation;
- return augmentation;
- } else {
- // Coverage-ignore-block(suite): Not run.
- libraryBuilder.addProblem(messagePatchDeclarationMismatch,
- augmentation.fileOffset, noLength, augmentation.fileUri, context: [
- messagePatchDeclarationOrigin.withLocation(
- fileUri, fileOffset, noLength)
- ]);
- return null;
- }
- }
-
- void _applyAugmentation(SourceExtensionBuilder augmentation) {
- // TODO(johnniwinther): Check that on-type match with origin declaration.
-
- int originLength = typeParameters?.length ?? 0;
- int augmentationLength = augmentation.typeParameters?.length ?? 0;
- if (originLength != augmentationLength) {
- // Coverage-ignore-block(suite): Not run.
- augmentation.addProblem(messagePatchExtensionTypeParametersMismatch,
- augmentation.fileOffset, noLength, context: [
- messagePatchExtensionOrigin.withLocation(fileUri, fileOffset, noLength)
- ]);
- } else if (typeParameters != null) {
- int count = 0;
- for (NominalParameterBuilder t in augmentation.typeParameters!) {
- typeParameters![count++].applyAugmentation(t);
- }
- }
- nameSpace.forEachLocalMember((String name, Builder member) {
- Builder? memberAugmentation =
- augmentation.nameSpace.lookupLocalMember(name, setter: false);
- if (memberAugmentation != null) {
- // Coverage-ignore-block(suite): Not run.
- member.applyAugmentation(memberAugmentation);
- }
- });
- nameSpace.forEachLocalSetter((String name, Builder member) {
- Builder? memberAugmentation =
- augmentation.nameSpace.lookupLocalMember(name, setter: true);
- if (memberAugmentation != null) {
- // Coverage-ignore-block(suite): Not run.
- member.applyAugmentation(memberAugmentation);
- }
- });
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- void applyAugmentation(Builder augmentation) {
- SourceExtensionBuilder? extensionBuilder = _addAugmentation(augmentation);
- if (extensionBuilder != null) {
- _applyAugmentation(extensionBuilder);
- }
- }
}
diff --git a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
index 17e2392c..5571675 100644
--- a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
@@ -13,7 +13,6 @@
import '../base/modifiers.dart';
import '../base/name_space.dart';
import '../base/problems.dart';
-import '../base/scope.dart';
import '../builder/augmentation_iterator.dart';
import '../builder/builder.dart';
import '../builder/constructor_reference_builder.dart';
@@ -42,7 +41,7 @@
class SourceExtensionTypeDeclarationBuilder
extends ExtensionTypeDeclarationBuilderImpl
- with SourceDeclarationBuilderMixin, ClassDeclarationBuilderMixin
+ with SourceDeclarationBuilderMixin
implements
Comparable<SourceExtensionTypeDeclarationBuilder>,
ClassDeclarationBuilder {
@@ -60,15 +59,10 @@
final Modifiers _modifiers;
- @override
final List<ConstructorReferenceBuilder> constructorReferences;
late final ExtensionTypeDeclaration _extensionTypeDeclaration;
- SourceExtensionTypeDeclarationBuilder? _origin;
-
- MergedClassMemberScope? _mergedScope;
-
final DeclarationNameSpaceBuilder _nameSpaceBuilder;
late final DeclarationNameSpace _nameSpace;
@@ -77,9 +71,6 @@
final List<NominalParameterBuilder>? typeParameters;
@override
- final LookupScope typeParameterScope;
-
- @override
List<TypeBuilder>? interfaceBuilders;
final ExtensionTypeFragment _introductory;
@@ -90,8 +81,6 @@
Nullability? _nullability;
- SourceExtensionTypeDeclarationBuilder? _augmentation;
-
SourceExtensionTypeDeclarationBuilder(
{required this.name,
required SourceLibraryBuilder enclosingLibraryBuilder,
@@ -108,7 +97,6 @@
_modifiers = fragment.modifiers,
typeParameters = fragment.typeParameters?.builders,
interfaceBuilders = fragment.interfaces,
- typeParameterScope = fragment.typeParameterScope,
_introductory = fragment,
_nameSpaceBuilder = fragment.toDeclarationNameSpaceBuilder(),
_representationFieldFragment = representationFieldFragment {
@@ -126,20 +114,31 @@
..fileOffset = nameOffset;
}
- // TODO(johnniwinther): Remove this when augmentations are handled through
- // fragments.
@override
- List<SourceExtensionTypeDeclarationBuilder>? get augmentations =>
- _augmentation != null
- ?
- // Coverage-ignore(suite): Not run.
- [_augmentation!]
- : const [];
-
- // TODO(johnniwinther): Remove this when augmentations are handled through
- // fragments.
- @override
- LookupScope get bodyScope => _introductory.bodyScope;
+ int resolveConstructors(SourceLibraryBuilder library) {
+ int count = 0;
+ if (constructorReferences.isNotEmpty) {
+ for (ConstructorReferenceBuilder ref in constructorReferences) {
+ ref.resolveIn(_introductory.bodyScope, library);
+ }
+ count += constructorReferences.length;
+ }
+ if (count > 0) {
+ Iterator<MemberBuilder> iterator = nameSpace.filteredConstructorIterator(
+ parent: null, includeDuplicates: true, includeAugmentations: false);
+ while (iterator.moveNext()) {
+ MemberBuilder declaration = iterator.current;
+ if (declaration.declarationBuilder?.origin != origin) {
+ unexpected("$fileUri", "${declaration.declarationBuilder!.fileUri}",
+ fileOffset, fileUri);
+ }
+ if (declaration is SourceFactoryBuilder) {
+ declaration.resolveRedirectingFactory();
+ }
+ }
+ }
+ return count;
+ }
// Coverage-ignore(suite): Not run.
// TODO(johnniwinther): Avoid exposing this. Annotations for macros and
@@ -174,11 +173,6 @@
indexedContainer: indexedContainer,
containerType: ContainerType.ExtensionType,
containerName: new ClassName(name));
- SourceExtensionTypeDeclarationBuilder? augmentation = _augmentation;
- if (augmentation != null) {
- // Coverage-ignore-block(suite): Not run.
- _applyAugmentation(augmentation);
- }
}
@override
@@ -190,14 +184,7 @@
_representationFieldFragment?.type;
@override
- SourceExtensionTypeDeclarationBuilder get origin => _origin ?? this;
-
- // Coverage-ignore(suite): Not run.
- // TODO(johnniwinther): Add merged scope for extension type declarations.
- MergedClassMemberScope get mergedScope => _mergedScope ??= isAugmenting
- ? origin.mergedScope
- : throw new UnimplementedError(
- "SourceExtensionTypeDeclarationBuilder.mergedScope");
+ SourceExtensionTypeDeclarationBuilder get origin => this;
@override
ExtensionTypeDeclaration get extensionTypeDeclaration => isAugmenting
@@ -733,7 +720,6 @@
}
}
- @override
void buildOutlineExpressions(ClassHierarchy classHierarchy,
List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
MetadataBuilder.buildAnnotations(
@@ -744,15 +730,30 @@
_introductory.fileUri,
_introductory.enclosingScope);
- super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
+ if (_introductory.typeParameters != null) {
+ for (int i = 0; i < _introductory.typeParameters!.length; i++) {
+ _introductory.typeParameters![i].builder.buildOutlineExpressions(
+ libraryBuilder,
+ createBodyBuilderContext(),
+ classHierarchy,
+ _introductory.typeParameterScope);
+ }
+ }
- Iterator<SourceMemberBuilder> iterator =
- nameSpace.filteredConstructorIterator(
- parent: this, includeDuplicates: false, includeAugmentations: true);
+ Iterator<SourceMemberBuilder> iterator = nameSpace.filteredIterator(
+ parent: this, includeDuplicates: false, includeAugmentations: true);
while (iterator.moveNext()) {
iterator.current
.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
}
+
+ Iterator<SourceMemberBuilder> constructorIterator =
+ nameSpace.filteredConstructorIterator(
+ parent: this, includeDuplicates: false, includeAugmentations: true);
+ while (constructorIterator.moveNext()) {
+ constructorIterator.current
+ .buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
+ }
}
@override
@@ -850,60 +851,6 @@
kind: kind));
}
- @override
- // Coverage-ignore(suite): Not run.
- void addAugmentation(Builder augmentation) {
- _addAugmentation(augmentation);
- }
-
- // Coverage-ignore(suite): Not run.
- SourceExtensionTypeDeclarationBuilder? _addAugmentation(
- Builder augmentation) {
- if (augmentation is SourceExtensionTypeDeclarationBuilder) {
- augmentation._origin = this;
- _augmentation = augmentation;
- return augmentation;
- } else {
- libraryBuilder.addProblem(messagePatchDeclarationMismatch,
- augmentation.fileOffset, noLength, augmentation.fileUri, context: [
- messagePatchDeclarationOrigin.withLocation(
- fileUri, fileOffset, noLength)
- ]);
- return null;
- }
- }
-
- // Coverage-ignore(suite): Not run.
- void _applyAugmentation(SourceExtensionTypeDeclarationBuilder augmentation) {
- nameSpace.forEachLocalMember((String name, Builder member) {
- Builder? memberAugmentation =
- augmentation.nameSpace.lookupLocalMember(name, setter: false);
- if (memberAugmentation != null) {
- member.applyAugmentation(memberAugmentation);
- }
- });
- nameSpace.forEachLocalSetter((String name, Builder member) {
- Builder? memberAugmentation =
- augmentation.nameSpace.lookupLocalMember(name, setter: true);
- if (memberAugmentation != null) {
- member.applyAugmentation(memberAugmentation);
- }
- });
-
- // TODO(johnniwinther): Check that type parameters and on-type match
- // with origin declaration.
- }
-
- @override
- // Coverage-ignore(suite): Not run.
- void applyAugmentation(Builder augmentation) {
- SourceExtensionTypeDeclarationBuilder? extensionTypeDeclarationBuilder =
- _addAugmentation(augmentation);
- if (extensionTypeDeclarationBuilder != null) {
- _applyAugmentation(extensionTypeDeclarationBuilder);
- }
- }
-
/// Looks up the constructor by [name] on the class built by this class
/// builder.
SourceConstructorBuilderImpl? lookupConstructor(Name name) {
@@ -960,7 +907,6 @@
// Coverage-ignore(suite): Not run.
bool get isMixinDeclaration => false;
- @override
BodyBuilderContext createBodyBuilderContext() {
return new ExtensionTypeBodyBuilderContext(this);
}
diff --git a/pkg/front_end/lib/src/source/source_library_builder.dart b/pkg/front_end/lib/src/source/source_library_builder.dart
index ca2064d..5298033 100644
--- a/pkg/front_end/lib/src/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/source/source_library_builder.dart
@@ -335,6 +335,7 @@
/// `true` if this is an augmentation library.
bool get isAugmentationLibrary => compilationUnit.forAugmentationLibrary;
+ // Coverage-ignore(suite): Not run.
/// `true` if this is a patch library.
bool get isPatchLibrary => compilationUnit.forPatchLibrary;
@@ -648,11 +649,11 @@
// recording the non-synthetic instance fields and getters of each.
Iterator<SourceClassBuilder> classIterator = localMembersIteratorOfType();
while (classIterator.moveNext()) {
- SourceClassBuilder class_ = classIterator.current;
- ClassInfo<Class> classInfo = fieldPromotability.addClass(class_.actualCls,
- isAbstract: class_.isAbstract);
+ SourceClassBuilder classBuilder = classIterator.current;
+ ClassInfo<Class> classInfo = fieldPromotability.addClass(classBuilder.cls,
+ isAbstract: classBuilder.isAbstract);
Iterator<SourceMemberBuilder> memberIterator =
- class_.fullMemberIterator<SourceMemberBuilder>();
+ classBuilder.fullMemberIterator<SourceMemberBuilder>();
while (memberIterator.moveNext()) {
SourceMemberBuilder member = memberIterator.current;
if (member.isStatic) continue;
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 a15f6da..01a6feb 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
@@ -107,7 +107,9 @@
/// map the [NameSpace], they are not directly marked as duplicate if they
/// do not conflict with other setters.
void createBuilders(
- void Function(Fragment, {bool conflictingSetter}) createBuilder);
+ void Function(Fragment,
+ {bool conflictingSetter, List<Fragment>? augmentations})
+ createBuilder);
}
/// [_PreBuilder] for properties, i.e. fields, getters and setters.
@@ -732,7 +734,9 @@
@override
void createBuilders(
- void Function(Fragment, {bool conflictingSetter}) createBuilder) {
+ void Function(Fragment,
+ {bool conflictingSetter, List<Fragment>? augmentations})
+ createBuilder) {
if (getter != null) {
createBuilder(getter!.fragment);
}
@@ -856,11 +860,11 @@
@override
void createBuilders(
- void Function(Fragment, {bool conflictingSetter}) createBuilder) {
- createBuilder(fragment.fragment);
- for (_FragmentName fragmentName in augmentations) {
- createBuilder(fragmentName.fragment);
- }
+ void Function(Fragment,
+ {bool conflictingSetter, List<Fragment>? augmentations})
+ createBuilder) {
+ createBuilder(fragment.fragment,
+ augmentations: augmentations.map((f) => f.fragment).toList());
}
}
@@ -984,11 +988,11 @@
@override
void createBuilders(
- void Function(Fragment, {bool conflictingSetter}) createBuilder) {
- createBuilder(fragment.fragment);
- for (_FragmentName fragmentName in augmentations) {
- createBuilder(fragmentName.fragment);
- }
+ void Function(Fragment,
+ {bool conflictingSetter, List<Fragment>? augmentations})
+ createBuilder) {
+ createBuilder(fragment.fragment,
+ augmentations: augmentations.map((f) => f.fragment).toList());
}
}
@@ -1215,7 +1219,8 @@
}
}
- void createBuilder(Fragment fragment, {bool conflictingSetter = false}) {
+ void createBuilder(Fragment fragment,
+ {bool conflictingSetter = false, List<Fragment>? augmentations}) {
switch (fragment) {
case TypedefFragment():
Reference? reference = indexedLibrary?.lookupTypedef(fragment.name);
@@ -1233,22 +1238,75 @@
loader.buildersCreatedWithReferences[reference] = typedefBuilder;
}
case ClassFragment():
- IndexedClass? indexedClass =
- indexedLibrary?.lookupIndexedClass(fragment.name);
+ String name = fragment.name;
+ DeclarationNameSpaceBuilder nameSpaceBuilder =
+ fragment.toDeclarationNameSpaceBuilder();
+ ClassDeclaration introductoryDeclaration =
+ new RegularClassDeclaration(fragment);
+
+ Modifiers modifiers = fragment.modifiers;
+ List<ClassDeclaration> augmentationDeclarations = [];
+ if (augmentations != null) {
+ int introductoryTypeParameterCount =
+ fragment.typeParameters?.length ?? 0;
+ for (Fragment augmentation in augmentations) {
+ // Promote [augmentation] to [ClassFragment].
+ augmentation as ClassFragment;
+
+ // TODO(johnniwinther): Check that other modifiers are consistent.
+ if (augmentation.modifiers.declaresConstConstructor) {
+ modifiers |= Modifiers.DeclaresConstConstructor;
+ }
+ augmentationDeclarations
+ .add(new RegularClassDeclaration(augmentation));
+ nameSpaceBuilder
+ .includeBuilders(augmentation.toDeclarationNameSpaceBuilder());
+
+ int augmentationTypeParameterCount =
+ augmentation.typeParameters?.length ?? 0;
+ if (introductoryTypeParameterCount !=
+ augmentationTypeParameterCount) {
+ problemReporting.addProblem(
+ messagePatchClassTypeParametersMismatch,
+ augmentation.nameOffset,
+ name.length,
+ augmentation.fileUri,
+ context: [
+ messagePatchClassOrigin.withLocation(
+ fragment.fileUri, fragment.nameOffset, name.length)
+ ]);
+ } else if (augmentation.typeParameters != null) {
+ int count = 0;
+ for (TypeParameterFragment t in augmentation.typeParameters!) {
+ fragment.typeParameters![count++].builder
+ .applyAugmentation(t.builder);
+ }
+ }
+ }
+ }
+ IndexedClass? indexedClass = indexedLibrary?.lookupIndexedClass(name);
SourceClassBuilder classBuilder = new SourceClassBuilder(
- modifiers: fragment.modifiers,
- name: fragment.name,
+ modifiers: modifiers,
+ name: name,
typeParameters: fragment.typeParameters?.builders,
typeParameterScope: fragment.typeParameterScope,
- nameSpaceBuilder: fragment.toDeclarationNameSpaceBuilder(),
+ nameSpaceBuilder: nameSpaceBuilder,
libraryBuilder: enclosingLibraryBuilder,
- constructorReferences: fragment.constructorReferences,
fileUri: fragment.fileUri,
nameOffset: fragment.nameOffset,
indexedClass: indexedClass,
- classDeclaration: new RegularClassDeclaration(fragment));
+ introductory: introductoryDeclaration,
+ augmentations: augmentationDeclarations);
fragment.builder = classBuilder;
fragment.bodyScope.declarationBuilder = classBuilder;
+ if (augmentations != null) {
+ for (Fragment augmentation in augmentations) {
+ augmentation as ClassFragment;
+ augmentation.builder = classBuilder;
+ augmentation.bodyScope.declarationBuilder = classBuilder;
+ }
+ augmentations = null;
+ }
builders.add(new _AddBuilder(
fragment.name, classBuilder, fragment.fileUri, fragment.fileOffset,
inPatch: fragment.enclosingCompilationUnit.isPatch));
@@ -1268,11 +1326,10 @@
typeParameterScope: fragment.typeParameterScope,
nameSpaceBuilder: fragment.toDeclarationNameSpaceBuilder(),
libraryBuilder: enclosingLibraryBuilder,
- constructorReferences: fragment.constructorReferences,
fileUri: fragment.fileUri,
nameOffset: fragment.nameOffset,
indexedClass: indexedClass,
- classDeclaration: new MixinDeclaration(fragment));
+ introductory: new MixinDeclaration(fragment));
fragment.builder = mixinBuilder;
fragment.bodyScope.declarationBuilder = mixinBuilder;
builders.add(new _AddBuilder(
@@ -1306,12 +1363,11 @@
typeParameterScope: typeParameterScope,
nameSpaceBuilder: nameSpaceBuilder,
libraryBuilder: enclosingLibraryBuilder,
- constructorReferences: [],
fileUri: fragment.fileUri,
nameOffset: fragment.nameOffset,
indexedClass: referencesFromIndexedClass,
mixedInTypeBuilder: mixin,
- classDeclaration: classDeclaration);
+ introductory: classDeclaration);
mixinApplications[classBuilder] = mixin;
fragment.builder = classBuilder;
builders.add(new _AddBuilder(
@@ -1333,7 +1389,6 @@
interfaceBuilders: fragment.interfaces,
enumElements: fragment.enumElements,
libraryBuilder: enclosingLibraryBuilder,
- constructorReferences: fragment.constructorReferences,
fileUri: fragment.fileUri,
startOffset: fragment.startOffset,
nameOffset: fragment.nameOffset,
@@ -1353,6 +1408,45 @@
enumBuilder;
}
case ExtensionFragment():
+ DeclarationNameSpaceBuilder nameSpaceBuilder =
+ fragment.toDeclarationNameSpaceBuilder();
+ List<ExtensionFragment> augmentationFragments = [];
+ if (augmentations != null) {
+ int introductoryTypeParameterCount =
+ fragment.typeParameters?.length ?? 0;
+ int nameLength = fragment.isUnnamed ? noLength : fragment.name.length;
+
+ for (Fragment augmentation in augmentations) {
+ // Promote [augmentation] to [ExtensionFragment].
+ augmentation as ExtensionFragment;
+
+ augmentationFragments.add(augmentation);
+ nameSpaceBuilder
+ .includeBuilders(augmentation.toDeclarationNameSpaceBuilder());
+
+ int augmentationTypeParameterCount =
+ augmentation.typeParameters?.length ?? 0;
+ if (introductoryTypeParameterCount !=
+ augmentationTypeParameterCount) {
+ problemReporting.addProblem(
+ messagePatchExtensionTypeParametersMismatch,
+ augmentation.nameOrExtensionOffset,
+ nameLength,
+ augmentation.fileUri,
+ context: [
+ messagePatchExtensionOrigin.withLocation(fragment.fileUri,
+ fragment.nameOrExtensionOffset, nameLength)
+ ]);
+ } else if (augmentation.typeParameters != null) {
+ int count = 0;
+ for (TypeParameterFragment t in augmentation.typeParameters!) {
+ fragment.typeParameters![count++].builder
+ .applyAugmentation(t.builder);
+ }
+ }
+ }
+ augmentations = null;
+ }
Reference? reference;
if (!fragment.extensionName.isUnnamedExtension) {
reference = indexedLibrary?.lookupExtension(fragment.name);
@@ -1363,7 +1457,9 @@
startOffset: fragment.startOffset,
nameOffset: fragment.nameOrExtensionOffset,
endOffset: fragment.endOffset,
- fragment: fragment,
+ introductory: fragment,
+ augmentations: augmentationFragments,
+ nameSpaceBuilder: nameSpaceBuilder,
reference: reference);
builders.add(new _AddBuilder(fragment.name, extensionBuilder,
fragment.fileUri, fragment.fileOffset,
@@ -1970,6 +2066,11 @@
fragment.fileUri, fragment.nameOffset,
inPatch: fragment.enclosingDeclaration.isPatch));
}
+ if (augmentations != null) {
+ for (Fragment augmentation in augmentations) {
+ createBuilder(augmentation);
+ }
+ }
}
for (_PreBuilder preBuilder in nonConstructorPreBuilders) {
@@ -2114,7 +2215,6 @@
// output.
extensions.add(declaration as SourceExtensionBuilder);
} else if (declaration.isAugment) {
- // Coverage-ignore-block(suite): Not run.
if (existing == null) {
// TODO(cstefantsova): Report an error.
}
@@ -2392,6 +2492,8 @@
if (addBuilder.inPatch &&
!name.startsWith('_') &&
!_allowInjectedPublicMember(enclosingLibraryBuilder, declaration)) {
+ // TODO(johnniwinther): Test adding a no-name constructor in the patch,
+ // either as an injected or duplicated constructor.
problemReporting.addProblem(
templatePatchInjectionFailed.withArguments(
name, enclosingLibraryBuilder.importUri),
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index 185ddf9..afb0410 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -190,7 +190,7 @@
),
// 100.0%.
"package:front_end/src/base/name_space.dart": (
- hitCount: 153,
+ hitCount: 137,
missCount: 0,
),
// 100.0%.
@@ -210,7 +210,7 @@
),
// 100.0%.
"package:front_end/src/base/scope.dart": (
- hitCount: 455,
+ hitCount: 412,
missCount: 0,
),
// 100.0%.
@@ -470,7 +470,7 @@
),
// 100.0%.
"package:front_end/src/fragment/class/declaration.dart": (
- hitCount: 168,
+ hitCount: 234,
missCount: 0,
),
// 100.0%.
@@ -815,7 +815,7 @@
),
// 100.0%.
"package:front_end/src/source/class_declaration.dart": (
- hitCount: 110,
+ hitCount: 57,
missCount: 0,
),
// 100.0%.
@@ -850,22 +850,22 @@
),
// 100.0%.
"package:front_end/src/source/source_builder_factory.dart": (
- hitCount: 1190,
+ hitCount: 1191,
missCount: 0,
),
// 100.0%.
"package:front_end/src/source/source_builder_mixins.dart": (
- hitCount: 131,
+ hitCount: 114,
missCount: 0,
),
// 100.0%.
"package:front_end/src/source/source_class_builder.dart": (
- hitCount: 1398,
+ hitCount: 1354,
missCount: 0,
),
// 100.0%.
"package:front_end/src/source/source_compilation_unit.dart": (
- hitCount: 669,
+ hitCount: 668,
missCount: 0,
),
// 100.0%.
@@ -880,13 +880,13 @@
),
// 100.0%.
"package:front_end/src/source/source_extension_builder.dart": (
- hitCount: 158,
+ hitCount: 137,
missCount: 0,
),
// 100.0%.
"package:front_end/src/source/source_extension_type_declaration_builder.dart":
(
- hitCount: 514,
+ hitCount: 550,
missCount: 0,
),
// 100.0%.
@@ -901,12 +901,12 @@
),
// 100.0%.
"package:front_end/src/source/source_library_builder.dart": (
- hitCount: 1120,
+ hitCount: 1085,
missCount: 0,
),
// 100.0%.
"package:front_end/src/source/source_loader.dart": (
- hitCount: 1792,
+ hitCount: 1790,
missCount: 0,
),
// 100.0%.
@@ -941,7 +941,7 @@
),
// 100.0%.
"package:front_end/src/source/type_parameter_scope_builder.dart": (
- hitCount: 1496,
+ hitCount: 1567,
missCount: 0,
),
// 100.0%.
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index 0271767..23dc46a 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_test.dart
@@ -130,7 +130,7 @@
features.addElement(Tags.scope, name);
});
- for (Member m in clsBuilder.actualCls.members) {
+ for (Member m in clsBuilder.cls.members) {
if (m is Procedure &&
(m.isMemberSignature ||
(m.isForwardingStub && !m.isForwardingSemiStub))) {
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
index 1eaf61d..f776adc 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
@@ -16,7 +16,7 @@
import "dart:_internal";
@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
-class Class extends core::Object {
+class Class extends core::Object /*hasConstConstructor*/ {
final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _internal({core::bool defaultValue = #C2}) → test::Class
: test::Class::defaultValue = defaultValue, super core::Object::•()
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.modular.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.modular.expect
index 1eaf61d..f776adc 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.modular.expect
@@ -16,7 +16,7 @@
import "dart:_internal";
@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
-class Class extends core::Object {
+class Class extends core::Object /*hasConstConstructor*/ {
final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _internal({core::bool defaultValue = #C2}) → test::Class
: test::Class::defaultValue = defaultValue, super core::Object::•()
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.outline.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.outline.expect
index 20b5b94..d02c957 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.outline.expect
@@ -14,7 +14,7 @@
import "dart:_internal";
@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
-class Class extends core::Object {
+class Class extends core::Object /*hasConstConstructor*/ {
final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _internal({core::bool defaultValue = false}) → self2::Class
: self2::Class::defaultValue = defaultValue, super core::Object::•()
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
index 1eaf61d..f776adc 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
import "dart:_internal";
@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
-class Class extends core::Object {
+class Class extends core::Object /*hasConstConstructor*/ {
final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _internal({core::bool defaultValue = #C2}) → test::Class
: test::Class::defaultValue = defaultValue, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart b/pkg/front_end/testcases/general/constructor_patch/main.dart
index 57977cc..2c5f44e 100644
--- a/pkg/front_end/testcases/general/constructor_patch/main.dart
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart
@@ -7,6 +7,7 @@
test() {
new Class._private(); // Error
new Class._privateInjected(); // Error
+ new Class3(); // Error
}
main() {
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.expect
index 35fd7d7..8b5ac71 100644
--- a/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.expect
@@ -10,6 +10,10 @@
// new Class._privateInjected(); // Error
// ^^^^^^^^^^^^^^^^
//
+// pkg/front_end/testcases/general/constructor_patch/main.dart:10:7: Error: Couldn't find constructor 'Class3'.
+// new Class3(); // Error
+// ^^^^^^
+//
import self as self;
import "dart:test" as test;
@@ -22,6 +26,9 @@
invalid-expression "pkg/front_end/testcases/general/constructor_patch/main.dart:9:13: Error: Couldn't find constructor 'Class._privateInjected'.
new Class._privateInjected(); // Error
^^^^^^^^^^^^^^^^";
+ invalid-expression "pkg/front_end/testcases/general/constructor_patch/main.dart:10:7: Error: Couldn't find constructor 'Class3'.
+ new Class3(); // Error
+ ^^^^^^";
}
static method main() → dynamic {
new test::Class::generative();
@@ -77,15 +84,23 @@
: super test::Class::_privateInjected()
;
}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C3
+class Class3 extends core::Object /*hasConstConstructor*/ {
+ const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _() → test::Class3
+ : super core::Object::•()
+ ;
+}
static method test() → dynamic {
new test::Class::_private();
new test::Class::_privateInjected();
+ #C4;
}
constants {
#C1 = true
#C2 = test::Class {defaultValue:#C1}
#C3 = _in::_Patch {}
+ #C4 = test::Class3 {}
}
@@ -93,3 +108,7 @@
org-dartlang-testcase:///main.dart:
- Class.constGenerative (from org-dartlang-testcase:///patch_lib.dart:16:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
+
+org-dartlang-testcase:///origin_lib.dart:
+- Class3._ (from org-dartlang-testcase:///patch_lib.dart:38:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.modular.expect
index 35fd7d7..8b5ac71 100644
--- a/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.modular.expect
@@ -10,6 +10,10 @@
// new Class._privateInjected(); // Error
// ^^^^^^^^^^^^^^^^
//
+// pkg/front_end/testcases/general/constructor_patch/main.dart:10:7: Error: Couldn't find constructor 'Class3'.
+// new Class3(); // Error
+// ^^^^^^
+//
import self as self;
import "dart:test" as test;
@@ -22,6 +26,9 @@
invalid-expression "pkg/front_end/testcases/general/constructor_patch/main.dart:9:13: Error: Couldn't find constructor 'Class._privateInjected'.
new Class._privateInjected(); // Error
^^^^^^^^^^^^^^^^";
+ invalid-expression "pkg/front_end/testcases/general/constructor_patch/main.dart:10:7: Error: Couldn't find constructor 'Class3'.
+ new Class3(); // Error
+ ^^^^^^";
}
static method main() → dynamic {
new test::Class::generative();
@@ -77,15 +84,23 @@
: super test::Class::_privateInjected()
;
}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C3
+class Class3 extends core::Object /*hasConstConstructor*/ {
+ const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _() → test::Class3
+ : super core::Object::•()
+ ;
+}
static method test() → dynamic {
new test::Class::_private();
new test::Class::_privateInjected();
+ #C4;
}
constants {
#C1 = true
#C2 = test::Class {defaultValue:#C1}
#C3 = _in::_Patch {}
+ #C4 = test::Class3 {}
}
@@ -93,3 +108,7 @@
org-dartlang-testcase:///main.dart:
- Class.constGenerative (from org-dartlang-testcase:///patch_lib.dart:16:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
+
+org-dartlang-testcase:///origin_lib.dart:
+- Class3._ (from org-dartlang-testcase:///patch_lib.dart:38:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.outline.expect
index c444a46..f4e3cc1 100644
--- a/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.outline.expect
@@ -46,6 +46,12 @@
constructor privateInjected() → self2::Subclass
;
}
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
+class Class3 extends core::Object /*hasConstConstructor*/ {
+ const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _() → self2::Class3
+ : super core::Object::•()
+ ;
+}
static method test() → dynamic
;
@@ -57,4 +63,5 @@
Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:17:8 -> InstanceConstant(const _Patch{})
Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:28:1 -> InstanceConstant(const _Patch{})
Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
-Extra constant evaluation: evaluated: 7, effectively constant: 6
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:36:1 -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 8, effectively constant: 7
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.transformed.expect
index 35fd7d7..8b5ac71 100644
--- a/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.strong.transformed.expect
@@ -10,6 +10,10 @@
// new Class._privateInjected(); // Error
// ^^^^^^^^^^^^^^^^
//
+// pkg/front_end/testcases/general/constructor_patch/main.dart:10:7: Error: Couldn't find constructor 'Class3'.
+// new Class3(); // Error
+// ^^^^^^
+//
import self as self;
import "dart:test" as test;
@@ -22,6 +26,9 @@
invalid-expression "pkg/front_end/testcases/general/constructor_patch/main.dart:9:13: Error: Couldn't find constructor 'Class._privateInjected'.
new Class._privateInjected(); // Error
^^^^^^^^^^^^^^^^";
+ invalid-expression "pkg/front_end/testcases/general/constructor_patch/main.dart:10:7: Error: Couldn't find constructor 'Class3'.
+ new Class3(); // Error
+ ^^^^^^";
}
static method main() → dynamic {
new test::Class::generative();
@@ -77,15 +84,23 @@
: super test::Class::_privateInjected()
;
}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C3
+class Class3 extends core::Object /*hasConstConstructor*/ {
+ const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _() → test::Class3
+ : super core::Object::•()
+ ;
+}
static method test() → dynamic {
new test::Class::_private();
new test::Class::_privateInjected();
+ #C4;
}
constants {
#C1 = true
#C2 = test::Class {defaultValue:#C1}
#C3 = _in::_Patch {}
+ #C4 = test::Class3 {}
}
@@ -93,3 +108,7 @@
org-dartlang-testcase:///main.dart:
- Class.constGenerative (from org-dartlang-testcase:///patch_lib.dart:16:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
+
+org-dartlang-testcase:///origin_lib.dart:
+- Class3._ (from org-dartlang-testcase:///patch_lib.dart:38:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/constructor_patch/origin_lib.dart b/pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
index 9f48201..50547af 100644
--- a/pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
+++ b/pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
@@ -17,9 +17,12 @@
test() {
new Class._private(); // Ok
new Class._privateInjected(); // Ok
+ const Class3._(); // Ok
}
class Subclass extends Class {
Subclass.private() : super._private(); // Ok
Subclass.privateInjected() : super._privateInjected(); // Ok
}
+
+class Class3 {}
diff --git a/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart b/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart
index ed5bfee..8de4517 100644
--- a/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart
+++ b/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart
@@ -32,3 +32,8 @@
@patch
Class2(this.field) : injectedField = field;
}
+
+@patch
+class Class3 {
+ const Class3._();
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.strong.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.strong.expect
index e2d7f06..2461e05 100644
--- a/pkg/front_end/testcases/general/factory_patch/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.strong.expect
@@ -24,7 +24,7 @@
import "dart:_internal";
@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
-class Class extends core::Object {
+class Class extends core::Object /*hasConstConstructor*/ {
final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _internal({core::bool defaultValue = #C2}) → test::Class
: test::Class::defaultValue = defaultValue, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.strong.modular.expect
index e2d7f06..2461e05 100644
--- a/pkg/front_end/testcases/general/factory_patch/main.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.strong.modular.expect
@@ -24,7 +24,7 @@
import "dart:_internal";
@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
-class Class extends core::Object {
+class Class extends core::Object /*hasConstConstructor*/ {
final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _internal({core::bool defaultValue = #C2}) → test::Class
: test::Class::defaultValue = defaultValue, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.strong.outline.expect
index 0746810..91a92f6 100644
--- a/pkg/front_end/testcases/general/factory_patch/main.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.strong.outline.expect
@@ -14,7 +14,7 @@
import "dart:_internal";
@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
-class Class extends core::Object {
+class Class extends core::Object /*hasConstConstructor*/ {
final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _internal({core::bool defaultValue = false}) → self2::Class
: self2::Class::defaultValue = defaultValue, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.strong.transformed.expect
index e2d7f06..2461e05 100644
--- a/pkg/front_end/testcases/general/factory_patch/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.strong.transformed.expect
@@ -24,7 +24,7 @@
import "dart:_internal";
@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
-class Class extends core::Object {
+class Class extends core::Object /*hasConstConstructor*/ {
final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
const constructor /* from org-dartlang-testcase:///patch_lib.dart */ _internal({core::bool defaultValue = #C2}) → test::Class
: test::Class::defaultValue = defaultValue, super core::Object::•()
diff --git a/pkg/front_end/testcases/general/invalid_patch/libraries.json b/pkg/front_end/testcases/general/invalid_patch/libraries.json
new file mode 100644
index 0000000..79373ad
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/libraries.json
@@ -0,0 +1,13 @@
+{
+ "vm": {
+ "comment:0": "This adds to the default libraries found in the platform.",
+ "libraries": {
+ "test": {
+ "patches": [
+ "patch_lib.dart"
+ ],
+ "uri": "origin_lib.dart"
+ }
+ }
+ }
+}
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart b/pkg/front_end/testcases/general/invalid_patch/main.dart
new file mode 100644
index 0000000..c345588
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart
@@ -0,0 +1,7 @@
+// 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 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.expect
new file mode 100644
index 0000000..85f0092
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.expect
@@ -0,0 +1,90 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic {}
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:9:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount1<T> /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:5:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount1 {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:12:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount2 /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:7:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount2<T> {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:15:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount3<T> /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:9:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount3<T, S> {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:18:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount1<T> on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:11:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount1 on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:21:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount2 on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:13:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount2<T> on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:24:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount3<T> on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:15:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount3<T, S> on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount1 extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount1
+ : super core::Object::•()
+ ;
+}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount2<self2::InvalidClassTypeParameterCount2::T%>
+ : super core::Object::•()
+ ;
+}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount3<self2::InvalidClassTypeParameterCount3::T%, self2::InvalidClassTypeParameterCount3::S%>
+ : super core::Object::•()
+ ;
+}
+@#C1
+extension InvalidExtensionTypeParameterCount1 on core::int {
+}
+@#C1
+extension InvalidExtensionTypeParameterCount2<T extends core::Object? = dynamic> on core::int {
+}
+@#C1
+extension InvalidExtensionTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> on core::int {
+}
+
+constants {
+ #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.modular.expect
new file mode 100644
index 0000000..85f0092
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.modular.expect
@@ -0,0 +1,90 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic {}
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:9:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount1<T> /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:5:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount1 {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:12:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount2 /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:7:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount2<T> {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:15:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount3<T> /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:9:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount3<T, S> {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:18:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount1<T> on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:11:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount1 on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:21:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount2 on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:13:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount2<T> on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:24:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount3<T> on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:15:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount3<T, S> on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount1 extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount1
+ : super core::Object::•()
+ ;
+}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount2<self2::InvalidClassTypeParameterCount2::T%>
+ : super core::Object::•()
+ ;
+}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount3<self2::InvalidClassTypeParameterCount3::T%, self2::InvalidClassTypeParameterCount3::S%>
+ : super core::Object::•()
+ ;
+}
+@#C1
+extension InvalidExtensionTypeParameterCount1 on core::int {
+}
+@#C1
+extension InvalidExtensionTypeParameterCount2<T extends core::Object? = dynamic> on core::int {
+}
+@#C1
+extension InvalidExtensionTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> on core::int {
+}
+
+constants {
+ #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.outline.expect
new file mode 100644
index 0000000..59d64c6
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.outline.expect
@@ -0,0 +1,94 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+ ;
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:9:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount1<T> /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:5:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount1 {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:12:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount2 /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:7:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount2<T> {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:15:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount3<T> /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:9:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount3<T, S> {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:18:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount1<T> on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:11:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount1 on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:21:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount2 on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:13:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount2<T> on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:24:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount3<T> on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:15:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount3<T, S> on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
+class InvalidClassTypeParameterCount1 extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount1
+ ;
+}
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
+class InvalidClassTypeParameterCount2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount2<self2::InvalidClassTypeParameterCount2::T%>
+ ;
+}
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
+class InvalidClassTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount3<self2::InvalidClassTypeParameterCount3::T%, self2::InvalidClassTypeParameterCount3::S%>
+ ;
+}
+@_in::patch
+extension InvalidExtensionTypeParameterCount1 on core::int {
+}
+@_in::patch
+extension InvalidExtensionTypeParameterCount2<T extends core::Object? = dynamic> on core::int {
+}
+@_in::patch
+extension InvalidExtensionTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> on core::int {
+}
+
+
+Extra constant evaluation status:
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:8:1 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:11:1 -> InstanceConstant(const _Patch{})
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:14:1 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:14:1 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 6, effectively constant: 6
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..85f0092
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.strong.transformed.expect
@@ -0,0 +1,90 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic {}
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:9:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount1<T> /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:5:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount1 {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:12:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount2 /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:7:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount2<T> {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:15:7: Error: A patch class must have the same number of type variables as its origin class.
+// class InvalidClassTypeParameterCount3<T> /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:9:7: Context: This is the origin class.
+// class InvalidClassTypeParameterCount3<T, S> {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:18:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount1<T> on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:11:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount1 on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:21:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount2 on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:13:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount2<T> on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/invalid_patch/patch_lib.dart:24:11: Error: A patch extension must have the same number of type variables as its origin extension.
+// extension InvalidExtensionTypeParameterCount3<T> on int /* Error */ {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/invalid_patch/origin_lib.dart:15:11: Context: This is the origin extension.
+// extension InvalidExtensionTypeParameterCount3<T, S> on int {}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount1 extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount1
+ : super core::Object::•()
+ ;
+}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount2<self2::InvalidClassTypeParameterCount2::T%>
+ : super core::Object::•()
+ ;
+}
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class InvalidClassTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self2::InvalidClassTypeParameterCount3<self2::InvalidClassTypeParameterCount3::T%, self2::InvalidClassTypeParameterCount3::S%>
+ : super core::Object::•()
+ ;
+}
+@#C1
+extension InvalidExtensionTypeParameterCount1 on core::int {
+}
+@#C1
+extension InvalidExtensionTypeParameterCount2<T extends core::Object? = dynamic> on core::int {
+}
+@#C1
+extension InvalidExtensionTypeParameterCount3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> on core::int {
+}
+
+constants {
+ #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/invalid_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/invalid_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/invalid_patch/origin_lib.dart b/pkg/front_end/testcases/general/invalid_patch/origin_lib.dart
new file mode 100644
index 0000000..d83a119
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/origin_lib.dart
@@ -0,0 +1,15 @@
+// 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.
+
+class InvalidClassTypeParameterCount1 {}
+
+class InvalidClassTypeParameterCount2<T> {}
+
+class InvalidClassTypeParameterCount3<T, S> {}
+
+extension InvalidExtensionTypeParameterCount1 on int {}
+
+extension InvalidExtensionTypeParameterCount2<T> on int {}
+
+extension InvalidExtensionTypeParameterCount3<T, S> on int {}
diff --git a/pkg/front_end/testcases/general/invalid_patch/patch_lib.dart b/pkg/front_end/testcases/general/invalid_patch/patch_lib.dart
new file mode 100644
index 0000000..e7e4e9c
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_patch/patch_lib.dart
@@ -0,0 +1,24 @@
+// 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.
+
+// ignore: import_internal_library
+import 'dart:_internal';
+
+@patch
+class InvalidClassTypeParameterCount1<T> /* Error */ {}
+
+@patch
+class InvalidClassTypeParameterCount2 /* Error */ {}
+
+@patch
+class InvalidClassTypeParameterCount3<T> /* Error */ {}
+
+@patch
+extension InvalidExtensionTypeParameterCount1<T> on int /* Error */ {}
+
+@patch
+extension InvalidExtensionTypeParameterCount2 on int /* Error */ {}
+
+@patch
+extension InvalidExtensionTypeParameterCount3<T> on int /* Error */ {}
diff --git a/pkg/front_end/testcases/general/patch_internal/internal_lib.dart b/pkg/front_end/testcases/general/patch_internal/internal_lib.dart
new file mode 100644
index 0000000..8d70e16
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/internal_lib.dart
@@ -0,0 +1,7 @@
+// 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 'dart:test';
+
+class ClassImpl implements Class {}
diff --git a/pkg/front_end/testcases/general/patch_internal/libraries.json b/pkg/front_end/testcases/general/patch_internal/libraries.json
new file mode 100644
index 0000000..4ee8fa5
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/libraries.json
@@ -0,0 +1,16 @@
+{
+ "vm": {
+ "comment:0": "This adds to the default libraries found in the platform.",
+ "libraries": {
+ "test": {
+ "patches": [
+ "patch_lib.dart"
+ ],
+ "uri": "origin_lib.dart"
+ },
+ "_test_internal": {
+ "uri": "internal_lib.dart"
+ }
+ }
+ }
+}
diff --git a/pkg/front_end/testcases/general/patch_internal/main.dart b/pkg/front_end/testcases/general/patch_internal/main.dart
new file mode 100644
index 0000000..9e5172c
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/main.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 'dart:test';
+
+main() {
+ new Class();
+}
diff --git a/pkg/front_end/testcases/general/patch_internal/main.dart.strong.expect b/pkg/front_end/testcases/general/patch_internal/main.dart.strong.expect
new file mode 100644
index 0000000..a0b5275
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/main.dart.strong.expect
@@ -0,0 +1,42 @@
+library;
+import self as self;
+import "dart:_test_internal" as _te;
+
+import "dart:test";
+
+static method main() → dynamic {
+ new _te::ClassImpl::•();
+}
+
+library;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+import "dart:_test_internal" as _te;
+
+import "dart:_internal";
+import "dart:_test_internal";
+
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class Class extends core::Object {
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ •() → self2::Class /* redirection-target: _te::ClassImpl::• */
+ return new _te::ClassImpl::•();
+}
+
+library /*isUnsupported*/;
+import self as _te;
+import "dart:core" as core;
+import "dart:test" as self2;
+
+import "dart:test";
+
+class ClassImpl extends core::Object implements self2::Class {
+ synthetic constructor •() → _te::ClassImpl
+ : super core::Object::•()
+ ;
+}
+
+constants {
+ #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/patch_internal/main.dart.strong.modular.expect b/pkg/front_end/testcases/general/patch_internal/main.dart.strong.modular.expect
new file mode 100644
index 0000000..a0b5275
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/main.dart.strong.modular.expect
@@ -0,0 +1,42 @@
+library;
+import self as self;
+import "dart:_test_internal" as _te;
+
+import "dart:test";
+
+static method main() → dynamic {
+ new _te::ClassImpl::•();
+}
+
+library;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+import "dart:_test_internal" as _te;
+
+import "dart:_internal";
+import "dart:_test_internal";
+
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class Class extends core::Object {
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ •() → self2::Class /* redirection-target: _te::ClassImpl::• */
+ return new _te::ClassImpl::•();
+}
+
+library /*isUnsupported*/;
+import self as _te;
+import "dart:core" as core;
+import "dart:test" as self2;
+
+import "dart:test";
+
+class ClassImpl extends core::Object implements self2::Class {
+ synthetic constructor •() → _te::ClassImpl
+ : super core::Object::•()
+ ;
+}
+
+constants {
+ #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/patch_internal/main.dart.strong.outline.expect b/pkg/front_end/testcases/general/patch_internal/main.dart.strong.outline.expect
new file mode 100644
index 0000000..8f6d2b5
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/main.dart.strong.outline.expect
@@ -0,0 +1,41 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+ ;
+
+library;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+import "dart:_test_internal" as _te;
+
+import "dart:_internal";
+import "dart:_test_internal";
+
+@/* from org-dartlang-testcase:///patch_lib.dart */ _in::patch
+class Class extends core::Object {
+ @_in::patch
+ external static factory •() → self2::Class /* redirection-target: _te::ClassImpl::• */
+ return new _te::ClassImpl::•();
+}
+
+library /*isUnsupported*/;
+import self as _te;
+import "dart:core" as core;
+import "dart:test" as self2;
+
+import "dart:test";
+
+class ClassImpl extends core::Object implements self2::Class {
+ synthetic constructor •() → _te::ClassImpl
+ ;
+}
+
+
+Extra constant evaluation status:
+Evaluated: FileUriExpression @ org-dartlang-testcase:///patch_lib.dart:9:1 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 3, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/patch_internal/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/patch_internal/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..a0b5275
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/main.dart.strong.transformed.expect
@@ -0,0 +1,42 @@
+library;
+import self as self;
+import "dart:_test_internal" as _te;
+
+import "dart:test";
+
+static method main() → dynamic {
+ new _te::ClassImpl::•();
+}
+
+library;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+import "dart:_test_internal" as _te;
+
+import "dart:_internal";
+import "dart:_test_internal";
+
+@/* from org-dartlang-testcase:///patch_lib.dart */ #C1
+class Class extends core::Object {
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ •() → self2::Class /* redirection-target: _te::ClassImpl::• */
+ return new _te::ClassImpl::•();
+}
+
+library /*isUnsupported*/;
+import self as _te;
+import "dart:core" as core;
+import "dart:test" as self2;
+
+import "dart:test";
+
+class ClassImpl extends core::Object implements self2::Class {
+ synthetic constructor •() → _te::ClassImpl
+ : super core::Object::•()
+ ;
+}
+
+constants {
+ #C1 = _in::_Patch {}
+}
diff --git a/pkg/front_end/testcases/general/patch_internal/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/patch_internal/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/patch_internal/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/patch_internal/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/patch_internal/origin_lib.dart b/pkg/front_end/testcases/general/patch_internal/origin_lib.dart
new file mode 100644
index 0000000..76d3e5f
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/origin_lib.dart
@@ -0,0 +1,7 @@
+// 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.
+
+class Class {
+ external factory Class();
+}
diff --git a/pkg/front_end/testcases/general/patch_internal/patch_lib.dart b/pkg/front_end/testcases/general/patch_internal/patch_lib.dart
new file mode 100644
index 0000000..0afb1b5
--- /dev/null
+++ b/pkg/front_end/testcases/general/patch_internal/patch_lib.dart
@@ -0,0 +1,13 @@
+// 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.
+
+// ignore: import_internal_library
+import 'dart:_internal';
+import 'dart:_test_internal';
+
+@patch
+class Class {
+ @patch
+ factory Class() = ClassImpl;
+}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 769106e..b7108eb 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -95,6 +95,7 @@
general/factory_patch/main: SemiFuzzFailure
general/inject_private_patch/main: SemiFuzzFailure
general/inject_public/main: SemiFuzzFailure
+general/invalid_patch/main: SemiFuzzFailure
general/issue45101/main: SemiFuzzFailure
general/mixin_from_patch/main: SemiFuzzFailure
general/multiple_class_patches/main: SemiFuzzFailure
@@ -105,6 +106,7 @@
general/patch_extends_implements/main: SemiFuzzFailure
general/patch_extension_scope/main: SemiFuzzFailure
general/patch_getter/main: SemiFuzzFailure
+general/patch_internal/main: SemiFuzzFailure
general/patch_prefix_access/main: SemiFuzzFailure
general/patch_type_parameters/main: SemiFuzzFailure
general/tear_off_patch/main: SemiFuzzFailure