Version 2.17.0-154.0.dev

Merge commit 'f8ef1b7f427371e62297b60a18eb96ede01464fa' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3be94d5..d06a699 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -84,6 +84,16 @@
   The standalone `dartdoc` tool has been removed as
   previously announced. Its replacement is the `dart doc` command.
 
+- The template names used in the `dart create` command have been simplified,
+  and the current template names are now the set shown below. (Note: for
+  backwards compatibility the former template names can still be used.)
+```
+          [console] (default)    A command-line application.
+          [package]              A package containing shared Dart libraries.
+          [server-shelf]         A server app using package:shelf.
+          [web]                  A web app that uses only core Dart libraries.
+```
+
 ## 2.16.1 - 2022-02-09
 
 This is a patch release that fixes an AOT precompiler crash when building some
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 7248789..779de84 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -7815,6 +7815,46 @@
 }
 
 // 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<Message Function(String name)>
+    codeNonAugmentationClassMemberConflict =
+    const Code<Message Function(String name)>(
+  "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<Null> 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<Null> codeNonConstConstructor = messageNonConstConstructor;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -10395,6 +10435,35 @@
     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<Message Function(String name)> codeUnmatchedAugmentationClassMember =
+    const Code<Message Function(String name)>(
+  "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<Message Function(String string, Token token)>
     templateUnmatchedToken =
     const Template<Message Function(String string, Token token)>(
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index f67b886..f64f323 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -450,7 +450,13 @@
           // Add in any snippets.
           final snippetsEnabled =
               server.clientConfiguration.forResource(unit.path).enableSnippets;
-          if (capabilities.completionSnippets && snippetsEnabled) {
+          // We can only produce edits with edit builders for files inside
+          // the root, so skip snippets entirely if not.
+          final isEditableFile =
+              unit.session.analysisContext.contextRoot.isAnalyzed(unit.path);
+          if (capabilities.completionSnippets &&
+              snippetsEnabled &&
+              isEditableFile) {
             results.addAll(await _getDartSnippetItems(
               clientCapabilities: capabilities,
               unit: unit,
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
index 565b9a8..5aaf8ad 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
@@ -52,7 +52,9 @@
     }
     // method
     var field = element.variable;
-    if (field is FieldElement && field.enclosingElement is ClassElement) {
+    if (field is FieldElement &&
+        (field.enclosingElement is ClassElement ||
+            field.enclosingElement is ExtensionElement)) {
       var elements = await getHierarchyMembers(searchEngine, field);
       await Future.forEach(elements, (ClassMemberElement member) async {
         if (member is FieldElement) {
diff --git a/pkg/analysis_server/lib/src/services/snippets/dart/flutter_snippet_producers.dart b/pkg/analysis_server/lib/src/services/snippets/dart/flutter_snippet_producers.dart
index b5e210a..1a6a9ec 100644
--- a/pkg/analysis_server/lib/src/services/snippets/dart/flutter_snippet_producers.dart
+++ b/pkg/analysis_server/lib/src/services/snippets/dart/flutter_snippet_producers.dart
@@ -29,7 +29,7 @@
       return false;
     }
 
-    return true;
+    return super.isValid();
   }
 
   Future<ClassElement?> _getClass(String name) =>
@@ -152,7 +152,7 @@
     return Snippet(
       prefix,
       label,
-      'Insert a StatelessWidget',
+      'Insert a StatefulWidget',
       builder.sourceChange,
     );
   }
diff --git a/pkg/analysis_server/lib/src/services/snippets/dart/snippet_manager.dart b/pkg/analysis_server/lib/src/services/snippets/dart/snippet_manager.dart
index e3c1588..34dc40b 100644
--- a/pkg/analysis_server/lib/src/services/snippets/dart/snippet_manager.dart
+++ b/pkg/analysis_server/lib/src/services/snippets/dart/snippet_manager.dart
@@ -184,5 +184,10 @@
 
   Future<Snippet> compute();
 
-  Future<bool> isValid();
+  Future<bool> isValid() async {
+    // File edit builders will not produce edits for files outside of the
+    // analysis roots so we should not try to produce any snippets.
+    final analysisContext = request.analysisSession.analysisContext;
+    return analysisContext.contextRoot.isAnalyzed(request.filePath);
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index f77603ba..d22c4da 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -2622,6 +2622,19 @@
       FlutterStatelessWidgetSnippetProducer.prefix,
     );
   }
+
+  Future<void> test_snippets_flutterStateless_outsideAnalysisRoot() async {
+    final content = '''
+stle^
+''';
+
+    await initializeWithSnippetSupportAndPreviewFlag();
+    final otherFileUri = Uri.file('/other/file.dart');
+    await openFile(otherFileUri, withoutMarkers(content));
+    final res = await getCompletion(otherFileUri, positionFromMarker(content));
+    final snippetItems = res.where((c) => c.kind == CompletionItemKind.Snippet);
+    expect(snippetItems, hasLength(0));
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
index 8b090db..ee79e97 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
@@ -20,6 +20,28 @@
   @override
   late ConvertGetterToMethodRefactoring refactoring;
 
+  Future<void> test_change_extensionMethod() async {
+    await indexTestUnit('''
+extension A on String {
+  int get test => 1;
+}
+void f(String a) {
+  var va = a.test;
+}
+''');
+    var element = findElement.getter('test', of: 'A');
+    _createRefactoringForElement(element);
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+extension A on String {
+  int test() => 1;
+}
+void f(String a) {
+  var va = a.test();
+}
+''');
+  }
+
   Future<void> test_change_function() async {
     await indexTestUnit('''
 int get test => 42;
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 f93f47e..e4a2839 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 @@
         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 ef90973..ab0037c 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -810,6 +810,15 @@
   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 @@
       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 102db7f..f24406d 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 @@
     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 @@
             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 @@
     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 bb1a2546..ce1548c 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 @@
       }
     } 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 68f2d84..257a4b8 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 @@
       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 @@
         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 @@
       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 @@
         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 @@
       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 @@
       {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 @@
             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 fcdfb76..f4cf938 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/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 @@
   /// 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 @@
       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 @@
 
   bool get isRedirectingGenerativeConstructor => false;
 
+  @override
+  bool get isAugmentation => modifiers & augmentMask != 0;
+
   bool? _isConflictingSetter;
 
   @override
@@ -81,6 +105,20 @@
     _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 b2e67dc..5ff0e55 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -644,6 +644,8 @@
 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/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 b3403f3..8e6f415 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -5507,3 +5507,15 @@
 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 a444cf0..6173f58 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 @@
   @override
   FutureOr<void> 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 3a56029..68d6ea1 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 @@
   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 @@
   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 e6964cd..664608e 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 @@
 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 7313d71..0a0575a 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 @@
 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 0000000..12aa818
--- /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 0000000..52ceeba
--- /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{<unresolved>}.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{<unresolved>}.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 0000000..52ceeba
--- /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{<unresolved>}.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{<unresolved>}.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 0000000..c5c8d44
--- /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 0000000..52ceeba
--- /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{<unresolved>}.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{<unresolved>}.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 0000000..52ceeba
--- /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{<unresolved>}.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{<unresolved>}.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 0000000..49e7b51
--- /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 0000000..52ceeba
--- /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{<unresolved>}.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{<unresolved>}.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 0000000..a5952d5
--- /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 afa3f8a..fbb0de5 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -162,6 +162,7 @@
 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 5706ec9..544345d 100644
--- a/pkg/front_end/tool/dart_doctest_impl.dart
+++ b/pkg/front_end/tool/dart_doctest_impl.dart
@@ -918,7 +918,8 @@
       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 @@
         packageLanguageVersion: packageLanguageVersion,
         origin: origin,
         referencesFrom: referencesFrom,
-        referenceIsPartOwner: referenceIsPartOwner);
+        referenceIsPartOwner: referenceIsPartOwner,
+        isAugmentation: isAugmentation);
   }
 }
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 22ff2d3..360d454 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -2410,6 +2410,8 @@
 
         Definition* replacement = current->Canonicalize(this);
         ASSERT(replacement != nullptr);
+        RELEASE_ASSERT(unmatched_representations_allowed() ||
+                       !replacement->HasUnmatchedInputRepresentations());
         if (replacement != current) {
           current->ReplaceUsesWith(replacement);
           it.RemoveCurrentFromGraph();
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc
index 140ee55..4fa26ee 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.cc
+++ b/runtime/vm/compiler/backend/flow_graph_checker.cc
@@ -333,6 +333,9 @@
       }
     }
   }
+  ASSERT1(flow_graph_->unmatched_representations_allowed() ||
+              !instruction->HasUnmatchedInputRepresentations(),
+          instruction);
 
   // Check all regular inputs.
   for (intptr_t i = 0, n = instruction->InputCount(); i < n; ++i) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index c063152..7677166 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -676,6 +676,13 @@
       Instruction* instr = it.Current();
       set_current_instruction(instr);
       StatsBegin(instr);
+      // Unoptimized code always stores boxed values on the expression stack.
+      // However, unboxed representation is allowed for instruction inputs and
+      // outputs of certain types (e.g. for doubles).
+      // Unboxed inputs/outputs are handled in the instruction prologue
+      // and epilogue, but flagged as a mismatch on the IL level.
+      RELEASE_ASSERT(!is_optimizing() ||
+                     !instr->HasUnmatchedInputRepresentations());
 
       if (FLAG_code_comments || FLAG_disassemble ||
           FLAG_disassemble_optimized) {
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 0a53fbb..dd1c919 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -23,7 +23,7 @@
 // Test to ensure that an exception is thrown if no isolate creation
 // callback has been set by the embedder when an isolate is spawned.
 void IsolateSpawn(const char* platform_script_value) {
-  const char* kScriptChars = OS::SCreate(
+  char* scriptChars = OS::SCreate(
       nullptr,
       "import 'dart:isolate';\n"
       // Ignores printed lines.
@@ -40,7 +40,9 @@
       "}\n",
       platform_script_value);
 
-  Dart_Handle test_lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_Handle test_lib = TestCase::LoadTestScript(scriptChars, NULL);
+
+  free(scriptChars);
 
   // Setup the internal library's 'internalPrint' function.
   // Necessary because asynchronous errors use "print" to print their
diff --git a/tools/VERSION b/tools/VERSION
index 8bbd500..5169cdd 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 153
+PRERELEASE 154
 PRERELEASE_PATCH 0
\ No newline at end of file