[kernel] Add an option to the cloner for cloning annotations

Fixes #33099

Bug: http://dartbug.com/33099
Change-Id: I291e75fa49fb6bf62557cfeab0c874c5de9b618d
Reviewed-on: https://dart-review.googlesource.com/57264
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
This commit is contained in:
Dmitry Stefantsov 2018-05-31 10:11:52 +00:00 committed by commit-bot@chromium.org
parent bb0808db80
commit 5ecd78222e
8 changed files with 303 additions and 8 deletions

View file

@ -427,8 +427,9 @@ abstract class KernelClassBuilder
KernelTarget target, Procedure procedure, ClassHierarchy hierarchy) {
CloneWithoutBody cloner = new CloneWithoutBody(
typeSubstitution: getSubstitutionMap(
hierarchy.getClassAsInstanceOf(cls, procedure.enclosingClass)));
Procedure cloned = cloner.clone(procedure);
hierarchy.getClassAsInstanceOf(cls, procedure.enclosingClass)),
cloneAnnotations: false);
Procedure cloned = cloner.clone(procedure)..isExternal = false;
transformProcedureToNoSuchMethodForwarder(noSuchMethod, target, cloned);
cls.procedures.add(cloned);
cloned.parent = cls;

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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
;

View file

@ -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);
});

View file

@ -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);
});

View file

@ -20,8 +20,16 @@ class CloneVisitor implements TreeVisitor {
<LabeledStatement, LabeledStatement>{};
final Map<SwitchCase, SwitchCase> switchCases = <SwitchCase, SwitchCase>{};
final Map<TypeParameter, DartType> typeSubstitution;
bool cloneAnnotations;
CloneVisitor({Map<TypeParameter, DartType> typeSubstitution})
/// Creates an instance of the cloning visitor for Kernel ASTs.
///
/// The boolean value of [cloneAnnotations] tells if the annotations on the
/// outline elements in the source AST should be cloned to the target AST. The
/// annotations in procedure bodies are cloned unconditionally.
CloneVisitor(
{Map<TypeParameter, DartType> typeSubstitution,
this.cloneAnnotations = true})
: this.typeSubstitution = ensureMutable(typeSubstitution);
static Map<TypeParameter, DartType> ensureMutable(
@ -395,6 +403,9 @@ class CloneVisitor implements TreeVisitor {
return variables[node] = new VariableDeclaration(node.name,
initializer: cloneOptional(node.initializer),
type: visitType(node.type))
..annotations = cloneAnnotations && !node.annotations.isEmpty
? node.annotations.map(clone).toList()
: const <Expression>[]
..flags = node.flags;
}
@ -413,6 +424,9 @@ class CloneVisitor implements TreeVisitor {
initializers: node.initializers.map(clone).toList(),
transformerFlags: node.transformerFlags,
fileUri: _activeFileUri)
..annotations = cloneAnnotations && !node.annotations.isEmpty
? node.annotations.map(clone).toList()
: const <Expression>[]
..fileOffset = _cloneFileOffset(node.fileOffset)
..fileEndOffset = _cloneFileOffset(node.fileEndOffset);
}
@ -423,6 +437,9 @@ class CloneVisitor implements TreeVisitor {
fileUri: _activeFileUri,
forwardingStubSuperTarget: node.forwardingStubSuperTarget,
forwardingStubInterfaceTarget: node.forwardingStubInterfaceTarget)
..annotations = cloneAnnotations && !node.annotations.isEmpty
? node.annotations.map(clone).toList()
: const <Expression>[]
..fileOffset = _cloneFileOffset(node.fileOffset)
..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
..flags = node.flags;
@ -440,6 +457,9 @@ class CloneVisitor implements TreeVisitor {
hasImplicitSetter: node.hasImplicitSetter,
transformerFlags: node.transformerFlags,
fileUri: _activeFileUri)
..annotations = cloneAnnotations && !node.annotations.isEmpty
? node.annotations.map(clone).toList()
: const <Expression>[]
..fileOffset = _cloneFileOffset(node.fileOffset)
..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
..flags = node.flags;
@ -456,7 +476,10 @@ class CloneVisitor implements TreeVisitor {
positionalParameters: node.positionalParameters.map(clone).toList(),
namedParameters: node.namedParameters.map(clone).toList(),
requiredParameterCount: node.requiredParameterCount,
fileUri: _activeFileUri);
fileUri: _activeFileUri)
..annotations = cloneAnnotations && !node.annotations.isEmpty
? node.annotations.map(clone).toList()
: const <Expression>[];
}
visitTypeParameter(TypeParameter node) {
@ -466,10 +489,22 @@ class CloneVisitor implements TreeVisitor {
if (node.defaultType != null) {
newNode.defaultType = visitType(node.defaultType);
}
return newNode..flags = node.flags;
return newNode
..annotations = cloneAnnotations && !node.annotations.isEmpty
? node.annotations.map(clone).toList()
: const <Expression>[]
..flags = node.flags;
}
TreeNode cloneFunctionNodeBody(FunctionNode node) => cloneOptional(node.body);
TreeNode cloneFunctionNodeBody(FunctionNode node) {
bool savedCloneAnnotations = this.cloneAnnotations;
try {
this.cloneAnnotations = true;
return cloneOptional(node.body);
} finally {
this.cloneAnnotations = savedCloneAnnotations;
}
}
visitFunctionNode(FunctionNode node) {
var typeParameters = node.typeParameters.map(clone).toList();
@ -584,8 +619,12 @@ class CloneVisitor implements TreeVisitor {
}
class CloneWithoutBody extends CloneVisitor {
CloneWithoutBody({Map<TypeParameter, DartType> typeSubstitution})
: super(typeSubstitution: typeSubstitution);
CloneWithoutBody(
{Map<TypeParameter, DartType> typeSubstitution,
bool cloneAnnotations = true})
: super(
typeSubstitution: typeSubstitution,
cloneAnnotations: cloneAnnotations);
@override
TreeNode cloneFunctionNodeBody(FunctionNode node) => null;