Version 1.2.0-dev.5.5
svn merge -c 32600 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32603 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32616 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32622 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32623 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32628 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32634 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32646 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32658 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@32664 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index a6641b3..3e1c86e 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -1311,7 +1311,7 @@
Library& ctxt_library = Library::Handle();
String& library_key = String::Handle();
- if (library_key.IsNull()) {
+ if (private_key.IsNull()) {
ctxt_library = Library::CoreLibrary();
} else {
for (int i = 0; i < num_libraries; i++) {
diff --git a/sdk/lib/_internal/compiler/implementation/js/builder.dart b/sdk/lib/_internal/compiler/implementation/js/builder.dart
index 24b492a..ab05952 100644
--- a/sdk/lib/_internal/compiler/implementation/js/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/builder.dart
@@ -126,16 +126,12 @@
}
return new ObjectInitializer([]);
} else if (expression is List) {
- var values = new List<ArrayElement>(expression.length);
- int index = 0;
- for (var entry in expression) {
- values[index] = new ArrayElement(index, toExpression(entry));
- index++;
- }
+ var values = new List<ArrayElement>.generate(expression.length,
+ (index) => new ArrayElement(index, toExpression(expression[index])));
return new ArrayInitializer(values.length, values);
} else {
throw new ArgumentError('expression should be an Expression, '
- 'a String, a num, a bool, or a Map');
+ 'a String, a num, a bool, a Map, or a List;');
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index b42cc55..a9f6407 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -398,11 +398,10 @@
String newName = operatorNameToIdentifier(name);
if (newName != name) return getMappedOperatorName(newName);
assert(!isPrivateName(name));
- var base = name;
// We don't mangle the closure invoking function name because it
// is generated by string concatenation in applyFunction from
// js_helper.dart.
- var proposedName = '$base\$$arity';
+ String proposedName = '$name\$$arity';
if (name == closureInvocationSelectorName) return proposedName;
return getMappedInstanceName(proposedName);
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
index 7632220..49f51a9 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/class_emitter.dart
@@ -342,7 +342,7 @@
if (!backend.isNeededForReflection(classElement)) {
enclosingBuilder.addProperty("+$reflectionName", js.number(0));
} else {
- List<int> types = new List<int>();
+ List<int> types = <int>[];
if (classElement.supertype != null) {
types.add(task.metadataEmitter.reifyType(classElement.supertype));
}
@@ -350,8 +350,7 @@
types.add(task.metadataEmitter.reifyType(interface));
}
enclosingBuilder.addProperty("+$reflectionName",
- new jsAst.ArrayInitializer.from(types.map((typeNumber) =>
- js.number(typeNumber))));
+ new jsAst.ArrayInitializer.from(types.map(js.number)));
}
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
index 7e7fe90..98ef937 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
@@ -486,6 +486,15 @@
if (canBeReflected || canBeApplied) {
parameters.orderedForEachParameter((Element parameter) {
expressions.add(task.metadataEmitter.reifyName(parameter.name));
+ List<MetadataAnnotation> annotations = parameter.metadata.toList();
+ Iterable<int> metadataIndices = annotations.map((MetadataAnnotation a) {
+ compiler.constantHandler.addCompileTimeConstantForEmission(a.value);
+ return task.metadataEmitter.reifyMetadata(a);
+ });
+ // TODO(karlklose): store metadata on elements in correct source order.
+ metadataIndices = metadataIndices.toList().reversed.toList();
+ expressions.add(metadataIndices.isNotEmpty ? metadataIndices
+ : js('[]'));
});
}
if (canBeReflected) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
index 5fabe21..29630bb 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
@@ -32,7 +32,7 @@
void addNoSuchMethodHandlers(String ignore, Set<Selector> selectors) {
// Cache the object class and type.
ClassElement objectClass = compiler.objectClass;
- DartType objectType = objectClass.computeType(compiler);
+ DartType objectType = objectClass.rawType;
for (Selector selector in selectors) {
TypeMask mask = selector.mask;
@@ -64,7 +64,6 @@
// Values match JSInvocationMirror in js-helper library.
int type = selector.invocationMirrorKind;
List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
- CodeBuffer args = new CodeBuffer();
for (int i = 0; i < selector.argumentCount; i++) {
parameters.add(new jsAst.Parameter('\$$i'));
}
@@ -109,7 +108,7 @@
if (reflectionName != null) {
bool accessible = compiler.world.allFunctions.filter(selector).any(
(Element e) => backend.isAccessibleByReflection(e));
- addProperty('+$reflectionName', js(accessible ? '1' : '0'));
+ addProperty('+$reflectionName', js(accessible ? '2' : '0'));
}
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
index ee897b9..bc13d80 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
@@ -98,7 +98,8 @@
''' requiredParameterCount + optionalParameterCount != funcs[0].length;
var functionTypeIndex = ${readFunctionType("array", "2")};
var isReflectable =''' // Break long line.
- ''' array.length > requiredParameterCount + optionalParameterCount + 3;
+ ''' array.length > 3 * optionalParameterCount + ''' // Break
+ '''2 * requiredParameterCount + 3
if (getterStubName) {
f = tearOff(funcs, array, isStatic, name, isIntercepted);
'''
@@ -119,7 +120,7 @@
}
if (isReflectable) {
var unmangledNameIndex =''' // Break long line.
- ''' optionalParameterCount * 2 + requiredParameterCount + 3;
+ ''' 3 * optionalParameterCount + 2 * requiredParameterCount + 3;
var unmangledName = ${readString("array", "unmangledNameIndex")};
var reflectionName =''' // Break long line.
''' unmangledName + ":" + requiredParameterCount +''' // Break long line.
@@ -238,8 +239,9 @@
var previousProperty;
if (firstChar === "+") {
mangledGlobalNames[previousProperty] = property.substring(1);
- if (descriptor[property] == 1) ''' // Break long line.
- '''descriptor[previousProperty].$reflectableField = 1;
+ var flag = descriptor[property];
+ if (flag > 0) ''' // Break long line.
+ '''descriptor[previousProperty].$reflectableField = flag;
if (element && element.length) ''' // Break long line.
'''init.typeInformation[previousProperty] = element;
} else if (firstChar === "@") {
@@ -270,8 +272,9 @@
processStatics(init.statics[property] = element[prop]);
} else if (firstChar === "+") {
mangledNames[previousProp] = prop.substring(1);
- if (element[prop] == 1) ''' // Break long line.
- '''element[previousProp].$reflectableField = 1;
+ var flag = element[prop];
+ if (flag > 0) ''' // Break long line.
+ '''element[previousProp].$reflectableField = flag;
} else if (firstChar === "@" && prop !== "@") {
newDesc[prop.substring(1)][$metadataField] = element[prop];
} else if (firstChar === "*") {
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index caad757..4ab41ca 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -3879,8 +3879,7 @@
calculateAllSupertypes(element);
if (!element.hasConstructor) {
- Element superMember =
- element.superclass.localLookup('');
+ Element superMember = element.superclass.localLookup('');
if (superMember == null || !superMember.isGenerativeConstructor()) {
DualKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR;
Map arguments = {'constructorName': ''};
@@ -3890,6 +3889,13 @@
superMember = new ErroneousElementX(
kind.error, arguments, '', element);
compiler.backend.registerThrowNoSuchMethod(mapping);
+ } else {
+ Selector callToMatch = new Selector.call("", element.getLibrary(), 0);
+ if (!callToMatch.applies(superMember, compiler)) {
+ MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT;
+ compiler.reportError(node, kind);
+ superMember = new ErroneousElementX(kind, {}, '', element);
+ }
}
FunctionElement constructor =
new SynthesizedConstructorElementX.forDefault(superMember, element);
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index 8be9ee5..92b23ad 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -396,11 +396,16 @@
}
String parameterName(int parameter) {
- int metadataIndex = JS('int', '#[# + # + #]', data, parameter,
- optionalParameterCount, FIRST_DEFAULT_ARGUMENT);
+ int metadataIndex = JS('int', '#[2 * # + # + #]', data, parameter,
+ optionalParameterCount, FIRST_DEFAULT_ARGUMENT);
return JS('String', 'init.metadata[#]', metadataIndex);
}
+ List<int> parameterMetadataAnnotations(int parameter) {
+ return JS('', '#[2 * # + # + # + 1]', data, parameter,
+ optionalParameterCount, FIRST_DEFAULT_ARGUMENT);
+ }
+
int defaultValue(int parameter) {
if (parameter < requiredParameterCount) return null;
return JS('int', '#[# + # - #]', data,
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index a5ee2bf..6b58b6f 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -355,11 +355,8 @@
throw new NoSuchMethodError(
this, memberName, positionalArguments, namedArguments);
}
- if (mirror is JsMethodMirror) {
- JsMethodMirror method = mirror;
- if (!method.canInvokeReflectively()) {
- throwInvalidReflectionError(n(memberName));
- }
+ if (mirror is JsMethodMirror && !mirror.canInvokeReflectively()) {
+ throwInvalidReflectionError(n(memberName));
}
return reflect(mirror._invoke(positionalArguments, namedArguments));
}
@@ -1537,6 +1534,7 @@
// reflection with metadata.
if (simpleName == null) continue;
var function = JS('', '#[#]', prototype, key);
+ if (isNoSuchMethodStub(function)) continue;
var mirror =
new JsMethodMirror.fromUnmangledName(
simpleName, function, false, false);
@@ -2184,13 +2182,15 @@
bool isNamed = info.areOptionalParametersNamed;
for (JsParameterMirror parameter in type.parameters) {
var name = info.parameterName(i);
+ List<int> annotations = info.parameterMetadataAnnotations(i);
var p;
if (i < info.requiredParameterCount) {
- p = new JsParameterMirror(name, this, parameter._type);
+ p = new JsParameterMirror(name, this, parameter._type,
+ metadataList: annotations);
} else {
var defaultValue = info.defaultValue(i);
p = new JsParameterMirror(
- name, this, parameter._type,
+ name, this, parameter._type, metadataList: annotations,
isOptional: true, isNamed: isNamed, defaultValue: defaultValue);
}
formals[i++] = p;
@@ -2285,10 +2285,13 @@
final int _defaultValue;
+ final List<int> metadataList;
+
JsParameterMirror(String unmangledName,
this.owner,
this._type,
- {this.isOptional: false,
+ {this.metadataList: const <int>[],
+ this.isOptional: false,
this.isNamed: false,
defaultValue})
: _defaultValue = defaultValue,
@@ -2315,8 +2318,10 @@
return hasDefaultValue ? reflect(getMetadata(_defaultValue)) : null;
}
- // TODO(ahe): Implement this.
- List<InstanceMirror> get metadata => throw new UnimplementedError();
+ List<InstanceMirror> get metadata {
+ preserveMetadata();
+ return metadataList.map((int i) => reflect(getMetadata(i))).toList();
+ }
}
class JsTypedefMirror extends JsDeclarationMirror implements TypedefMirror {
@@ -2369,7 +2374,7 @@
InstanceMirror newInstance(
Symbol constructorName,
List positionalArguments,
- [Map<Symbol,dynamic> namedArguments]) => throw new UnimplementedError();
+ [Map<Symbol, dynamic> namedArguments]) => throw new UnimplementedError();
Function operator [](Symbol name) => throw new UnimplementedError();
InstanceMirror invoke(Symbol memberName,
List positionalArguments,
@@ -2546,7 +2551,7 @@
representation = runtimeTypeToString(type);
}
} else {
- getTypeArgument(int index) {
+ TypeMirror getTypeArgument(int index) {
TypeVariable typeVariable = getMetadata(index);
int variableIndex =
findTypeVariableIndex(ownerClass.typeVariables, typeVariable.name);
@@ -2562,8 +2567,9 @@
}
String substituteTypeVariable(int index) {
var typeArgument = getTypeArgument(index);
- if (typeArgument is JsTypeVariableMirror)
+ if (typeArgument is JsTypeVariableMirror) {
return '${typeArgument._metadataIndex}';
+ }
if (typeArgument is! JsClassMirror &&
typeArgument is! JsTypeBoundClassMirror) {
if (typeArgument == JsMirrorSystem._dynamicType) {
@@ -2683,6 +2689,10 @@
return firstChar == '*' || firstChar == '+';
}
+bool isNoSuchMethodStub(var jsFunction) {
+ return JS('bool', r'#.$reflectable == 2', jsFunction);
+}
+
class NoSuchStaticMethodError extends Error implements NoSuchMethodError {
static const int MISSING_CONSTRUCTOR = 0;
final ClassMirror _cls;
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 48e3c70..5dfe170 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -555,6 +555,7 @@
if (_head == _tail) throw new StateError("No elements");
_modificationCount++;
E result = _table[_head];
+ _table[_head] = null;
_head = (_head + 1) & (_table.length - 1);
return result;
}
@@ -563,7 +564,9 @@
if (_head == _tail) throw new StateError("No elements");
_modificationCount++;
_tail = (_tail - 1) & (_table.length - 1);
- return _table[_tail];
+ E result = _table[_tail];
+ _table[_tail] = null;
+ return result;
}
// Internal helper functions.
diff --git a/tests/language/constructor10_test.dart b/tests/language/constructor10_test.dart
new file mode 100644
index 0000000..f4923b7
--- /dev/null
+++ b/tests/language/constructor10_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2014, 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.
+
+// Check that the implicit super call for synthetic constructors are checked.
+
+
+class A {
+ final x;
+ A(this.x);
+}
+
+class B extends A {
+ /* /// 00: compile-time error
+ B() : super(null);
+ */ /// 00: continued
+}
+
+// ==========
+
+class Y extends A {
+ /* /// 01: compile-time error
+ Y() : super(null);
+ */ /// 01: continued
+}
+
+class Z extends Y {
+ Z() : super();
+}
+
+// ==============
+
+class G extends A {
+ /* /// 02: compile-time error
+ G() : super(null);
+ */ /// 02: continued
+}
+
+class H extends G {
+}
+
+main() {
+ new B().x;
+ new Z().x;
+ new H().x;
+}
diff --git a/tests/language/constructor11_test.dart b/tests/language/constructor11_test.dart
new file mode 100644
index 0000000..5a971e5
--- /dev/null
+++ b/tests/language/constructor11_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2014, 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.
+
+// Check that the implicit super call for synthetic constructors are checked.
+
+import "package:expect/expect.dart";
+
+class A {
+ final x;
+ A([this.x = 499]);
+}
+
+class B extends A {
+}
+
+// ==========
+
+class X {
+ final x;
+ X([this.x = 42]);
+}
+
+class Y extends X {
+}
+
+class Z extends Y {
+ Z() : super();
+}
+
+// ==============
+
+class F {
+ final x;
+ F([this.x = 99]);
+}
+
+class G extends F {
+}
+
+class H extends G {
+}
+
+main() {
+ Expect.equals(499, new B().x);
+ Expect.equals(42, new Z().x);
+ Expect.equals(99, new H().x);
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index a4feb07..fa7539b 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -48,6 +48,8 @@
mirrors/generic_mixin_test: RuntimeError # Issue 12333
mirrors/generic_mixin_applications_test: RuntimeError # Issue 12333
mirrors/hierarchy_invariants_test: RuntimeError # Issue 15262
+mirrors/hot_get_field_test: CompileTimeError # Issue 12164
+mirrors/hot_set_field_test: CompileTimeError # Issue 12164
mirrors/immutable_collections_test: RuntimeError # Issue 14030
mirrors/initializing_formals_test/01: RuntimeError # Issue 6490
mirrors/initializing_formals_test/03: CompileTimeError # Issue 12164
diff --git a/tests/lib/mirrors/hot_get_field_test.dart b/tests/lib/mirrors/hot_get_field_test.dart
new file mode 100644
index 0000000..ca798d3
--- /dev/null
+++ b/tests/lib/mirrors/hot_get_field_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2014, 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.
+
+library test.hot_get_field;
+
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+class C {
+ var field;
+ var _field;
+}
+
+const int optimizationThreshold = 20;
+
+testPublic() {
+ var c = new C();
+ var im = reflect(c);
+
+ for (int i = 0; i < (2 * optimizationThreshold); i++) {
+ c.field = i;
+ Expect.equals(i, im.getField(#field).reflectee);
+ }
+}
+
+testPrivate() {
+ var c = new C();
+ var im = reflect(c);
+
+ for (int i = 0; i < (2 * optimizationThreshold); i++) {
+ c._field = i;
+ Expect.equals(i, im.getField(#_field).reflectee);
+ }
+}
+
+testPrivateWrongLibrary() {
+ var c = new C();
+ var im = reflect(c);
+ var selector = MirrorSystem.getSymbol('_field', reflectClass(Mirror).owner);
+
+ for (int i = 0; i < (2 * optimizationThreshold); i++) {
+ Expect.throws(() => im.getField(selector), (e) => e is NoSuchMethodError);
+ }
+}
+
+main() {
+ testPublic();
+ testPrivate();
+ testPrivateWrongLibrary();
+}
diff --git a/tests/lib/mirrors/hot_set_field_test.dart b/tests/lib/mirrors/hot_set_field_test.dart
new file mode 100644
index 0000000..f427f44
--- /dev/null
+++ b/tests/lib/mirrors/hot_set_field_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2014, 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.
+
+library test.hot_set_field;
+
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+class C {
+ var field;
+ var _field;
+}
+
+const int optimizationThreshold = 20;
+
+testPublic() {
+ var c = new C();
+ var im = reflect(c);
+
+ for (int i = 0; i < (2 * optimizationThreshold); i++) {
+ im.setField(#field, i);
+ Expect.equals(i, c.field);
+ }
+}
+
+testPrivate() {
+ var c = new C();
+ var im = reflect(c);
+
+ for (int i = 0; i < (2 * optimizationThreshold); i++) {
+ im.setField(#_field, i);
+ Expect.equals(i, c._field);
+ }
+}
+
+testPrivateWrongLibrary() {
+ var c = new C();
+ var im = reflect(c);
+ var selector = MirrorSystem.getSymbol('_field', reflectClass(Mirror).owner);
+
+ for (int i = 0; i < (2 * optimizationThreshold); i++) {
+ Expect.throws(() => im.setField(selector, i), (e) => e is NoSuchMethodError);
+ }
+}
+
+main() {
+ testPublic();
+ testPrivate();
+ testPrivateWrongLibrary();
+}
diff --git a/tests/lib/mirrors/parameter_annotation_mirror_test.dart b/tests/lib/mirrors/parameter_annotation_mirror_test.dart
new file mode 100644
index 0000000..c0a625a
--- /dev/null
+++ b/tests/lib/mirrors/parameter_annotation_mirror_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2014, 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.
+
+@MirrorsUsed(targets: "Foo")
+import "dart:mirrors";
+
+import 'package:expect/expect.dart';
+
+class ParameterAnnotation {
+ final String value;
+ const ParameterAnnotation(this.value);
+}
+
+class Foo {
+ f1(@ParameterAnnotation("hest") p) {}
+ f2(@ParameterAnnotation("hest") @ParameterAnnotation("fisk") p) {}
+ f3(a, @ParameterAnnotation("fugl") p) {}
+ f4(@ParameterAnnotation("fisk") a,
+ {@ParameterAnnotation("hval") p}) {}
+ f5(@ParameterAnnotation("fisk") a,
+ [@ParameterAnnotation("hval") p]) {}
+}
+
+expectAnnotations(Type type, Symbol method, int parameterIndex,
+ List<String> expectedValues) {
+ MethodMirror mirror = reflectClass(type).declarations[method];
+ ParameterMirror parameter = mirror.parameters[parameterIndex];
+ List<InstanceMirror> annotations = parameter.metadata;
+ Expect.equals(annotations.length, expectedValues.length,
+ "wrong number of parameter annotations");
+ for (int i = 0; i < annotations.length; i++) {
+ Expect.equals(expectedValues[i], annotations[i].reflectee.value,
+ "annotation #$i of parameter #$parameterIndex "
+ "of $type.$method.");
+ }
+}
+
+main() {
+ expectAnnotations(Foo, #f1, 0, ["hest"]);
+ expectAnnotations(Foo, #f2, 0, ["hest", "fisk"]);
+ expectAnnotations(Foo, #f3, 0, []);
+ expectAnnotations(Foo, #f3, 1, ["fugl"]);
+ expectAnnotations(Foo, #f4, 0, ["fisk"]);
+ expectAnnotations(Foo, #f4, 1, ["hval"]);
+ expectAnnotations(Foo, #f5, 0, ["fisk"]);
+ expectAnnotations(Foo, #f5, 1, ["hval"]);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 1fcfef6..30638fd 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 2
PATCH 0
PRERELEASE 5
-PRERELEASE_PATCH 4
+PRERELEASE_PATCH 5