fix #33872, support typeArguments passed to reflectType
Change-Id: I84cfbeec89fa9bf3fa50b7df0ccb6861d364b802
Reviewed-on: https://dart-review.googlesource.com/65201
Commit-Queue: Jenny Messerly <jmesserly@google.com>
Reviewed-by: Bob Nystrom <rnystrom@google.com>
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index c39397d..1140233 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -6381,8 +6381,8 @@
.replaceAll(path.separator, encodedSeparator);
} else {
// We don't have a unique name.
- throw 'Invalid library root. $libraryRoot does not contain ${uri
- .toFilePath()}';
+ throw 'Invalid library root. $libraryRoot does not contain '
+ '${uri.toFilePath()}';
}
return pathToJSIdentifier(qualifiedPath);
}
@@ -6395,8 +6395,8 @@
var filePath = uri.toFilePath();
if (!path.isWithin(libraryRoot, filePath)) {
- throw 'Invalid library root. $libraryRoot does not contain ${uri
- .toFilePath()}';
+ throw 'Invalid library root. $libraryRoot does not contain '
+ '${uri.toFilePath()}';
}
// Relative path to the library.
return path.relative(filePath, from: libraryRoot);
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart
index dec3d20..e3b015b 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/mirrors_patch.dart
@@ -6,6 +6,7 @@
import 'dart:_js_helper' show patch;
import 'dart:_js_mirrors' as js;
+import 'dart:_runtime' as dart;
@patch
class MirrorSystem {
@@ -43,9 +44,39 @@
}
@patch
-TypeMirror reflectType(Type key) {
- if (key == dynamic) {
- return currentMirrorSystem().dynamicType;
+TypeMirror reflectType(Type type, [List<Type> typeArguments]) {
+ if (typeArguments != null) {
+ type = _instantiateClass(type, typeArguments);
}
- return js.reflectType(key);
+ return js.reflectType(type);
+}
+
+/// Instantiates the generic class [type] with [typeArguments] and returns the
+/// result.
+///
+/// [type] may be instantiated with type arguments already. In that case, they
+/// are ignored. For example calling this function with `(List<int>, [String])`
+/// and `(List<dynamic>, [String])` will produce `List<String>` in both cases.
+Type _instantiateClass(Type type, List<Type> typeArguments) {
+ var unwrapped = dart.unwrapType(type);
+ var genericClass = dart.getGenericClass(unwrapped);
+ if (genericClass == null) {
+ throw ArgumentError('Type `$type` must be generic to apply '
+ 'type arguments: `$typeArguments`.');
+ }
+
+ var typeArgsLenth = typeArguments.length;
+ var unwrappedArgs = List(typeArgsLenth);
+ for (int i = 0; i < typeArgsLenth; i++) {
+ unwrappedArgs[i] = dart.unwrapType(typeArguments[i]);
+ }
+ var typeFormals = dart.getGenericTypeFormals(genericClass);
+ if (typeFormals.length != typeArgsLenth) {
+ throw ArgumentError('Type `$type` has ${typeFormals.length} type '
+ 'parameters, but $typeArgsLenth type arguments were '
+ 'passed: `$typeArguments`.');
+ }
+ // TODO(jmesserly): this does not validate bounds, as we don't have them
+ // available at runtime. Consider storing them when dart:mirrors is enabled.
+ return dart.wrapType(dart.instantiateClass(genericClass, unwrappedArgs));
}