Clone annotations when cloning nodes that have them

Annotations were not cloned.

Fixes https://github.com/dart-lang/sdk/issues/33099

Change-Id: I2d2b2153be9efcf1be4b39815eb8ac15b7cacd38
Reviewed-on: https://dart-review.googlesource.com/56494
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/front_end/testcases/bug33099.dart b/pkg/front_end/testcases/bug33099.dart
new file mode 100644
index 0000000..25fd24e
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2018, 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 'dart:mirrors';
+
+const _FailingTest failingTest = const _FailingTest();
+
+class _FailingTest {
+  const _FailingTest();
+}
+
+class MyTest {
+  @failingTest
+  void foo() {}
+}
+
+class MyTest2 extends Object with MyTest {}
+
+main() {
+  ClassMirror classMirror = reflectClass(MyTest2);
+  classMirror.instanceMembers
+      .forEach((Symbol symbol, MethodMirror memberMirror) {
+    if (memberMirror.simpleName == #foo) {
+      print(memberMirror);
+      print(_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+
+bool _hasFailingTestAnnotation(MethodMirror method) {
+  var r = _hasAnnotationInstance(method, failingTest);
+  print('[_hasFailingTestAnnotation] $method $r');
+  return r;
+}
+
+bool _hasAnnotationInstance(DeclarationMirror declaration, instance) =>
+    declaration.metadata.any((InstanceMirror annotation) {
+      print('annotation: ${annotation.reflectee}');
+      return identical(annotation.reflectee, instance);
+    });
diff --git a/pkg/front_end/testcases/bug33099.dart.direct.expect b/pkg/front_end/testcases/bug33099.dart.direct.expect
new file mode 100644
index 0000000..ac82f35
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.direct.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
+static method main() → dynamic {
+  mir::ClassMirror classMirror = mir::reflectClass(self::MyTest2);
+  classMirror.instanceMembers.forEach((core::Symbol symbol, mir::MethodMirror memberMirror) → dynamic {
+    if(memberMirror.simpleName.==(#foo)) {
+      core::print(memberMirror);
+      core::print(self::_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool {
+  dynamic r = self::_hasAnnotationInstance(method, self::failingTest);
+  core::print("[_hasFailingTestAnnotation] ${method} ${r}");
+  return r;
+}
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  return declaration.metadata.any((mir::InstanceMirror annotation) → dynamic {
+    core::print("annotation: ${annotation.reflectee}");
+    return core::identical(annotation.reflectee, instance);
+  });
diff --git a/pkg/front_end/testcases/bug33099.dart.direct.transformed.expect b/pkg/front_end/testcases/bug33099.dart.direct.transformed.expect
new file mode 100644
index 0000000..d26b033
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.direct.transformed.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
+static method main() → dynamic {
+  mir::ClassMirror classMirror = mir::reflectClass(self::MyTest2);
+  classMirror.instanceMembers.forEach((core::Symbol symbol, mir::MethodMirror memberMirror) → dynamic {
+    if(memberMirror.simpleName.==(#foo)) {
+      core::print(memberMirror);
+      core::print(self::_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool {
+  dynamic r = self::_hasAnnotationInstance(method, self::failingTest);
+  core::print("[_hasFailingTestAnnotation] ${method} ${r}");
+  return r;
+}
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  return declaration.metadata.any((mir::InstanceMirror annotation) → dynamic {
+    core::print("annotation: ${annotation.reflectee}");
+    return core::identical(annotation.reflectee, instance);
+  });
diff --git a/pkg/front_end/testcases/bug33099.dart.outline.expect b/pkg/front_end/testcases/bug33099.dart.outline.expect
new file mode 100644
index 0000000..9d360a0
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.outline.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    ;
+  method foo() → void
+    ;
+}
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    ;
+}
+static const field self::_FailingTest failingTest;
+static method main() → dynamic
+  ;
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool
+  ;
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  ;
diff --git a/pkg/front_end/testcases/bug33099.dart.strong.expect b/pkg/front_end/testcases/bug33099.dart.strong.expect
new file mode 100644
index 0000000..4119f1c
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.strong.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest {
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
+static method main() → dynamic {
+  mir::ClassMirror classMirror = mir::reflectClass(self::MyTest2);
+  classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol symbol, mir::MethodMirror memberMirror) → core::Null {
+    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#foo)) {
+      core::print(memberMirror);
+      core::print(self::_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool {
+  core::bool r = self::_hasAnnotationInstance(method, self::failingTest);
+  core::print("[_hasFailingTestAnnotation] ${method} ${r}");
+  return r;
+}
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  return declaration.{mir::DeclarationMirror::metadata}.{core::Iterable::any}((mir::InstanceMirror annotation) → core::bool {
+    core::print("annotation: ${annotation.{mir::InstanceMirror::reflectee}}");
+    return core::identical(annotation.{mir::InstanceMirror::reflectee}, instance);
+  });
diff --git a/pkg/front_end/testcases/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/bug33099.dart.strong.transformed.expect
new file mode 100644
index 0000000..072ae37
--- /dev/null
+++ b/pkg/front_end/testcases/bug33099.dart.strong.transformed.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:mirrors" as mir;
+
+class _FailingTest extends core::Object {
+  const constructor •() → void
+    : super core::Object::•()
+    ;
+}
+class MyTest extends core::Object {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+  @self::failingTest
+  method foo() → void {}
+}
+class MyTest2 extends self::_MyTest2&Object&MyTest {
+  synthetic constructor •() → void
+    : super core::Object::•()
+    ;
+}
+static const field self::_FailingTest failingTest = const self::_FailingTest::•();
+static method main() → dynamic {
+  mir::ClassMirror classMirror = mir::reflectClass(self::MyTest2);
+  classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol symbol, mir::MethodMirror memberMirror) → core::Null {
+    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#foo)) {
+      core::print(memberMirror);
+      core::print(self::_hasFailingTestAnnotation(memberMirror));
+    }
+  });
+}
+static method _hasFailingTestAnnotation(mir::MethodMirror method) → core::bool {
+  core::bool r = self::_hasAnnotationInstance(method, self::failingTest);
+  core::print("[_hasFailingTestAnnotation] ${method} ${r}");
+  return r;
+}
+static method _hasAnnotationInstance(mir::DeclarationMirror declaration, dynamic instance) → core::bool
+  return declaration.{mir::DeclarationMirror::metadata}.{core::Iterable::any}((mir::InstanceMirror annotation) → core::bool {
+    core::print("annotation: ${annotation.{mir::InstanceMirror::reflectee}}");
+    return core::identical(annotation.{mir::InstanceMirror::reflectee}, instance);
+  });
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 3a461aa1..54dbdad 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -395,6 +395,9 @@
     return variables[node] = new VariableDeclaration(node.name,
         initializer: cloneOptional(node.initializer),
         type: visitType(node.type))
+      ..annotations = node.annotations.isEmpty
+          ? const <Expression>[]
+          : node.annotations.map(clone).toList()
       ..flags = node.flags;
   }
 
@@ -413,6 +416,9 @@
         initializers: node.initializers.map(clone).toList(),
         transformerFlags: node.transformerFlags,
         fileUri: _activeFileUri)
+      ..annotations = node.annotations.isEmpty
+          ? const <Expression>[]
+          : node.annotations.map(clone).toList()
       ..fileOffset = _cloneFileOffset(node.fileOffset)
       ..fileEndOffset = _cloneFileOffset(node.fileEndOffset);
   }
@@ -423,6 +429,9 @@
         fileUri: _activeFileUri,
         forwardingStubSuperTarget: node.forwardingStubSuperTarget,
         forwardingStubInterfaceTarget: node.forwardingStubInterfaceTarget)
+      ..annotations = node.annotations.isEmpty
+          ? const <Expression>[]
+          : node.annotations.map(clone).toList()
       ..fileOffset = _cloneFileOffset(node.fileOffset)
       ..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
       ..flags = node.flags;
@@ -440,6 +449,9 @@
         hasImplicitSetter: node.hasImplicitSetter,
         transformerFlags: node.transformerFlags,
         fileUri: _activeFileUri)
+      ..annotations = node.annotations.isEmpty
+          ? const <Expression>[]
+          : node.annotations.map(clone).toList()
       ..fileOffset = _cloneFileOffset(node.fileOffset)
       ..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
       ..flags = node.flags;
@@ -456,7 +468,10 @@
         positionalParameters: node.positionalParameters.map(clone).toList(),
         namedParameters: node.namedParameters.map(clone).toList(),
         requiredParameterCount: node.requiredParameterCount,
-        fileUri: _activeFileUri);
+        fileUri: _activeFileUri)
+      ..annotations = node.annotations.isEmpty
+          ? const <Expression>[]
+          : node.annotations.map(clone).toList();
   }
 
   visitTypeParameter(TypeParameter node) {
@@ -466,7 +481,11 @@
     if (node.defaultType != null) {
       newNode.defaultType = visitType(node.defaultType);
     }
-    return newNode..flags = node.flags;
+    return newNode
+      ..annotations = node.annotations.isEmpty
+          ? const <Expression>[]
+          : node.annotations.map(clone).toList()
+      ..flags = node.flags;
   }
 
   TreeNode cloneFunctionNodeBody(FunctionNode node) => cloneOptional(node.body);