add declarationKind for extensions and libraries, support augmenting extensions and add test

Change-Id: I510976cac641800e664e92e7db786962d539ec9c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325021
Reviewed-by: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Jake Macdonald <jakemac@google.com>
Auto-Submit: Jake Macdonald <jakemac@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
index db56ca2..b67ddb7 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor.dart
@@ -188,8 +188,10 @@
   constructor,
   enumType,
   enumValue,
+  extension,
   field,
   function,
+  library,
   method,
   mixinType,
   variable,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart
index 91e06a7..368b2c0 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/augmentation_library.dart
@@ -135,14 +135,14 @@
     };
     for (Identifier type in mergedAugmentedTypes) {
       final TypeDeclaration typeDeclaration = resolveDeclaration(type);
-      String declarationKind = typeDeclaration is ClassDeclaration
-          ? 'class'
-          : typeDeclaration is EnumDeclaration
-              ? 'enum'
-              : typeDeclaration is MixinDeclaration
-                  ? 'mixin'
-                  : throw new UnsupportedError(
-                      'Unsupported augmentation type $typeDeclaration');
+      String declarationKind = switch (typeDeclaration) {
+        ClassDeclaration() => 'class',
+        EnumDeclaration() => 'enum',
+        ExtensionDeclaration() => 'extension',
+        MixinDeclaration() => 'mixin',
+        _ => throw new UnsupportedError(
+            'Unsupported augmentation type $typeDeclaration'),
+      };
       final List<String> keywords = [
         if (typeDeclaration is ClassDeclaration) ...[
           if (typeDeclaration.hasAbstract) 'abstract',
@@ -181,6 +181,7 @@
           ' '
         ]));
       }
+
       writeDirectiveStringPart('{\n');
       if (typeDeclaration is EnumDeclaration) {
         for (DeclarationCode entryAugmentation
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart
index 168c698..9615175 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor/response_impls.dart
@@ -33,171 +33,165 @@
                 if (macro is ClassTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is ClassDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is ClassDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
           case DeclarationKind.constructor:
             switch (phase) {
               case Phase.types:
                 if (macro is ConstructorTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is ConstructorDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is ConstructorDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
+          case DeclarationKind.extension:
+            switch (phase) {
+              case Phase.types:
+                if (macro is ExtensionTypesMacro) {
+                  interfaces |= interfaceMask;
+                }
+              case Phase.declarations:
+                if (macro is ExtensionDeclarationsMacro) {
+                  interfaces |= interfaceMask;
+                }
+              case Phase.definitions:
+                if (macro is ExtensionDefinitionMacro) {
+                  interfaces |= interfaceMask;
+                }
+            }
           case DeclarationKind.field:
             switch (phase) {
               case Phase.types:
                 if (macro is FieldTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is FieldDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is FieldDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
           case DeclarationKind.function:
             switch (phase) {
               case Phase.types:
                 if (macro is FunctionTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is FunctionDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is FunctionDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
+          case DeclarationKind.library:
+            switch (phase) {
+              case Phase.types:
+                if (macro is LibraryTypesMacro) {
+                  interfaces |= interfaceMask;
+                }
+              case Phase.declarations:
+                if (macro is LibraryDeclarationsMacro) {
+                  interfaces |= interfaceMask;
+                }
+              case Phase.definitions:
+                if (macro is LibraryDefinitionMacro) {
+                  interfaces |= interfaceMask;
+                }
+            }
           case DeclarationKind.method:
             switch (phase) {
               case Phase.types:
                 if (macro is MethodTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is MethodDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is MethodDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
           case DeclarationKind.enumType:
             switch (phase) {
               case Phase.types:
                 if (macro is EnumTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is EnumDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is EnumDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
           case DeclarationKind.enumValue:
             switch (phase) {
               case Phase.types:
                 if (macro is EnumValueTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is EnumValueDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is EnumValueDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
           case DeclarationKind.mixinType:
             switch (phase) {
               case Phase.types:
                 if (macro is MixinTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is MixinDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is MixinDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
           case DeclarationKind.variable:
             switch (phase) {
               case Phase.types:
                 if (macro is VariableTypesMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.declarations:
                 if (macro is VariableDeclarationsMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
               case Phase.definitions:
                 if (macro is VariableDefinitionMacro) {
                   interfaces |= interfaceMask;
                 }
-                break;
             }
-            break;
         }
       }
     }
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
index 026e70a..2838579 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/augmentation_library_test.dart
@@ -443,6 +443,83 @@
       '''));
     });
 
+    test('can augment extensions', () async {
+      final myExtension = ExtensionDeclarationImpl(
+        id: RemoteInstance.uniqueId,
+        identifier: TestIdentifier(
+            id: RemoteInstance.uniqueId,
+            name: 'MyExtension',
+            kind: IdentifierKind.topLevelMember,
+            uri: Uri.parse('a.dart'),
+            staticScope: null),
+        library: Fixtures.library,
+        metadata: [],
+        typeParameters: [],
+        onType: Fixtures.myClassType,
+      );
+      final myGetter = MethodDeclarationImpl(
+          id: RemoteInstance.uniqueId,
+          identifier: TestIdentifier(
+              id: RemoteInstance.uniqueId,
+              name: 'x',
+              kind: IdentifierKind.instanceMember,
+              uri: Uri.parse('a.dart'),
+              staticScope: null),
+          library: Fixtures.library,
+          metadata: [],
+          definingType: myExtension.identifier,
+          hasExternal: false,
+          isStatic: false,
+          returnType: NamedTypeAnnotationImpl(
+              id: RemoteInstance.uniqueId,
+              isNullable: false,
+              identifier: intIdentifier,
+              typeArguments: []),
+          hasAbstract: false,
+          hasBody: true,
+          isGetter: true,
+          isOperator: false,
+          isSetter: false,
+          namedParameters: [],
+          positionalParameters: [],
+          typeParameters: []);
+
+      var results = [
+        MacroExecutionResultImpl(
+            diagnostics: [],
+            enumValueAugmentations: {},
+            typeAugmentations: {
+              myExtension.identifier: [
+                DeclarationCode.fromParts([
+                  intIdentifier,
+                  ' get ',
+                  myGetter.identifier.name,
+                  ' => 1;\n'
+                ]),
+              ],
+            },
+            interfaceAugmentations: {},
+            mixinAugmentations: {},
+            newTypeNames: [],
+            libraryAugmentations: []),
+      ];
+      var library = _TestExecutor().buildAugmentationLibrary(
+          results,
+          (Identifier i) => i == myExtension.identifier
+              ? myExtension
+              : throw UnimplementedError(),
+          (Identifier i) => (i as TestIdentifier).resolved,
+          (OmittedTypeAnnotation i) =>
+              (i as TestOmittedTypeAnnotation).inferredType);
+      expect(library, equalsIgnoringWhitespace('''
+        import 'dart:core' as prefix0;
+
+        augment extension MyExtension {
+          prefix0.int get x => 1;
+        }
+      '''));
+    });
+
     test('copies keywords for classes', () async {
       for (final hasKeywords in [true, false]) {
         final clazz = ClassDeclarationImpl(
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor/response_impls_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor/response_impls_test.dart
index 0b3f983..11f0e56 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor/response_impls_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor/response_impls_test.dart
@@ -99,6 +99,14 @@
     Phase.definitions: MacroInstanceIdentifierImpl(
         FakeEnumValueDefinitionMacro(), RemoteInstance.uniqueId),
   },
+  DeclarationKind.extension: {
+    Phase.types: MacroInstanceIdentifierImpl(
+        FakeExtensionTypesMacro(), RemoteInstance.uniqueId),
+    Phase.declarations: MacroInstanceIdentifierImpl(
+        FakeExtensionDeclarationsMacro(), RemoteInstance.uniqueId),
+    Phase.definitions: MacroInstanceIdentifierImpl(
+        FakeExtensionDefinitionMacro(), RemoteInstance.uniqueId),
+  },
   DeclarationKind.field: {
     Phase.types: MacroInstanceIdentifierImpl(
         FakeFieldTypesMacro(), RemoteInstance.uniqueId),
@@ -115,6 +123,14 @@
     Phase.definitions: MacroInstanceIdentifierImpl(
         FakeFunctionDefinitionMacro(), RemoteInstance.uniqueId),
   },
+  DeclarationKind.library: {
+    Phase.types: MacroInstanceIdentifierImpl(
+        FakeLibraryTypesMacro(), RemoteInstance.uniqueId),
+    Phase.declarations: MacroInstanceIdentifierImpl(
+        FakeLibraryDeclarationsMacro(), RemoteInstance.uniqueId),
+    Phase.definitions: MacroInstanceIdentifierImpl(
+        FakeLibraryDefinitionMacro(), RemoteInstance.uniqueId),
+  },
   DeclarationKind.method: {
     Phase.types: MacroInstanceIdentifierImpl(
         FakeMethodTypesMacro(), RemoteInstance.uniqueId),
@@ -206,3 +222,19 @@
 
 class FakeEnumValueDefinitionMacro extends Fake
     implements EnumValueDefinitionMacro {}
+
+class FakeExtensionTypesMacro extends Fake implements ExtensionTypesMacro {}
+
+class FakeExtensionDeclarationsMacro extends Fake
+    implements ExtensionDeclarationsMacro {}
+
+class FakeExtensionDefinitionMacro extends Fake
+    implements ExtensionDefinitionMacro {}
+
+class FakeLibraryTypesMacro extends Fake implements LibraryTypesMacro {}
+
+class FakeLibraryDeclarationsMacro extends Fake
+    implements LibraryDeclarationsMacro {}
+
+class FakeLibraryDefinitionMacro extends Fake
+    implements LibraryDefinitionMacro {}