blob: 72e48784e0d8efd0f77c5e0486e01548da42fdb4 [file] [log] [blame]
// Copyright (c) 2013, 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.
/// Prints all information about all mirrors. This tests that it is possible to
/// enumerate all reflective information without crashing.
// Note: Adding imports below is fine for regression tests. For example,
// 'crash_library_metadata.dart' is imported to ensure the compiler doesn't
// crash.
// TODO(ahe): This test should be extended until we are sure all data is
// printed.
library test.mirror_printer_test;
@MirrorsUsed(targets: '*')
import 'dart:mirrors';
import 'crash_library_metadata.dart'; // This would crash dart2js.
// Importing dart:html to make things interesting.
import 'dart:html';
class MirrorPrinter {
final StringBuffer buffer;
final TypeMirror dynamicType = currentMirrorSystem().dynamicType;
int indentationLevel = 0;
MirrorPrinter(this.buffer);
void w(object) {
buffer.write(object);
}
n(Symbol symbol) => MirrorSystem.getName(symbol);
void indented(action) {
indentationLevel++;
action();
indentationLevel--;
}
get indent {
for (int i = 0; i < indentationLevel; i++) {
w(' ');
}
}
String stringifyInstance(InstanceMirror mirror) {
var reflectee = mirror.reflectee;
if (reflectee is String) return '"${reflectee}"';
if (reflectee is Null || reflectee is bool || reflectee is num ||
reflectee is List || reflectee is Map) {
return '$reflectee';
}
StringBuffer buffer = new StringBuffer();
Map<Symbol, DeclarationMirror> declarations = mirror.type.declarations;
buffer
..write(n(mirror.type.simpleName))
..write('(');
bool first = true;
declarations.forEach((Symbol name, DeclarationMirror declaration) {
if (declaration is! VariableMirror) return;
VariableMirror variable = declaration;
if (variable.isStatic) return;
// TODO(ahe): Include superclasses.
if (first) {
first = false;
} else {
buffer.write(', ');
}
buffer
..write(n(name))
..write(': ')
..write(stringifyInstance(mirror.getField(name)));
});
buffer.write(')');
return buffer.toString();
}
String stringifyMetadata(InstanceMirror mirror) {
return '@${stringifyInstance(mirror)}';
}
bool writeType(TypeMirror mirror) {
if (mirror == null || mirror == dynamicType) return false;
w('${n(mirror.simpleName)} ');
return true;
}
writeVariable(VariableMirror mirror) {
bool needsVar = true;
if (mirror.isStatic) w('static ');
// TODO(ahe): What about const?
if (mirror.isFinal) {
w('final ');
needsVar = false;
}
if (writeType(mirror.type)) needsVar = false;
if (needsVar) {
w('var ');
}
w('${n(mirror.simpleName)};');
}
writeMethod(MethodMirror mirror) {
writeType(mirror.returnType);
if (mirror.isOperator) {
w('operator ');
}
if (mirror.isGetter) {
w('get ');
}
if (mirror.isSetter) {
w('set ');
}
w('${n(mirror.simpleName)}');
if (!mirror.isGetter) {
w('()');
}
w(';');
}
writeClass(ClassMirror mirror) {
// TODO(ahe): Write 'abstract' if [mirror] is abstract.
w('class ${n(mirror.simpleName)}');
// TODO(ahe): Write superclass and interfaces.
w(' {');
bool first = true;
indented(() {
for (DeclarationMirror declaration in mirror.declarations.values) {
if (first) {
first = false;
} else {
w('\n');
}
writeDeclaration(declaration);
}
});
w('\n}\n');
}
writeDeclaration(DeclarationMirror declaration) {
w('\n');
var metadata = declaration.metadata;
if (!metadata.isEmpty) {
indent;
buffer.writeAll(metadata.map(stringifyMetadata), ' ');
w('\n');
}
indent;
if (declaration is ClassMirror) {
writeClass(declaration);
} else if (declaration is VariableMirror) {
writeVariable(declaration);
} else if (declaration is MethodMirror) {
writeMethod(declaration);
} else {
// TODO(ahe): Test other subclasses of DeclarationMirror.
w('$declaration');
}
}
writeLibrary(LibraryMirror library) {
w('library ${n(library.simpleName)};\n\n');
library.declarations.values
.where((d)=> d is! TypeMirror)
.forEach(writeDeclaration);
w('\n');
}
static StringBuffer stringify(Map<Uri, LibraryMirror> libraries) {
StringBuffer buffer = new StringBuffer();
libraries.values.forEach(new MirrorPrinter(buffer).writeLibrary);
return buffer;
}
}
main() {
print(MirrorPrinter.stringify(currentMirrorSystem().libraries));
// Clear the nodes to avoid confusing the fine test framework (by "fine" I
// mean something else) -- ahe.
document.body.nodes.clear();
}