[cfe] Implements ValueClassScanner

Change-Id: I36b839280513a75d92797d5999ecb567e6999a5c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/162180
Commit-Queue: Javier López-Contreras <jlcontreras@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/kernel/lib/transformations/scanner.dart b/pkg/kernel/lib/transformations/scanner.dart
new file mode 100644
index 0000000..5083fa6
--- /dev/null
+++ b/pkg/kernel/lib/transformations/scanner.dart
@@ -0,0 +1,51 @@
+library kernel.transformations.scanner;
+
+import '../ast.dart';
+import '../kernel.dart';
+
+abstract class Scanner<X extends TreeNode, Y extends TreeNode> {
+  final Scanner<Y, TreeNode> next;
+  Scanner(this.next);
+  bool predicate(X x);
+  ScanResult<X, Y> scan(TreeNode node);
+}
+
+class ScanResult<X extends TreeNode, Y extends TreeNode> {
+  Map<X, ScanResult<Y, TreeNode>> targets;
+  Map<X, ScanError> errors;
+}
+
+class ScanError {}
+
+abstract class ClassScanner<Y extends TreeNode> implements Scanner<Class, Y> {
+  final Scanner<Y, TreeNode> next;
+
+  ClassScanner(this.next);
+
+  bool predicate(Class node);
+
+  ScanResult<Class, Y> scan(TreeNode node) {
+    ScanResult<Class, Y> result = new ScanResult();
+    result.targets = new Map();
+    if (node is Class) {
+      if (predicate(node)) {
+        result.targets[node] = next?.scan(node);
+      }
+    } else if (node is Library) {
+      for (Class cls in node.classes) {
+        if (predicate(cls)) {
+          result.targets[cls] = next?.scan(cls);
+        }
+      }
+    } else if (node is Component) {
+      for (Library library in node.libraries) {
+        for (Class cls in library.classes) {
+          if (predicate(cls)) {
+            result.targets[cls] = next?.scan(cls);
+          }
+        }
+      }
+    }
+    return result;
+  }
+}
diff --git a/pkg/kernel/lib/transformations/value_class.dart b/pkg/kernel/lib/transformations/value_class.dart
index afda4be..9e38786 100644
--- a/pkg/kernel/lib/transformations/value_class.dart
+++ b/pkg/kernel/lib/transformations/value_class.dart
@@ -8,15 +8,31 @@
 import '../kernel.dart';
 import '../core_types.dart' show CoreTypes;
 import '../class_hierarchy.dart' show ClassHierarchy;
+import './scanner.dart';
+
+class ValueClassScanner extends ClassScanner<Null> {
+  ValueClassScanner() : super(null);
+
+  bool predicate(Class node) {
+    for (Expression annotation in node.annotations) {
+      if (annotation is ConstantExpression &&
+          annotation.constant is StringConstant) {
+        StringConstant constant = annotation.constant;
+        if (constant.value == 'valueClass') {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+}
 
 void transformComponent(
     Component node, CoreTypes coreTypes, ClassHierarchy hierarchy) {
-  for (Library library in node.libraries) {
-    for (Class cls in library.classes) {
-      if (isValueClass(cls)) {
-        transformValueClass(cls, coreTypes, hierarchy);
-      }
-    }
+  ValueClassScanner scanner = new ValueClassScanner();
+  ScanResult<Class, Null> valueClasses = scanner.scan(node);
+  for (Class valueClass in valueClasses.targets.keys) {
+    transformValueClass(valueClass, coreTypes, hierarchy);
   }
 }