mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 15:09:45 +00:00
[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:
parent
bb0808db80
commit
5ecd78222e
|
@ -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;
|
||||
|
|
41
pkg/front_end/testcases/bug33099.dart
Normal file
41
pkg/front_end/testcases/bug33099.dart
Normal 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);
|
||||
});
|
44
pkg/front_end/testcases/bug33099.dart.direct.expect
Normal file
44
pkg/front_end/testcases/bug33099.dart.direct.expect
Normal 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);
|
||||
});
|
|
@ -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);
|
||||
});
|
28
pkg/front_end/testcases/bug33099.dart.outline.expect
Normal file
28
pkg/front_end/testcases/bug33099.dart.outline.expect
Normal 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
|
||||
;
|
44
pkg/front_end/testcases/bug33099.dart.strong.expect
Normal file
44
pkg/front_end/testcases/bug33099.dart.strong.expect
Normal 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);
|
||||
});
|
|
@ -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);
|
||||
});
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue