diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart index 72487895a9c..779de84b6a4 100644 --- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart +++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart @@ -7814,6 +7814,46 @@ Message _withArgumentsNonAsciiWhitespace(int codePoint) { arguments: {'unicode': codePoint}); } +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const Template< + Message Function( + String + name)> templateNonAugmentationClassMemberConflict = const Template< + Message Function(String name)>( + problemMessageTemplate: + r"""Member '#name' conflicts with an existing member of the same name in the augmented class.""", + correctionMessageTemplate: + r"""Try changing the name to an existing member or adding an 'augment' modifier.""", + withArguments: _withArgumentsNonAugmentationClassMemberConflict); + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const Code + codeNonAugmentationClassMemberConflict = + const Code( + "NonAugmentationClassMemberConflict", +); + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +Message _withArgumentsNonAugmentationClassMemberConflict(String name) { + if (name.isEmpty) throw 'No name provided'; + name = demangleMixinApplicationName(name); + return new Message(codeNonAugmentationClassMemberConflict, + problemMessage: + """Member '${name}' conflicts with an existing member of the same name in the augmented class.""", + correctionMessage: """Try changing the name to an existing member or adding an 'augment' modifier.""", + arguments: {'name': name}); +} + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const Code codeNonAugmentationClassMemberConflictCause = + messageNonAugmentationClassMemberConflictCause; + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const MessageCode messageNonAugmentationClassMemberConflictCause = + const MessageCode("NonAugmentationClassMemberConflictCause", + severity: Severity.context, + problemMessage: r"""This is the existing member."""); + // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. const Code codeNonConstConstructor = messageNonConstConstructor; @@ -10394,6 +10434,35 @@ const MessageCode messageUnexpectedTokens = const MessageCode( index: 123, problemMessage: r"""Unexpected tokens."""); +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const Template< + Message Function( + String + name)> templateUnmatchedAugmentationClassMember = const Template< + Message Function(String name)>( + problemMessageTemplate: + r"""Augmentation member '#name' doesn't match a member in the augmented class.""", + correctionMessageTemplate: + r"""Try changing the name to an existing member or removing the 'augment' modifier.""", + withArguments: _withArgumentsUnmatchedAugmentationClassMember); + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const Code codeUnmatchedAugmentationClassMember = + const Code( + "UnmatchedAugmentationClassMember", +); + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +Message _withArgumentsUnmatchedAugmentationClassMember(String name) { + if (name.isEmpty) throw 'No name provided'; + name = demangleMixinApplicationName(name); + return new Message(codeUnmatchedAugmentationClassMember, + problemMessage: + """Augmentation member '${name}' doesn't match a member in the augmented class.""", + correctionMessage: """Try changing the name to an existing member or removing the 'augment' modifier.""", + arguments: {'name': name}); +} + // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. const Template templateUnmatchedToken = diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart index f93f47eda0a..e4a28398142 100644 --- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart +++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart @@ -1374,7 +1374,7 @@ class ClassMembersNodeBuilder { if (classBuilder is SourceClassBuilder && !declaredMember.isStatic) { assert( declaredMember.isSourceDeclaration && - declaredMember.classBuilder == classBuilder, + declaredMember.classBuilder.origin == classBuilder, "Only declared members can override: ${declaredMember}"); hasDeclaredMembers = true; if (declaredMember.isProperty) { diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart index ef9097399e7..ab0037c5054 100644 --- a/pkg/front_end/lib/src/fasta/scope.dart +++ b/pkg/front_end/lib/src/fasta/scope.dart @@ -809,6 +809,15 @@ mixin ErroneousMemberBuilderMixin implements SourceMemberBuilder { @override bool get isConflictingSetter => false; + @override + bool get isConflictingAugmentationMember => false; + + @override + void set isConflictingAugmentationMember(bool value) { + throw new UnsupportedError( + 'AmbiguousMemberBuilder.isConflictingAugmentationMember='); + } + @override void set parent(Builder? value) { throw new UnsupportedError('AmbiguousMemberBuilder.parent='); @@ -861,6 +870,11 @@ mixin ErroneousMemberBuilderMixin implements SourceMemberBuilder { SourceLibraryBuilder library, TypeEnvironment typeEnvironment) { assert(false, "Unexpected call to $runtimeType.checkVariance."); } + + @override + bool get isAugmentation { + throw new UnsupportedError('AmbiguousMemberBuilder.isAugmentation'); + } } class AmbiguousMemberBuilder extends AmbiguousBuilder diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart index 102db7f3c3a..f24406dd539 100644 --- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart +++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart @@ -158,15 +158,17 @@ class SourceClassBuilder extends ClassBuilderImpl void buildBuilders(String name, Builder? declaration) { while (declaration != null) { if (declaration.parent != this) { - if (fileUri != declaration.parent?.fileUri) { - unexpected("$fileUri", "${declaration.parent?.fileUri}", charOffset, - fileUri); - } else { - unexpected( - fullNameForErrors, - declaration.parent?.fullNameForErrors ?? '', - charOffset, - fileUri); + if (declaration.parent?.origin != this) { + if (fileUri != declaration.parent?.fileUri) { + unexpected("$fileUri", "${declaration.parent?.fileUri}", + charOffset, fileUri); + } else { + unexpected( + fullNameForErrors, + declaration.parent?.fullNameForErrors ?? '', + charOffset, + fileUri); + } } } else if (declaration is SourceMemberBuilder) { SourceMemberBuilder memberBuilder = declaration; @@ -175,7 +177,8 @@ class SourceClassBuilder extends ClassBuilderImpl member.parent = cls; if (!memberBuilder.isPatch && !memberBuilder.isDuplicate && - !memberBuilder.isConflictingSetter) { + !memberBuilder.isConflictingSetter && + !memberBuilder.isConflictingAugmentationMember) { if (member is Procedure) { cls.addProcedure(member); } else if (member is Field) { @@ -602,21 +605,71 @@ class SourceClassBuilder extends ClassBuilderImpl if (patch is SourceClassBuilder) { patch.actualOrigin = this; (_patches ??= []).add(patch); - // TODO(ahe): Complain if `patch.supertype` isn't null. - scope.forEachLocalMember((String name, Builder member) { - Builder? memberPatch = - patch.scope.lookupLocalMember(name, setter: false); - if (memberPatch != null) { - member.applyPatch(memberPatch); + + void applyAugmentation(String name, SourceMemberBuilder patchMember, + {required bool setter}) { + Builder? originMember = scope.lookupLocalMember(name, setter: setter); + if (patch.isAugmentation) { + if (originMember != null) { + if (patchMember.isAugmentation) { + originMember.applyPatch(patchMember); + } else { + patchMember.isConflictingAugmentationMember = true; + library.addProblem( + templateNonAugmentationClassMemberConflict + .withArguments(name), + patchMember.charOffset, + name.length, + patchMember.fileUri, + context: [ + messageNonAugmentationClassMemberConflictCause.withLocation( + originMember.fileUri!, + originMember.charOffset, + name.length) + ]); + } + } else { + if (patchMember.isAugmentation) { + library.addProblem( + templateUnmatchedAugmentationClassMember.withArguments(name), + patchMember.charOffset, + name.length, + patchMember.fileUri); + } else { + scope.addLocalMember(name, patchMember, setter: setter); + } + } + } else { + if (originMember != null) { + // Patch class implicitly assume matching members are patch + // members. + originMember.applyPatch(patchMember); + } else { + // Members injected into patch are not part of the origin scope. + } + } + } + + patch.scope.forEachLocalMember((String name, Builder patchMember) { + if (patchMember is SourceMemberBuilder) { + applyAugmentation(name, patchMember, setter: false); + } else { + assert(false, + "Unexpected member ${patchMember} (${patchMember.runtimeType})"); } }); - scope.forEachLocalSetter((String name, Builder member) { - Builder? memberPatch = - patch.scope.lookupLocalMember(name, setter: true); - if (memberPatch != null) { - member.applyPatch(memberPatch); + + patch.scope.forEachLocalSetter((String name, Builder patchMember) { + if (patchMember is SourceMemberBuilder) { + applyAugmentation(name, patchMember, setter: true); + } else { + assert(false, + "Unexpected member ${patchMember} (${patchMember.runtimeType})"); } }); + + // TODO(johnniwinther): Should we support constructor augmentation? + // Currently the syntax doesn't allow it. constructors.local.forEach((String name, Builder member) { Builder? memberPatch = patch.constructors.local[name]; if (memberPatch != null) { diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart index bb1a2546f1e..ce1548cc5d1 100644 --- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart +++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart @@ -798,7 +798,10 @@ class SourceLibraryBuilder extends LibraryBuilderImpl { } } else { resolvedUri = resolve(this.importUri, uri, uriOffset); - builder = loader.read(resolvedUri, uriOffset, accessor: this); + builder = loader.read(resolvedUri, uriOffset, + origin: isAugmentationImport ? this : null, + accessor: this, + isAugmentation: isAugmentationImport); } imports.add(new Import( diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart index 68f2d847c2e..257a4b82465 100644 --- a/pkg/front_end/lib/src/fasta/source/source_loader.dart +++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart @@ -321,7 +321,8 @@ class SourceLoader extends Loader { required LanguageVersion packageLanguageVersion, SourceLibraryBuilder? origin, Library? referencesFrom, - bool? referenceIsPartOwner}) { + bool? referenceIsPartOwner, + bool isAugmentation: false}) { return new SourceLibraryBuilder( importUri: importUri, fileUri: fileUri, @@ -334,7 +335,7 @@ class SourceLoader extends Loader { isUnsupported: origin?.library.isUnsupported ?? importUri.isScheme('dart') && !target.uriTranslator.isLibrarySupported(importUri.path), - isAugmentation: false); + isAugmentation: isAugmentation); } /// Return `"true"` if the [dottedName] is a 'dart.library.*' qualifier for a @@ -364,7 +365,8 @@ class SourceLoader extends Loader { Uri? fileUri, SourceLibraryBuilder? origin, Library? referencesFrom, - bool? referenceIsPartOwner) { + bool? referenceIsPartOwner, + bool isAugmentation) { if (fileUri != null && (fileUri.isScheme("dart") || fileUri.isScheme("package") || @@ -444,7 +446,8 @@ class SourceLoader extends Loader { packageLanguageVersion: packageLanguageVersion, origin: origin, referencesFrom: referencesFrom, - referenceIsPartOwner: referenceIsPartOwner); + referenceIsPartOwner: referenceIsPartOwner, + isAugmentation: isAugmentation); if (packageLanguageVersionProblem != null) { libraryBuilder.addPostponedProblem( packageLanguageVersionProblem, 0, noLength, libraryBuilder.fileUri); @@ -556,12 +559,14 @@ class SourceLoader extends Loader { required LibraryBuilder accessor, LibraryBuilder? origin, Library? referencesFrom, - bool? referenceIsPartOwner}) { + bool? referenceIsPartOwner, + bool isAugmentation: false}) { LibraryBuilder libraryBuilder = _read(uri, fileUri: fileUri, origin: origin, referencesFrom: referencesFrom, - referenceIsPartOwner: referenceIsPartOwner); + referenceIsPartOwner: referenceIsPartOwner, + isAugmentation: isAugmentation); libraryBuilder.recordAccess(charOffset, noLength, accessor.fileUri); if (!_hasLibraryAccess(imported: uri, importer: accessor.importUri) && !accessor.isPatch) { @@ -617,7 +622,8 @@ class SourceLoader extends Loader { {Uri? fileUri, LibraryBuilder? origin, Library? referencesFrom, - bool? referenceIsPartOwner}) { + bool? referenceIsPartOwner, + bool isAugmentation: false}) { LibraryBuilder? libraryBuilder = _builders[uri]; if (libraryBuilder == null) { if (target.dillTarget.isLoaded) { @@ -629,7 +635,8 @@ class SourceLoader extends Loader { fileUri, origin as SourceLibraryBuilder?, referencesFrom, - referenceIsPartOwner); + referenceIsPartOwner, + isAugmentation); } _builders[uri] = libraryBuilder; } diff --git a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart index fcdfb76baac..f4cf938c1db 100644 --- a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart +++ b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart @@ -14,6 +14,7 @@ import '../builder/declaration_builder.dart'; import '../builder/library_builder.dart'; import '../builder/member_builder.dart'; import '../kernel/kernel_helper.dart'; +import '../modifier.dart'; import '../problems.dart' show unsupported; import '../source/source_library_builder.dart'; import '../type_inference/type_inference_engine.dart' @@ -42,6 +43,14 @@ abstract class SourceMemberBuilder implements MemberBuilder { /// Checks the signature types of this member. void checkTypes( SourceLibraryBuilder library, TypeEnvironment typeEnvironment); + + /// Returns `true` if this member is an augmentation. + bool get isAugmentation; + + /// Returns `true` if this member is a member declared in an augmentation + /// library that conflicts with a member in the origin library. + bool get isConflictingAugmentationMember; + void set isConflictingAugmentationMember(bool value); } mixin SourceMemberBuilderMixin implements SourceMemberBuilder { @@ -54,6 +63,18 @@ mixin SourceMemberBuilderMixin implements SourceMemberBuilder { SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) { assert(false, "Unexpected call to $runtimeType.buildMembers."); } + + @override + bool get isAugmentation => false; + + @override + bool get isConflictingAugmentationMember => false; + + @override + void set isConflictingAugmentationMember(bool value) { + assert(false, + "Unexpected call to $runtimeType.isConflictingAugmentationMember="); + } } abstract class SourceMemberBuilderImpl extends MemberBuilderImpl @@ -68,6 +89,9 @@ abstract class SourceMemberBuilderImpl extends MemberBuilderImpl bool get isRedirectingGenerativeConstructor => false; + @override + bool get isAugmentation => modifiers & augmentMask != 0; + bool? _isConflictingSetter; @override @@ -81,6 +105,20 @@ abstract class SourceMemberBuilderImpl extends MemberBuilderImpl _isConflictingSetter = value; } + bool? _isConflictingAugmentationMember; + + @override + bool get isConflictingAugmentationMember { + return _isConflictingAugmentationMember ??= false; + } + + @override + void set isConflictingAugmentationMember(bool value) { + assert(_isConflictingAugmentationMember == null, + '$this.isConflictingAugmentationMember has already been fixed.'); + _isConflictingAugmentationMember = value; + } + // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface. @override ProcedureKind? get kind => unsupported("kind", charOffset, fileUri); diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status index b2e67dc1e73..5ff0e553d3e 100644 --- a/pkg/front_end/messages.status +++ b/pkg/front_end/messages.status @@ -644,6 +644,8 @@ NonAgnosticConstant/analyzerCode: Fail NonAgnosticConstant/example: Fail NonAsciiIdentifier/expression: Fail NonAsciiIdentifier/part_wrapped_expression: Fail +NonAugmentationClassMemberConflict/analyzerCode: Fail +NonAugmentationClassMemberConflict/example: Fail NonConstConstructor/example: Fail NonConstFactory/example: Fail NonInstanceTypeVariableUse/example: Fail @@ -849,6 +851,8 @@ UndefinedExtensionSetter/analyzerCode: Fail UndefinedExtensionSetter/example: Fail UnexpectedToken/part_wrapped_script1: Fail UnexpectedToken/script1: Fail +UnmatchedAugmentationClassMember/analyzerCode: Fail +UnmatchedAugmentationClassMember/example: Fail UnmatchedToken/part_wrapped_script1: Fail UnmatchedToken/part_wrapped_script3: Fail UnmatchedToken/script1: Fail diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml index b3403f3e942..8e6f4151b86 100644 --- a/pkg/front_end/messages.yaml +++ b/pkg/front_end/messages.yaml @@ -5507,3 +5507,15 @@ EnumImplementerContainsValuesDeclaration: MacroClassNotDeclaredMacro: problemMessage: "Non-abstract class '#name' implements 'Macro' but isn't declared as a macro class." correctionMessage: "Try adding the 'macro' class modifier." + +UnmatchedAugmentationClassMember: + problemMessage: "Augmentation member '#name' doesn't match a member in the augmented class." + correctionMessage: "Try changing the name to an existing member or removing the 'augment' modifier." + +NonAugmentationClassMemberConflict: + problemMessage: "Member '#name' conflicts with an existing member of the same name in the augmented class." + correctionMessage: "Try changing the name to an existing member or adding an 'augment' modifier." + +NonAugmentationClassMemberConflictCause: + problemMessage: "This is the existing member." + severity: CONTEXT diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro2.dart b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro2.dart index a444cf03953..6173f58be42 100644 --- a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro2.dart +++ b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro2.dart @@ -15,8 +15,10 @@ class Macro2 implements ClassDeclarationsMacro { @override FutureOr buildDeclarationsForClass(ClassDeclaration clazz, ClassMemberDeclarationBuilder builder) { - builder.declareInClass(new DeclarationCode.fromString(''' + if (isMacro) { + builder.declareInClass(new DeclarationCode.fromString(''' hasMacro() => true; ''')); + } } } diff --git a/pkg/front_end/test/macro_application/data/tests/to_string.dart.expect b/pkg/front_end/test/macro_application/data/tests/to_string.dart.expect index 3a56029204f..68d6ea1c939 100644 --- a/pkg/front_end/test/macro_application/data/tests/to_string.dart.expect +++ b/pkg/front_end/test/macro_application/data/tests/to_string.dart.expect @@ -12,7 +12,7 @@ class A extends core::Object { synthetic constructor •() → self::A : super core::Object::•() ; - method /* from org-dartlang-augmentation:/a/b/c/main.dart-0 */ toString() → dynamic { + method /* from org-dartlang-augmentation:/a/b/c/main.dart-0 */ toString() → core::String { return "A(a=${this.{self::A::a}{dynamic}},b=${this.{self::A::b}{dynamic}})"; } } @@ -24,7 +24,7 @@ class B extends core::Object { synthetic constructor •() → self::B : super core::Object::•() ; - method /* from org-dartlang-augmentation:/a/b/c/main.dart-1 */ toString() → dynamic { + method /* from org-dartlang-augmentation:/a/b/c/main.dart-1 */ toString() → core::String { return "B(c=${this.{self::B::c}{dynamic}},d=${this.{self::B::d}{dynamic}},e=${this.{self::B::e}{dynamic}})"; } } diff --git a/pkg/front_end/test/spell_checking_list_messages.txt b/pkg/front_end/test/spell_checking_list_messages.txt index e6964cdc50e..664608e47db 100644 --- a/pkg/front_end/test/spell_checking_list_messages.txt +++ b/pkg/front_end/test/spell_checking_list_messages.txt @@ -16,6 +16,9 @@ adjusting api argument(s) assigning +augment +augmentation +augmented b c compilercontext.runincontext diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt index 7313d713260..0a0575a7090 100644 --- a/pkg/front_end/test/spell_checking_list_tests.txt +++ b/pkg/front_end/test/spell_checking_list_tests.txt @@ -41,6 +41,7 @@ asserter assure asterisk atomic +augmented auth authority autobianchi diff --git a/pkg/front_end/testcases/macros/class_members.dart b/pkg/front_end/testcases/macros/class_members.dart new file mode 100644 index 00000000000..12aa81825ee --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2022, 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 augment 'class_members_lib.dart'; + +class Class { + void existingMethod() { + print('existingMethod-origin'); + } + + external void augmentedMethod(); + + void set existingSetter(_) { + print('existingSetter-origin'); + } + + external void set augmentedSetter(_); +} + +test(Class c) { + c.orphanedMethod(); + c.orphanedSetter = 0; +} + +main() { + Class c = new Class(); + c.augmentedMethod(); + c.injectedMethod(); + c.existingMethod(); + + c.augmentedSetter = 0; + c.injectedSetter = 0; + c.existingSetter = 0; + + injectedMethod(c); +} \ No newline at end of file diff --git a/pkg/front_end/testcases/macros/class_members.dart.strong.expect b/pkg/front_end/testcases/macros/class_members.dart.strong.expect new file mode 100644 index 00000000000..52ceebad4e5 --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members.dart.strong.expect @@ -0,0 +1,111 @@ +library /*isNonNullableByDefault*/; +// +// Problems in library: +// +// pkg/front_end/testcases/macros/class_members_lib.dart:9:8: Error: Member 'existingMethod' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:8:8: Context: This is the existing member. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:15:16: Error: Augmentation member 'orphanedMethod' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void orphanedMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:21:12: Error: Member 'existingSetter' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:14:12: Context: This is the existing member. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:27:20: Error: Augmentation member 'orphanedSetter' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void set orphanedSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. +// c.orphanedMethod(); +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. +// c.orphanedSetter = 0; +// ^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +import "org-dartlang-testcase:///class_members.dart"; + +class Class extends core::Object { + synthetic constructor •() → self::Class + : super core::Object::•() + ; + method existingMethod() → void { + core::print("existingMethod-origin"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedMethod() → void { + core::print("augmentedMethod"); + } + set existingSetter(dynamic _) → void { + core::print("existingSetter-origin"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedSetter(dynamic _) → void { + core::print("augmentedSetter"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod() → void { + core::print("injectedMethod"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedMethod() → void { + core::print("orphanedMethod"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ injectedSetter(dynamic _) → void { + core::print("injectedSetter"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedSetter(dynamic _) → void { + core::print("orphanedSetter"); + } +} +static method test(self::Class c) → dynamic { + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. + c.orphanedMethod(); + ^^^^^^^^^^^^^^" in c{}.orphanedMethod(); + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. + c.orphanedSetter = 0; + ^^^^^^^^^^^^^^" in c{}.orphanedSetter = 0; +} +static method main() → dynamic { + self::Class c = new self::Class::•(); + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; + self::injectedMethod(c); +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentTest(self::Class c) → void { + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedSetter} = 0; +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod(self::Class c) → void { + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; +} diff --git a/pkg/front_end/testcases/macros/class_members.dart.strong.transformed.expect b/pkg/front_end/testcases/macros/class_members.dart.strong.transformed.expect new file mode 100644 index 00000000000..52ceebad4e5 --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members.dart.strong.transformed.expect @@ -0,0 +1,111 @@ +library /*isNonNullableByDefault*/; +// +// Problems in library: +// +// pkg/front_end/testcases/macros/class_members_lib.dart:9:8: Error: Member 'existingMethod' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:8:8: Context: This is the existing member. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:15:16: Error: Augmentation member 'orphanedMethod' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void orphanedMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:21:12: Error: Member 'existingSetter' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:14:12: Context: This is the existing member. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:27:20: Error: Augmentation member 'orphanedSetter' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void set orphanedSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. +// c.orphanedMethod(); +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. +// c.orphanedSetter = 0; +// ^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +import "org-dartlang-testcase:///class_members.dart"; + +class Class extends core::Object { + synthetic constructor •() → self::Class + : super core::Object::•() + ; + method existingMethod() → void { + core::print("existingMethod-origin"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedMethod() → void { + core::print("augmentedMethod"); + } + set existingSetter(dynamic _) → void { + core::print("existingSetter-origin"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedSetter(dynamic _) → void { + core::print("augmentedSetter"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod() → void { + core::print("injectedMethod"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedMethod() → void { + core::print("orphanedMethod"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ injectedSetter(dynamic _) → void { + core::print("injectedSetter"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedSetter(dynamic _) → void { + core::print("orphanedSetter"); + } +} +static method test(self::Class c) → dynamic { + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. + c.orphanedMethod(); + ^^^^^^^^^^^^^^" in c{}.orphanedMethod(); + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. + c.orphanedSetter = 0; + ^^^^^^^^^^^^^^" in c{}.orphanedSetter = 0; +} +static method main() → dynamic { + self::Class c = new self::Class::•(); + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; + self::injectedMethod(c); +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentTest(self::Class c) → void { + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedSetter} = 0; +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod(self::Class c) → void { + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; +} diff --git a/pkg/front_end/testcases/macros/class_members.dart.textual_outline.expect b/pkg/front_end/testcases/macros/class_members.dart.textual_outline.expect new file mode 100644 index 00000000000..c5c8d442f39 --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members.dart.textual_outline.expect @@ -0,0 +1,9 @@ +import augment 'class_members_lib.dart'; +class Class { + void existingMethod() {} + external void augmentedMethod(); + void set existingSetter(_) {} + external void set augmentedSetter(_); +} +test(Class c) {} +main() {} diff --git a/pkg/front_end/testcases/macros/class_members.dart.weak.expect b/pkg/front_end/testcases/macros/class_members.dart.weak.expect new file mode 100644 index 00000000000..52ceebad4e5 --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members.dart.weak.expect @@ -0,0 +1,111 @@ +library /*isNonNullableByDefault*/; +// +// Problems in library: +// +// pkg/front_end/testcases/macros/class_members_lib.dart:9:8: Error: Member 'existingMethod' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:8:8: Context: This is the existing member. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:15:16: Error: Augmentation member 'orphanedMethod' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void orphanedMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:21:12: Error: Member 'existingSetter' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:14:12: Context: This is the existing member. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:27:20: Error: Augmentation member 'orphanedSetter' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void set orphanedSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. +// c.orphanedMethod(); +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. +// c.orphanedSetter = 0; +// ^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +import "org-dartlang-testcase:///class_members.dart"; + +class Class extends core::Object { + synthetic constructor •() → self::Class + : super core::Object::•() + ; + method existingMethod() → void { + core::print("existingMethod-origin"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedMethod() → void { + core::print("augmentedMethod"); + } + set existingSetter(dynamic _) → void { + core::print("existingSetter-origin"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedSetter(dynamic _) → void { + core::print("augmentedSetter"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod() → void { + core::print("injectedMethod"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedMethod() → void { + core::print("orphanedMethod"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ injectedSetter(dynamic _) → void { + core::print("injectedSetter"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedSetter(dynamic _) → void { + core::print("orphanedSetter"); + } +} +static method test(self::Class c) → dynamic { + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. + c.orphanedMethod(); + ^^^^^^^^^^^^^^" in c{}.orphanedMethod(); + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. + c.orphanedSetter = 0; + ^^^^^^^^^^^^^^" in c{}.orphanedSetter = 0; +} +static method main() → dynamic { + self::Class c = new self::Class::•(); + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; + self::injectedMethod(c); +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentTest(self::Class c) → void { + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedSetter} = 0; +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod(self::Class c) → void { + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; +} diff --git a/pkg/front_end/testcases/macros/class_members.dart.weak.modular.expect b/pkg/front_end/testcases/macros/class_members.dart.weak.modular.expect new file mode 100644 index 00000000000..52ceebad4e5 --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members.dart.weak.modular.expect @@ -0,0 +1,111 @@ +library /*isNonNullableByDefault*/; +// +// Problems in library: +// +// pkg/front_end/testcases/macros/class_members_lib.dart:9:8: Error: Member 'existingMethod' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:8:8: Context: This is the existing member. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:15:16: Error: Augmentation member 'orphanedMethod' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void orphanedMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:21:12: Error: Member 'existingSetter' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:14:12: Context: This is the existing member. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:27:20: Error: Augmentation member 'orphanedSetter' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void set orphanedSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. +// c.orphanedMethod(); +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. +// c.orphanedSetter = 0; +// ^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +import "org-dartlang-testcase:///class_members.dart"; + +class Class extends core::Object { + synthetic constructor •() → self::Class + : super core::Object::•() + ; + method existingMethod() → void { + core::print("existingMethod-origin"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedMethod() → void { + core::print("augmentedMethod"); + } + set existingSetter(dynamic _) → void { + core::print("existingSetter-origin"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedSetter(dynamic _) → void { + core::print("augmentedSetter"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod() → void { + core::print("injectedMethod"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedMethod() → void { + core::print("orphanedMethod"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ injectedSetter(dynamic _) → void { + core::print("injectedSetter"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedSetter(dynamic _) → void { + core::print("orphanedSetter"); + } +} +static method test(self::Class c) → dynamic { + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. + c.orphanedMethod(); + ^^^^^^^^^^^^^^" in c{}.orphanedMethod(); + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. + c.orphanedSetter = 0; + ^^^^^^^^^^^^^^" in c{}.orphanedSetter = 0; +} +static method main() → dynamic { + self::Class c = new self::Class::•(); + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; + self::injectedMethod(c); +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentTest(self::Class c) → void { + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedSetter} = 0; +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod(self::Class c) → void { + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; +} diff --git a/pkg/front_end/testcases/macros/class_members.dart.weak.outline.expect b/pkg/front_end/testcases/macros/class_members.dart.weak.outline.expect new file mode 100644 index 00000000000..49e7b5107c3 --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members.dart.weak.outline.expect @@ -0,0 +1,61 @@ +library /*isNonNullableByDefault*/; +// +// Problems in library: +// +// pkg/front_end/testcases/macros/class_members_lib.dart:9:8: Error: Member 'existingMethod' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:8:8: Context: This is the existing member. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:15:16: Error: Augmentation member 'orphanedMethod' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void orphanedMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:21:12: Error: Member 'existingSetter' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:14:12: Context: This is the existing member. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:27:20: Error: Augmentation member 'orphanedSetter' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void set orphanedSetter(_) { +// ^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +import "org-dartlang-testcase:///class_members.dart"; + +class Class extends core::Object { + synthetic constructor •() → self::Class + ; + method existingMethod() → void + ; + external method augmentedMethod() → void; + set existingSetter(dynamic _) → void + ; + external set augmentedSetter(dynamic _) → void; + method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod() → void + ; + method /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedMethod() → void + ; + set /* from org-dartlang-testcase:///class_members_lib.dart */ injectedSetter(dynamic _) → void + ; + set /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedSetter(dynamic _) → void + ; +} +static method test(self::Class c) → dynamic + ; +static method main() → dynamic + ; +static method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentTest(self::Class c) → void + ; +static method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod(self::Class c) → void + ; diff --git a/pkg/front_end/testcases/macros/class_members.dart.weak.transformed.expect b/pkg/front_end/testcases/macros/class_members.dart.weak.transformed.expect new file mode 100644 index 00000000000..52ceebad4e5 --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members.dart.weak.transformed.expect @@ -0,0 +1,111 @@ +library /*isNonNullableByDefault*/; +// +// Problems in library: +// +// pkg/front_end/testcases/macros/class_members_lib.dart:9:8: Error: Member 'existingMethod' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:8:8: Context: This is the existing member. +// void existingMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:15:16: Error: Augmentation member 'orphanedMethod' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void orphanedMethod() { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:21:12: Error: Member 'existingSetter' conflicts with an existing member of the same name in the augmented class. +// Try changing the name to an existing member or adding an 'augment' modifier. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// pkg/front_end/testcases/macros/class_members.dart:14:12: Context: This is the existing member. +// void set existingSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members_lib.dart:27:20: Error: Augmentation member 'orphanedSetter' doesn't match a member in the augmented class. +// Try changing the name to an existing member or removing the 'augment' modifier. +// augment void set orphanedSetter(_) { +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. +// c.orphanedMethod(); +// ^^^^^^^^^^^^^^ +// +// pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. +// - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +// Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. +// c.orphanedSetter = 0; +// ^^^^^^^^^^^^^^ +// +import self as self; +import "dart:core" as core; + +import "org-dartlang-testcase:///class_members.dart"; + +class Class extends core::Object { + synthetic constructor •() → self::Class + : super core::Object::•() + ; + method existingMethod() → void { + core::print("existingMethod-origin"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedMethod() → void { + core::print("augmentedMethod"); + } + set existingSetter(dynamic _) → void { + core::print("existingSetter-origin"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ augmentedSetter(dynamic _) → void { + core::print("augmentedSetter"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod() → void { + core::print("injectedMethod"); + } + method /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedMethod() → void { + core::print("orphanedMethod"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ injectedSetter(dynamic _) → void { + core::print("injectedSetter"); + } + set /* from org-dartlang-testcase:///class_members_lib.dart */ orphanedSetter(dynamic _) → void { + core::print("orphanedSetter"); + } +} +static method test(self::Class c) → dynamic { + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:22:5: Error: The method 'orphanedMethod' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing method, or defining a method named 'orphanedMethod'. + c.orphanedMethod(); + ^^^^^^^^^^^^^^" in c{}.orphanedMethod(); + invalid-expression "pkg/front_end/testcases/macros/class_members.dart:23:5: Error: The setter 'orphanedSetter' isn't defined for the class 'Class'. + - 'Class' is from 'pkg/front_end/testcases/macros/class_members.dart'. +Try correcting the name to the name of an existing setter, or defining a setter or field named 'orphanedSetter'. + c.orphanedSetter = 0; + ^^^^^^^^^^^^^^" in c{}.orphanedSetter = 0; +} +static method main() → dynamic { + self::Class c = new self::Class::•(); + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; + self::injectedMethod(c); +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ augmentTest(self::Class c) → void { + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedMethod}(){() → void}; + c.{self::Class::orphanedSetter} = 0; +} +static method /* from org-dartlang-testcase:///class_members_lib.dart */ injectedMethod(self::Class c) → void { + c.{self::Class::augmentedMethod}(){() → void}; + c.{self::Class::injectedMethod}(){() → void}; + c.{self::Class::existingMethod}(){() → void}; + c.{self::Class::augmentedSetter} = 0; + c.{self::Class::injectedSetter} = 0; + c.{self::Class::existingSetter} = 0; +} diff --git a/pkg/front_end/testcases/macros/class_members_lib.dart b/pkg/front_end/testcases/macros/class_members_lib.dart new file mode 100644 index 00000000000..a5952d546cf --- /dev/null +++ b/pkg/front_end/testcases/macros/class_members_lib.dart @@ -0,0 +1,46 @@ +// Copyright (c) 2022, 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. + +augment class Class { + augment void augmentedMethod() { + print('augmentedMethod'); + } + void existingMethod() { + print('existingMethod-duplicate'); + } + void injectedMethod() { + print('injectedMethod'); + } + augment void orphanedMethod() { + print('orphanedMethod'); + } + augment void set augmentedSetter(_) { + print('augmentedSetter'); + } + void set existingSetter(_) { + print('existingSetter-duplicate'); + } + void set injectedSetter(_) { + print('injectedSetter'); + } + augment void set orphanedSetter(_) { + print('orphanedSetter'); + } +} + +void augmentTest(Class c) { + c.orphanedMethod(); + c.orphanedMethod(); + c.orphanedSetter = 0; +} + +void injectedMethod(Class c) { + c.augmentedMethod(); + c.injectedMethod(); + c.existingMethod(); + + c.augmentedSetter = 0; + c.injectedSetter = 0; + c.existingSetter = 0; +} \ No newline at end of file diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status index afa3f8adf00..fbb0de5154d 100644 --- a/pkg/front_end/testcases/textual_outline.status +++ b/pkg/front_end/testcases/textual_outline.status @@ -162,6 +162,7 @@ late_lowering/override_getter_setter: FormatterCrash late_lowering/skip_late_final_uninitialized_instance_fields/main: FormatterCrash late_lowering/uninitialized_non_nullable_late_fields: FormatterCrash macros/augment_class: FormatterCrash +macros/class_members: FormatterCrash macros/macro_class: FormatterCrash nnbd/abstract_field_errors: FormatterCrash nnbd/covariant_late_field: FormatterCrash diff --git a/pkg/front_end/tool/dart_doctest_impl.dart b/pkg/front_end/tool/dart_doctest_impl.dart index 5706ec99ad7..544345dc486 100644 --- a/pkg/front_end/tool/dart_doctest_impl.dart +++ b/pkg/front_end/tool/dart_doctest_impl.dart @@ -918,7 +918,8 @@ class DocTestSourceLoader extends SourceLoader { required LanguageVersion packageLanguageVersion, SourceLibraryBuilder? origin, kernel.Library? referencesFrom, - bool? referenceIsPartOwner}) { + bool? referenceIsPartOwner, + bool isAugmentation: false}) { if (importUri == DocTestIncrementalCompiler.dartDocTestUri) { HybridFileSystem hfs = target.fileSystem as HybridFileSystem; MemoryFileSystem fs = hfs.memory; @@ -935,6 +936,7 @@ class DocTestSourceLoader extends SourceLoader { packageLanguageVersion: packageLanguageVersion, origin: origin, referencesFrom: referencesFrom, - referenceIsPartOwner: referenceIsPartOwner); + referenceIsPartOwner: referenceIsPartOwner, + isAugmentation: isAugmentation); } }