Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2821)

Unified Diff: pkg/compiler/lib/src/mirrors/mirrors_util.dart

Issue 1805563002: Revert "Delete support for source mirrors" (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/mirrors/mirrors_util.dart
diff --git a/pkg/compiler/lib/src/mirrors/mirrors_util.dart b/pkg/compiler/lib/src/mirrors/mirrors_util.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d1d4f5f26449b2764ab6da0959c3310e409d9098
--- /dev/null
+++ b/pkg/compiler/lib/src/mirrors/mirrors_util.dart
@@ -0,0 +1,429 @@
+// Copyright (c) 2012, 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 mirrors_util;
+
+import 'dart:collection' show Queue, IterableBase;
+
+import 'source_mirrors.dart';
+
+//------------------------------------------------------------------------------
+// Utility functions for using the Mirror API
+//------------------------------------------------------------------------------
+
+String nameOf(DeclarationMirror mirror) =>
+ MirrorSystem.getName(mirror.simpleName);
+
+String qualifiedNameOf(DeclarationMirror mirror) =>
+ MirrorSystem.getName(mirror.qualifiedName);
+
+// TODO(johnniwinther): Handle private names.
+Symbol symbolOf(String name, [LibraryMirror library]) => new Symbol(name);
+
+/**
+ * Return the display name for [mirror].
+ *
+ * The display name is the normal representation of the entity name. In most
+ * cases the display name is the simple name, but for a setter 'foo=' the
+ * display name is simply 'foo' and for the unary minus operator the display
+ * name is 'operator -'. For 'dart:' libraries the display name is the URI and
+ * not the library name, for instance 'dart:core' instead of 'dart.core'.
+ *
+ * The display name is not unique.
+ */
+String displayName(DeclarationMirror mirror) {
+ if (mirror is LibraryMirror) {
+ LibraryMirror library = mirror;
+ if (library.uri.scheme == 'dart') {
+ return library.uri.toString();
+ }
+ } else if (mirror is MethodMirror) {
+ String simpleName = nameOf(mirror);
+ if (mirror.isSetter) {
+ // Remove trailing '='.
+ return simpleName.substring(0, simpleName.length-1);
+ } else if (mirror.isOperator) {
+ return 'operator ${operatorName(mirror)}';
+ } else if (mirror.isConstructor) {
+ String className = displayName(mirror.owner);
+ if (simpleName == '') {
+ return className;
+ } else {
+ return '$className.$simpleName';
+ }
+ }
+ }
+ return MirrorSystem.getName(mirror.simpleName);
+}
+
+/**
+ * Returns the operator name if [methodMirror] is an operator method,
+ * for instance [:'<':] for [:operator <:] and [:'-':] for the unary minus
+ * operator. Return [:null:] if [methodMirror] is not an operator method.
+ */
+String operatorName(MethodMirror methodMirror) {
+ if (methodMirror.isOperator) {
+ if (methodMirror.simpleName == const Symbol('unary-')) {
+ return '-';
+ } else {
+ return nameOf(methodMirror);
+ }
+ }
+ return null;
+}
+
+/**
+ * Returns an iterable over the type declarations directly inheriting from
+ * the declaration of [type] within [mirrors].
+ */
+Iterable<ClassMirror> computeSubdeclarations(MirrorSystem mirrors,
+ ClassMirror type) {
+ type = type.originalDeclaration;
+ var subtypes = <ClassMirror>[];
+ mirrors.libraries.forEach((_, library) {
+ library.declarations.values
+ .where((mirror) => mirror is ClassMirror)
+ .forEach((ClassMirror otherType) {
+ var superClass = otherType.superclass;
+ if (superClass != null) {
+ superClass = superClass.originalDeclaration;
+ if (superClass == type) {
+ subtypes.add(otherType);
+ }
+ }
+ final superInterfaces = otherType.superinterfaces;
+ for (ClassMirror superInterface in superInterfaces) {
+ superInterface = superInterface.originalDeclaration;
+ if (superInterface == type) {
+ subtypes.add(otherType);
+ }
+ }
+ });
+ });
+ return subtypes;
+}
+
+class HierarchyIterable extends IterableBase<ClassMirror> {
+ final bool includeType;
+ final ClassMirror type;
+
+ HierarchyIterable(this.type, {bool includeType})
+ : this.includeType = includeType;
+
+ Iterator<ClassMirror> get iterator =>
+ new HierarchyIterator(type, includeType: includeType);
+}
+
+/**
+ * [HierarchyIterator] iterates through the class hierarchy of the provided
+ * type.
+ *
+ * First the superclass relation is traversed, skipping [Object], next the
+ * superinterface relation and finally is [Object] visited. The supertypes are
+ * visited in breadth first order and a superinterface is visited more than once
+ * if implemented through multiple supertypes.
+ */
+class HierarchyIterator implements Iterator<ClassMirror> {
+ final Queue<ClassMirror> queue = new Queue<ClassMirror>();
+ ClassMirror object;
+ ClassMirror _current;
+
+ HierarchyIterator(ClassMirror type, {bool includeType}) {
+ if (includeType) {
+ queue.add(type);
+ } else {
+ push(type);
+ }
+ }
+
+ ClassMirror push(ClassMirror type) {
+ if (type.superclass != null) {
+ if (isObject(type.superclass)) {
+ object = type.superclass;
+ } else {
+ queue.addFirst(type.superclass);
+ }
+ }
+ queue.addAll(type.superinterfaces);
+ return type;
+ }
+
+ ClassMirror get current => _current;
+
+ bool moveNext() {
+ _current = null;
+ if (queue.isEmpty) {
+ if (object == null) return false;
+ _current = object;
+ object = null;
+ return true;
+ } else {
+ _current = push(queue.removeFirst());
+ return true;
+ }
+ }
+}
+
+LibraryMirror getLibrary(DeclarationMirror declaration) {
+ while (declaration != null && declaration is! LibraryMirror) {
+ declaration = declaration.owner;
+ }
+ return declaration;
+}
+
+Iterable<DeclarationMirror> membersOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return declarations.values.where(
+ (mirror) => mirror is MethodMirror || mirror is VariableMirror);
+}
+
+Iterable<TypeMirror> classesOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return new _TypeOfIterable<ClassMirror>(declarations.values);
+}
+
+Iterable<TypeMirror> typesOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return new _TypeOfIterable<TypeMirror>(declarations.values);
+}
+
+Iterable<MethodMirror> methodsOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return anyMethodOf(declarations).where((mirror) => mirror.isRegularMethod);
+}
+
+Iterable<MethodMirror> constructorsOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return anyMethodOf(declarations).where((mirror) => mirror.isConstructor);
+}
+
+Iterable<MethodMirror> settersOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return anyMethodOf(declarations).where((mirror) => mirror.isSetter);
+}
+
+Iterable<MethodMirror> gettersOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return anyMethodOf(declarations).where((mirror) => mirror.isGetter);
+}
+
+Iterable<MethodMirror> anyMethodOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return new _TypeOfIterable<MethodMirror>(declarations.values);
+}
+
+Iterable<VariableMirror> variablesOf(
+ Map<Symbol, DeclarationMirror> declarations) {
+ return new _TypeOfIterable<VariableMirror>(declarations.values);
+}
+
+class _TypeOfIterable<T> extends IterableBase<T> {
+ final Iterable _source;
+
+ _TypeOfIterable(this._source);
+
+ Iterator<T> get iterator => new _TypeOfIterator<T>(_source.iterator);
+}
+
+class _TypeOfIterator<T> implements Iterator<T> {
+ final Iterator _source;
+
+ T get current => _source.current;
+
+ _TypeOfIterator(this._source);
+
+ bool moveNext() {
+ while(_source.moveNext()) {
+ if (_source.current is T) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+bool isObject(TypeMirror mirror) =>
+ mirror is ClassMirror && mirror.superclass == null;
+
+/// Returns `true` if [cls] is declared in a private dart library.
+bool isFromPrivateDartLibrary(ClassMirror cls) {
+ if (isMixinApplication(cls)) cls = cls.mixin;
+ var uri = getLibrary(cls).uri;
+ return uri.scheme == 'dart' && uri.path.startsWith('_');
+}
+
+/// Returns `true` if [mirror] reflects a mixin application.
+bool isMixinApplication(Mirror mirror) {
+ return mirror is ClassMirror && mirror.mixin != mirror;
+}
+
+/**
+ * Returns the superclass of [cls] skipping unnamed mixin applications.
+ *
+ * For instance, for all of the following definitions this method returns [:B:].
+ *
+ * class A extends B {}
+ * class A extends B with C1, C2 {}
+ * class A extends B implements D1, D2 {}
+ * class A extends B with C1, C2 implements D1, D2 {}
+ * class A = B with C1, C2;
+ * abstract class A = B with C1, C2 implements D1, D2;
+ */
+ClassSourceMirror getSuperclass(ClassSourceMirror cls) {
+ ClassSourceMirror superclass = cls.superclass;
+ while (isMixinApplication(superclass) && superclass.isNameSynthetic) {
+ superclass = superclass.superclass;
+ }
+ return superclass;
+}
+
+/**
+ * Returns the mixins directly applied to [cls].
+ *
+ * For instance, for all of the following definitions this method returns
+ * [:C1, C2:].
+ *
+ * class A extends B with C1, C2 {}
+ * class A extends B with C1, C2 implements D1, D2 {}
+ * class A = B with C1, C2;
+ * abstract class A = B with C1, C2 implements D1, D2;
+ */
+Iterable<ClassSourceMirror> getAppliedMixins(ClassSourceMirror cls) {
+ List<ClassSourceMirror> mixins = <ClassSourceMirror>[];
+ ClassSourceMirror superclass = cls.superclass;
+ while (isMixinApplication(superclass) && superclass.isNameSynthetic) {
+ mixins.add(superclass.mixin);
+ superclass = superclass.superclass;
+ }
+ if (mixins.length > 1) {
+ mixins = new List<ClassSourceMirror>.from(mixins.reversed);
+ }
+ if (isMixinApplication(cls)) {
+ mixins.add(cls.mixin);
+ }
+ return mixins;
+}
+
+/**
+ * Returns the superinterfaces directly and explicitly implemented by [cls].
+ *
+ * For instance, for all of the following definitions this method returns
+ * [:D1, D2:].
+ *
+ * class A extends B implements D1, D2 {}
+ * class A extends B with C1, C2 implements D1, D2 {}
+ * abstract class A = B with C1, C2 implements D1, D2;
+ */
+Iterable<ClassMirror> getExplicitInterfaces(ClassMirror cls) {
+ if (isMixinApplication(cls)) {
+ bool first = true;
+ ClassMirror mixin = cls.mixin;
+ bool filter(ClassMirror superinterface) {
+ if (first && superinterface == mixin) {
+ first = false;
+ return false;
+ }
+ return true;
+ }
+ return cls.superinterfaces.where(filter);
+ }
+ return cls.superinterfaces;
+}
+
+final RegExp _singleLineCommentStart = new RegExp(r'^///? ?(.*)');
+final RegExp _multiLineCommentStartEnd =
+ new RegExp(r'^/\*\*? ?([\s\S]*)\*/$', multiLine: true);
+final RegExp _multiLineCommentLineStart = new RegExp(r'^[ \t]*\* ?(.*)');
+
+/**
+ * Pulls the raw text out of a comment (i.e. removes the comment
+ * characters).
+ */
+String stripComment(String comment) {
+ Match match = _singleLineCommentStart.firstMatch(comment);
+ if (match != null) {
+ return match[1];
+ }
+ match = _multiLineCommentStartEnd.firstMatch(comment);
+ if (match != null) {
+ comment = match[1];
+ var sb = new StringBuffer();
+ List<String> lines = comment.split('\n');
+ for (int index = 0 ; index < lines.length ; index++) {
+ String line = lines[index];
+ if (index == 0) {
+ sb.write(line); // Add the first line unprocessed.
+ continue;
+ }
+ sb.write('\n');
+ match = _multiLineCommentLineStart.firstMatch(line);
+ if (match != null) {
+ sb.write(match[1]);
+ } else if (index < lines.length-1 || !line.trim().isEmpty) {
+ // Do not add the last line if it only contains white space.
+ // This interprets cases like
+ // /*
+ // * Foo
+ // */
+ // as "\nFoo\n" and not as "\nFoo\n ".
+ sb.write(line);
+ }
+ }
+ return sb.toString();
+ }
+ throw new ArgumentError('Invalid comment $comment');
+}
+
+/**
+ * Looks up [name] in the scope [declaration].
+ *
+ * If [name] is of the form 'a.b.c', 'a' is looked up in the scope of
+ * [declaration] and if unresolved 'a.b' is looked in the scope of
+ * [declaration]. Each identifier of the remaining suffix, 'c' or 'b.c', is
+ * then looked up in the local scope of the previous result.
+ *
+ * For instance, assumming that [:Iterable:] is imported into the scope of
+ * [declaration] via the prefix 'col', 'col.Iterable.E' finds the type
+ * variable of [:Iterable:] and 'col.Iterable.contains.element' finds the
+ * [:element:] parameter of the [:contains:] method on [:Iterable:].
+ */
+DeclarationMirror lookupQualifiedInScope(DeclarationSourceMirror declaration,
+ String name) {
+ // TODO(11653): Support lookup of constructors using the [:new Foo:]
+ // syntax.
+ int offset = 1;
+ List<String> parts = name.split('.');
+ DeclarationMirror result = declaration.lookupInScope(parts[0]);
+ if (result == null && parts.length > 1) {
+ // Try lookup of `prefix.id`.
+ result = declaration.lookupInScope('${parts[0]}.${parts[1]}');
+ offset = 2;
+ }
+ if (result == null) return null;
+ LibraryMirror library = getLibrary(result);
+ while (result != null && offset < parts.length) {
+ result = _lookupLocal(result, symbolOf(parts[offset++], library));
+ }
+ return result;
+}
+
+DeclarationMirror _lookupLocal(Mirror mirror, Symbol id) {
+ DeclarationMirror result;
+ if (mirror is LibraryMirror) {
+ // Try member lookup.
+ result = mirror.declarations[id];
+ } else if (mirror is ClassMirror) {
+ // Try member lookup.
+ result = mirror.declarations[id];
+ if (result != null) return result;
+ // Try type variables.
+ result = mirror.typeVariables.firstWhere(
+ (TypeVariableMirror v) => v.simpleName == id, orElse: () => null);
+ } else if (mirror is MethodMirror) {
+ result = mirror.parameters.firstWhere(
+ (ParameterMirror p) => p.simpleName == id, orElse: () => null);
+ }
+ return result;
+
+}
« no previous file with comments | « pkg/compiler/lib/src/mirrors/dart2js_type_mirrors.dart ('k') | pkg/compiler/lib/src/mirrors/source_mirrors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698