Implement constructor kinds in the VM mirrors.
BUG=http://dartbug.com/13798
R=asiva@google.com, hausner@google.com
Review URL: https://codereview.chromium.org//26436004
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@28416 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index be30b5d..59ac369 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -261,12 +261,14 @@
args.SetAt(4, Bool::Get(func.is_abstract()));
args.SetAt(5, Bool::Get(func.IsGetterFunction()));
args.SetAt(6, Bool::Get(func.IsSetterFunction()));
- args.SetAt(7, Bool::Get(func.kind() == RawFunction::kConstructor));
- // TODO(mlippautz): Implement different constructor kinds.
- args.SetAt(8, Bool::False());
- args.SetAt(9, Bool::False());
- args.SetAt(10, Bool::False());
- args.SetAt(11, Bool::False());
+
+ bool isConstructor = (func.kind() == RawFunction::kConstructor);
+ args.SetAt(7, Bool::Get(isConstructor));
+ args.SetAt(8, Bool::Get(isConstructor && func.is_const()));
+ args.SetAt(9, Bool::Get(isConstructor && func.IsConstructor()));
+ args.SetAt(10, Bool::Get(isConstructor && func.is_redirecting()));
+ args.SetAt(11, Bool::Get(isConstructor && func.IsFactory()));
+
return CreateMirror(Symbols::_LocalMethodMirrorImpl(), args);
}
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index b07be27..f544f8c 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -252,11 +252,12 @@
func = cls_mirror.constructors[const Symbol('MyClass')];
Expect.isTrue(func is MethodMirror);
- Expect.equals('MyClass return(MyClass) constructor', buildMethodString(func));
+ Expect.equals('MyClass return(MyClass) constructor generative',
+ buildMethodString(func));
func = cls_mirror.constructors[const Symbol('MyClass.named')];
Expect.isTrue(func is MethodMirror);
- Expect.equals('MyClass.named return(MyClass) constructor',
+ Expect.equals('MyClass.named return(MyClass) constructor generative',
buildMethodString(func));
func = generic_cls_mirror.members[const Symbol('method')];
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 4852fb8..3564c2c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4197,6 +4197,11 @@
}
+void Function::set_is_redirecting(bool value) const {
+ set_kind_tag(RedirectingBit::update(value, raw_ptr()->kind_tag_));
+}
+
+
void Function::set_is_static(bool value) const {
set_kind_tag(StaticBit::update(value, raw_ptr()->kind_tag_));
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 30ce9f7..30ffe5a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1699,6 +1699,11 @@
}
void set_is_recognized(bool value) const;
+ bool is_redirecting() const {
+ return RedirectingBit::decode(raw_ptr()->kind_tag_);
+ }
+ void set_is_redirecting(bool value) const;
+
bool HasOptimizedCode() const;
// Returns true if the argument counts are valid for calling this function.
@@ -1858,7 +1863,8 @@
kVisibleBit = 8,
kIntrinsicBit = 9,
kRecognizedBit = 10,
- kKindTagBit = 11,
+ kRedirectingBit = 11,
+ kKindTagBit = 12,
kKindTagSize = 4,
};
class StaticBit : public BitField<bool, kStaticBit, 1> {};
@@ -1872,6 +1878,7 @@
class VisibleBit : public BitField<bool, kVisibleBit, 1> {};
class IntrinsicBit : public BitField<bool, kIntrinsicBit, 1> {};
class RecognizedBit : public BitField<bool, kRecognizedBit, 1> {};
+ class RedirectingBit : public BitField<bool, kRedirectingBit, 1> {};
class KindBits :
public BitField<RawFunction::Kind, kKindTagBit, kKindTagSize> {}; // NOLINT
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 7ffeeb8..438dc5f 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -3121,9 +3121,11 @@
// Parse redirecting factory constructor.
Type& redirection_type = Type::Handle();
String& redirection_identifier = String::Handle();
+ bool is_redirecting = false;
if (method->IsFactory() && (CurrentToken() == Token::kASSIGN)) {
ConsumeToken();
const intptr_t type_pos = TokenPos();
+ is_redirecting = true;
const AbstractType& type = AbstractType::Handle(
ParseType(ClassFinalizer::kResolveTypeParameters));
if (!type.IsMalformed() && type.IsTypeParameter()) {
@@ -3153,6 +3155,7 @@
((LookaheadToken(2) == Token::kLPAREN) ||
LookaheadToken(4) == Token::kLPAREN)) {
// Redirected constructor: either this(...) or this.xxx(...).
+ is_redirecting = true;
if (method->params.has_field_initializer) {
// Constructors that redirect to another constructor must not
// initialize any fields using field initializer parameters.
@@ -3287,6 +3290,7 @@
method->decl_begin_pos));
func.set_result_type(*method->type);
func.set_end_token_pos(method_end_pos);
+ func.set_is_redirecting(is_redirecting);
if (method->metadata_pos > 0) {
library_.AddFunctionMetadata(func, method->metadata_pos);
}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 9b62a13..daf4ba1 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -155,7 +155,6 @@
mirrors/typedef_test/01: Fail, OK # Incorrect dart2js behavior.
mirrors/closures_test/01: Fail, OK # Incorrect dart2js behavior.
-mirrors/constructor_kinds_test: RuntimeError # Issue 13798
mirrors/generics_substitution_test: RuntimeError # Issue 13808
mirrors/generic_function_typedef_test: RuntimeError # Issue 12282
mirrors/generic_mixin_applications_test: RuntimeError # Issue 12282
@@ -209,7 +208,6 @@
mirrors/mixin_test/01: Fail # Issue 13719: Please triage this failure.
mirrors/typedef_test/01: Fail # Issue 13719: Please triage this failure.
-mirrors/constructor_kinds_test: RuntimeError # Issue 13798
mirrors/generics_substitution_test: RuntimeError # Issue 13808
mirrors/generic_function_typedef_test: RuntimeError # Issue 12282
mirrors/generic_mixin_applications_test: RuntimeError # Issue 12282
diff --git a/tests/lib/mirrors/constructor_kinds_test.dart b/tests/lib/mirrors/constructor_kinds_test.dart
index f3339ca..febac1f 100644
--- a/tests/lib/mirrors/constructor_kinds_test.dart
+++ b/tests/lib/mirrors/constructor_kinds_test.dart
@@ -10,29 +10,36 @@
class ClassWithDefaultConstructor {}
class Class {
- Class.generative();
- Class.redirectingGenerative() : this.generative();
- factory Class.faktory () => new Class.generative();
- factory Class.redirectingFactory() = Class.faktory;
+ Class.generativeConstructor();
+ Class.redirectingGenerativeConstructor() : this.generativeConstructor();
+ factory Class.factoryConstructor() => new Class.generativeConstructor();
+ factory Class.redirectingFactoryConstructor() = Class.factoryConstructor;
- const Class.constGenerative();
- const Class.constRedirectingGenerative() : this.constGenerative();
+ const Class.constGenerativeConstructor();
+ const Class.constRedirectingGenerativeConstructor()
+ : this.constGenerativeConstructor();
// Not legal.
- // const factory Class.constFaktory () => const Class.constGenerative();
- const factory Class.constRedirectingFactory() = Class.constGenerative;
+ // const factory Class.constFactoryConstructor() => ...
+ const factory Class.constRedirectingFactoryConstructor()
+ = Class.constGenerativeConstructor;
}
main() {
ClassMirror cm;
MethodMirror mm;
- new Class.generative();
- new Class.redirectingGenerative();
- new Class.faktory();
- new Class.redirectingFactory();
- const Class.constGenerative();
- const Class.constRedirectingGenerative();
- const Class.constRedirectingFactory();
+ // Multitest with and without constructor calls. On the VM, we want to check
+ // that constructor properties are correctly set even if the constructor
+ // hasn't been fully compiled. On dart2js, we want to check that constructors
+ // are retain even if there are no base-level calls.
+ new ClassWithDefaultConstructor(); /// 01: ok
+ new Class.generativeConstructor(); /// 01: ok
+ new Class.redirectingGenerativeConstructor(); /// 01: ok
+ new Class.factoryConstructor(); /// 01: ok
+ new Class.redirectingFactoryConstructor(); /// 01: ok
+ const Class.constGenerativeConstructor(); /// 01: ok
+ const Class.constRedirectingGenerativeConstructor(); /// 01: ok
+ const Class.constRedirectingFactoryConstructor(); /// 01: ok
cm = reflectClass(ClassWithDefaultConstructor);
mm = cm.constructors.values.single;
@@ -42,45 +49,44 @@
Expect.isFalse(mm.isRedirectingConstructor);
Expect.isFalse(mm.isConstConstructor);
-
cm = reflectClass(Class);
- mm = cm.constructors[#generative];
+ mm = cm.constructors[#Class.generativeConstructor];
Expect.isTrue(mm.isConstructor);
Expect.isTrue(mm.isGenerativeConstructor);
Expect.isFalse(mm.isFactoryConstructor);
Expect.isFalse(mm.isRedirectingConstructor);
Expect.isFalse(mm.isConstConstructor);
- mm = cm.constructors[#redirectingGenerative];
+ mm = cm.constructors[#Class.redirectingGenerativeConstructor];
Expect.isTrue(mm.isConstructor);
Expect.isTrue(mm.isGenerativeConstructor);
Expect.isFalse(mm.isFactoryConstructor);
Expect.isTrue(mm.isRedirectingConstructor);
Expect.isFalse(mm.isConstConstructor);
- mm = cm.constructors[#faktory];
+ mm = cm.constructors[#Class.factoryConstructor];
Expect.isTrue(mm.isConstructor);
Expect.isFalse(mm.isGenerativeConstructor);
Expect.isTrue(mm.isFactoryConstructor);
Expect.isFalse(mm.isRedirectingConstructor);
Expect.isFalse(mm.isConstConstructor);
- mm = cm.constructors[#redirectingFactory];
+ mm = cm.constructors[#Class.redirectingFactoryConstructor];
Expect.isTrue(mm.isConstructor);
Expect.isFalse(mm.isGenerativeConstructor);
Expect.isTrue(mm.isFactoryConstructor);
Expect.isTrue(mm.isRedirectingConstructor);
Expect.isFalse(mm.isConstConstructor);
- mm = cm.constructors[#constGenerative];
+ mm = cm.constructors[#Class.constGenerativeConstructor];
Expect.isTrue(mm.isConstructor);
Expect.isTrue(mm.isGenerativeConstructor);
Expect.isFalse(mm.isFactoryConstructor);
Expect.isFalse(mm.isRedirectingConstructor);
Expect.isTrue(mm.isConstConstructor);
- mm = cm.constructors[#constRedirectingGenerative];
+ mm = cm.constructors[#Class.constRedirectingGenerativeConstructor];
Expect.isTrue(mm.isConstructor);
Expect.isTrue(mm.isGenerativeConstructor);
Expect.isFalse(mm.isFactoryConstructor);
@@ -88,14 +94,14 @@
Expect.isTrue(mm.isConstConstructor);
// Not legal.
- // mm = cm.constructors[#constFaktory];
+ // mm = cm.constructors[#Class.constFactoryConstructor];
// Expect.isTrue(mm.isConstructor);
// Expect.isFalse(mm.isGenerativeConstructor);
// Expect.isTrue(mm.isFactoryConstructor);
// Expect.isFalse(mm.isRedirectingConstructor);
// Expect.isTrue(mm.isConstConstructor);
- mm = cm.constructors[#constRedirectingFactory];
+ mm = cm.constructors[#Class.constRedirectingFactoryConstructor];
Expect.isTrue(mm.isConstructor);
Expect.isFalse(mm.isGenerativeConstructor);
Expect.isTrue(mm.isFactoryConstructor);