From 345dfd34ac7613cea4ba9f736eb10529982de66d Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Mon, 28 Feb 2022 15:07:18 +0000 Subject: [PATCH] [cfe] Support class member augmentation directly This adds direct support for class member augmentation, including checks that the 'augment' modifier is used correctly. Different from the patch member support, non-augment members added in augment classes are now part of the interface of the class and can therefore be used outside the augmentation library. The CL includes support for using the 'import augment' syntax to import libraries as augmentation libraries. The enable direct testing of the augmentation features in expectation tests. Change-Id: I9961e15862dba827050bec4aceb7dfc45e053d7d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/234520 Reviewed-by: Chloe Stefantsova Commit-Queue: Johnni Winther --- .../lib/src/messages/codes_generated.dart | 69 +++++++++++ .../fasta/kernel/hierarchy/members_node.dart | 2 +- pkg/front_end/lib/src/fasta/scope.dart | 14 +++ .../fasta/source/source_class_builder.dart | 95 +++++++++++---- .../fasta/source/source_library_builder.dart | 5 +- .../lib/src/fasta/source/source_loader.dart | 23 ++-- .../fasta/source/source_member_builder.dart | 38 ++++++ pkg/front_end/messages.status | 4 + pkg/front_end/messages.yaml | 12 ++ .../data/pkgs/macro/lib/macro2.dart | 4 +- .../data/tests/to_string.dart.expect | 4 +- .../test/spell_checking_list_messages.txt | 3 + .../test/spell_checking_list_tests.txt | 1 + .../testcases/macros/class_members.dart | 37 ++++++ .../macros/class_members.dart.strong.expect | 111 ++++++++++++++++++ ...ass_members.dart.strong.transformed.expect | 111 ++++++++++++++++++ .../class_members.dart.textual_outline.expect | 9 ++ .../macros/class_members.dart.weak.expect | 111 ++++++++++++++++++ .../class_members.dart.weak.modular.expect | 111 ++++++++++++++++++ .../class_members.dart.weak.outline.expect | 61 ++++++++++ ...class_members.dart.weak.transformed.expect | 111 ++++++++++++++++++ .../testcases/macros/class_members_lib.dart | 46 ++++++++ .../testcases/textual_outline.status | 1 + pkg/front_end/tool/dart_doctest_impl.dart | 6 +- 24 files changed, 953 insertions(+), 36 deletions(-) create mode 100644 pkg/front_end/testcases/macros/class_members.dart create mode 100644 pkg/front_end/testcases/macros/class_members.dart.strong.expect create mode 100644 pkg/front_end/testcases/macros/class_members.dart.strong.transformed.expect create mode 100644 pkg/front_end/testcases/macros/class_members.dart.textual_outline.expect create mode 100644 pkg/front_end/testcases/macros/class_members.dart.weak.expect create mode 100644 pkg/front_end/testcases/macros/class_members.dart.weak.modular.expect create mode 100644 pkg/front_end/testcases/macros/class_members.dart.weak.outline.expect create mode 100644 pkg/front_end/testcases/macros/class_members.dart.weak.transformed.expect create mode 100644 pkg/front_end/testcases/macros/class_members_lib.dart 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); } }