Move ConstantValue handling outside BehaviorBuilder

Change-Id: Ie397c7e1a927e694de2d5968c9c962c024713633
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96659
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 2d04f00..74411dc 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -1492,7 +1492,10 @@
     DartType type = getDartType(field.type);
     List<ConstantValue> metadata = getMetadata(field.annotations);
     return nativeBehaviorBuilder.buildFieldLoadBehavior(
-        type, metadata, typeLookup(resolveAsRaw: false),
+        type,
+        getCreatesAnnotations(reporter, commonElements, metadata),
+        getReturnsAnnotations(reporter, commonElements, metadata),
+        typeLookup(resolveAsRaw: false),
         isJsInterop: isJsInterop);
   }
 
@@ -1517,7 +1520,10 @@
     }
     List<ConstantValue> metadata = getMetadata(member.annotations);
     return nativeBehaviorBuilder.buildMethodBehavior(
-        type, metadata, typeLookup(resolveAsRaw: false),
+        type,
+        getCreatesAnnotations(reporter, commonElements, metadata),
+        getReturnsAnnotations(reporter, commonElements, metadata),
+        typeLookup(resolveAsRaw: false),
         isJsInterop: isJsInterop);
   }
 
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 07e03da..138fc5e 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -736,14 +736,12 @@
 
   NativeBehavior _behavior;
 
-  void _overrideWithAnnotations(
-      Iterable<ConstantValue> metadata, TypeLookup lookupType) {
-    if (metadata.isEmpty) return;
+  void _overrideWithAnnotations(Iterable<String> createsAnnotations,
+      Iterable<String> returnsAnnotations, TypeLookup lookupType) {
+    if (createsAnnotations.isEmpty && returnsAnnotations.isEmpty) return;
 
-    List creates =
-        _collect(metadata, commonElements.annotationCreatesClass, lookupType);
-    List returns =
-        _collect(metadata, commonElements.annotationReturnsClass, lookupType);
+    List creates = _collect(createsAnnotations, lookupType);
+    List returns = _collect(returnsAnnotations, lookupType);
 
     if (creates != null) {
       _behavior.typesInstantiated
@@ -760,22 +758,9 @@
   /// Returns a list of type constraints from the annotations of
   /// [annotationClass].
   /// Returns `null` if no constraints.
-  List _collect(Iterable<ConstantValue> metadata, ClassEntity annotationClass,
-      TypeLookup lookupType) {
+  List _collect(Iterable<String> annotations, TypeLookup lookupType) {
     var types = null;
-    for (ConstantValue value in metadata) {
-      if (!value.isConstructedObject) continue;
-      ConstructedConstantValue constructedObject = value;
-      if (constructedObject.type.element != annotationClass) continue;
-
-      Iterable<ConstantValue> fields = constructedObject.fields.values;
-      // TODO(sra): Better validation of the constant.
-      if (fields.length != 1 || !fields.single.isString) {
-        reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
-            'Annotations needs one string: ${value.toStructuredText()}');
-      }
-      StringConstantValue specStringConstant = fields.single;
-      String specString = specStringConstant.stringValue;
+    for (String specString in annotations) {
       for (final typeString in specString.split('|')) {
         var type = NativeBehavior._parseType(typeString, lookupType);
         if (types == null) types = [];
@@ -847,7 +832,10 @@
   }
 
   NativeBehavior buildFieldLoadBehavior(
-      DartType type, Iterable<ConstantValue> metadata, TypeLookup lookupType,
+      DartType type,
+      Iterable<String> createsAnnotations,
+      Iterable<String> returnsAnnotations,
+      TypeLookup lookupType,
       {bool isJsInterop}) {
     _behavior = new NativeBehavior();
     // TODO(sigmund,sra): consider doing something better for numeric types.
@@ -857,7 +845,8 @@
     // Declared types are nullable.
     _behavior.typesReturned.add(commonElements.nullType);
     _capture(type, isJsInterop);
-    _overrideWithAnnotations(metadata, lookupType);
+    _overrideWithAnnotations(
+        createsAnnotations, returnsAnnotations, lookupType);
     return _behavior;
   }
 
@@ -869,8 +858,11 @@
     return _behavior;
   }
 
-  NativeBehavior buildMethodBehavior(FunctionType type,
-      Iterable<ConstantValue> metadata, TypeLookup lookupType,
+  NativeBehavior buildMethodBehavior(
+      FunctionType type,
+      Iterable<String> createAnnotations,
+      Iterable<String> returnsAnnotations,
+      TypeLookup lookupType,
       {bool isJsInterop}) {
     _behavior = new NativeBehavior();
     DartType returnType = type.returnType;
@@ -899,7 +891,40 @@
       _escape(type, isJsInterop);
     }
 
-    _overrideWithAnnotations(metadata, lookupType);
+    _overrideWithAnnotations(createAnnotations, returnsAnnotations, lookupType);
     return _behavior;
   }
 }
+
+List<String> _getAnnotations(DiagnosticReporter reporter,
+    Iterable<ConstantValue> metadata, ClassEntity cls) {
+  List<String> annotations = [];
+  for (ConstantValue value in metadata) {
+    if (!value.isConstructedObject) continue;
+    ConstructedConstantValue constructedObject = value;
+    if (constructedObject.type.element != cls) continue;
+
+    Iterable<ConstantValue> fields = constructedObject.fields.values;
+    // TODO(sra): Better validation of the constant.
+    if (fields.length != 1 || !fields.single.isString) {
+      reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
+          'Annotations needs one string: ${value.toStructuredText()}');
+    }
+    StringConstantValue specStringConstant = fields.single;
+    String specString = specStringConstant.stringValue;
+    annotations.add(specString);
+  }
+  return annotations;
+}
+
+List<String> getCreatesAnnotations(DiagnosticReporter reporter,
+    CommonElements commonElements, Iterable<ConstantValue> metadata) {
+  return _getAnnotations(
+      reporter, metadata, commonElements.annotationCreatesClass);
+}
+
+List<String> getReturnsAnnotations(DiagnosticReporter reporter,
+    CommonElements commonElements, Iterable<ConstantValue> metadata) {
+  return _getAnnotations(
+      reporter, metadata, commonElements.annotationReturnsClass);
+}