Macro. Record InvalidMacroTargetDiagnostic, if the target is not suitable for the macro.

Change-Id: Ic9e69e0297b76d06a2012e609750b1e0b7438093
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/350687
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index e2cd45b..cd1d589 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -95,7 +95,7 @@
 // TODO(scheglov): Clean up the list of implicitly analyzed files.
 class AnalysisDriver {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 339;
+  static const int DATA_VERSION = 340;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 8de08c4..9d3af70 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -6191,6 +6191,9 @@
               // TODO(scheglov): Handle this case.
               throw UnimplementedError();
           }
+        case InvalidMacroTargetDiagnostic():
+          // TODO(scheglov): Handle this case.
+          throw UnimplementedError();
       }
     }
   }
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
index 9e2adc8..d446350 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
@@ -25,8 +25,9 @@
 
 enum MacroDiagnosticKind {
   argument,
-  introspectionCycle,
   exception,
+  introspectionCycle,
+  invalidTarget,
   macro,
 }
 
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 97c443e..605f742 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -2338,6 +2338,12 @@
           argumentIndex: readUInt30(),
           message: _reader.readStringUtf8(),
         );
+      case MacroDiagnosticKind.exception:
+        return ExceptionMacroDiagnostic(
+          annotationIndex: readUInt30(),
+          message: _reader.readStringUtf8(),
+          stackTrace: _reader.readStringUtf8(),
+        );
       case MacroDiagnosticKind.introspectionCycle:
         return DeclarationsIntrospectionCycleDiagnostic(
           annotationIndex: readUInt30(),
@@ -2350,11 +2356,9 @@
             );
           }),
         );
-      case MacroDiagnosticKind.exception:
-        return ExceptionMacroDiagnostic(
-          annotationIndex: readUInt30(),
-          message: _reader.readStringUtf8(),
-          stackTrace: _reader.readStringUtf8(),
+      case MacroDiagnosticKind.invalidTarget:
+        return InvalidMacroTargetDiagnostic(
+          supportedKinds: _reader.readStringUtf8List(),
         );
       case MacroDiagnosticKind.macro:
         return MacroDiagnostic(
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 22f2d63..1ccf831 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -960,6 +960,9 @@
         writeUInt30(diagnostic.annotationIndex);
         writeStringUtf8(diagnostic.message);
         writeStringUtf8(diagnostic.stackTrace);
+      case InvalidMacroTargetDiagnostic():
+        writeEnum(MacroDiagnosticKind.invalidTarget);
+        writeStringUtf8Iterable(diagnostic.supportedKinds);
       case MacroDiagnostic():
         writeEnum(MacroDiagnosticKind.macro);
         writeEnum(diagnostic.severity);
diff --git a/pkg/analyzer/lib/src/summary2/macro_application.dart b/pkg/analyzer/lib/src/summary2/macro_application.dart
index 25191af..f6e067a 100644
--- a/pkg/analyzer/lib/src/summary2/macro_application.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_application.dart
@@ -483,6 +483,18 @@
         return instance.shouldExecute(targetDeclarationKind, phase);
       }).toSet();
 
+      if (!instance.supportsDeclarationKind(targetDeclarationKind)) {
+        macroTarget.element.addMacroDiagnostic(
+          InvalidMacroTargetDiagnostic(
+            supportedKinds: macro.DeclarationKind.values
+                .where(instance.supportsDeclarationKind)
+                .map((e) => e.name)
+                .toList(),
+          ),
+        );
+        return;
+      }
+
       final application = _MacroApplication(
         target: macroTarget,
         annotationIndex: annotationIndex,
diff --git a/pkg/analyzer/lib/src/summary2/macro_application_error.dart b/pkg/analyzer/lib/src/summary2/macro_application_error.dart
index b37821e..33bd6f3 100644
--- a/pkg/analyzer/lib/src/summary2/macro_application_error.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_application_error.dart
@@ -86,6 +86,14 @@
   });
 }
 
+final class InvalidMacroTargetDiagnostic extends AnalyzerMacroDiagnostic {
+  final List<String> supportedKinds;
+
+  InvalidMacroTargetDiagnostic({
+    required this.supportedKinds,
+  });
+}
+
 /// Diagnostic from the macro framework.
 final class MacroDiagnostic extends AnalyzerMacroDiagnostic {
   final macro.Severity severity;
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index bacdc98..d02ce82 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -901,6 +901,17 @@
                   'stackTrace:\n${diagnostic.stackTrace}',
                 );
               });
+            case InvalidMacroTargetDiagnostic():
+              _sink.writelnWithIndent('InvalidMacroTargetDiagnostic');
+              _sink.withIndent(() {
+                _sink.writeElements(
+                  'supportedKinds',
+                  diagnostic.supportedKinds,
+                  (kindName) {
+                    _sink.writelnWithIndent(kindName);
+                  },
+                );
+              });
             case MacroDiagnostic():
               _sink.writelnWithIndent('MacroDiagnostic');
               _sink.withIndent(() {
diff --git a/pkg/analyzer/test/src/summary/macro/diagnostic.dart b/pkg/analyzer/test/src/summary/macro/diagnostic.dart
index f5880ed..8cd13d9 100644
--- a/pkg/analyzer/test/src/summary/macro/diagnostic.dart
+++ b/pkg/analyzer/test/src/summary/macro/diagnostic.dart
@@ -348,6 +348,17 @@
   }
 }
 
+/*macro*/ class TargetClassOrMixinMacro
+    implements ClassTypesMacro, MixinTypesMacro {
+  const TargetClassOrMixinMacro();
+
+  @override
+  buildTypesForClass(declaration, builder) {}
+
+  @override
+  buildTypesForMixin(declaration, builder) {}
+}
+
 /*macro*/ class ThrowExceptionDeclarationsPhase
     implements
         ClassDeclarationsMacro,
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index 0f04b14..a954c57 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -3534,6 +3534,38 @@
 ''');
   }
 
+  test_macroDiagnostics_invalidTarget_wantsClassOrMixin_hasFunction() async {
+    newFile(
+      '$testPackageLibPath/diagnostic.dart',
+      _getMacroCode('diagnostic.dart'),
+    );
+
+    final library = await buildLibrary(r'''
+import 'diagnostic.dart';
+
+@TargetClassOrMixinMacro()
+void f() {}
+''');
+
+    configuration
+      ..withConstructors = false
+      ..withMetadata = false;
+    checkElementText(library, r'''
+library
+  imports
+    package:test/diagnostic.dart
+  definingUnit
+    functions
+      f @59
+        returnType: void
+        macroDiagnostics
+          InvalidMacroTargetDiagnostic
+            supportedKinds
+              classType
+              mixinType
+''');
+  }
+
   test_macroDiagnostics_report_atDeclaration_class() async {
     newFile(
       '$testPackageLibPath/diagnostic.dart',