Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 library docgen.models.class_indexable; | |
|
kevmoo
2014/04/18 17:03:18
Analyzer does not like a library sub-unit named 'c
Siggi Cherem (dart-lang)
2014/04/18 22:20:08
The name class_indexable is a bit strange. Some ot
kevmoo
2014/04/18 22:36:43
Done.
| |
| 2 | |
| 3 import '../exports/dart2js_mirrors.dart' as dart2js_mirrors; | |
| 4 import '../exports/mirrors_util.dart' as dart2js_util; | |
| 5 import '../exports/source_mirrors.dart'; | |
| 6 | |
| 7 import '../library_helpers.dart'; | |
| 8 | |
| 9 import 'dummy_mirror.dart'; | |
| 10 import 'generic.dart'; | |
| 11 import 'indexable.dart'; | |
| 12 import 'library.dart'; | |
| 13 import 'method.dart'; | |
| 14 import 'model_helpers.dart'; | |
| 15 import 'owned_indexable.dart'; | |
| 16 import 'variable.dart'; | |
| 17 | |
| 18 /// A class containing contents of a Dart class. | |
| 19 class Class extends OwnedIndexable<dart2js_mirrors.Dart2JsInterfaceTypeMirror> | |
| 20 implements Comparable<Class> { | |
| 21 | |
| 22 /// List of the names of interfaces that this class implements. | |
| 23 List<Class> interfaces = []; | |
| 24 | |
| 25 /// Names of classes that extends or implements this class. | |
| 26 Set<Class> subclasses = new Set<Class>(); | |
| 27 | |
| 28 /// Top-level variables in the class. | |
| 29 Map<String, Variable> variables; | |
| 30 | |
| 31 /// Inherited variables in the class. | |
| 32 final Map<String, Variable> inheritedVariables = {}; | |
| 33 | |
| 34 /// Methods in the class. | |
| 35 Map<String, Method> methods; | |
| 36 | |
| 37 final Map<String, Method> inheritedMethods = new Map<String, Method>(); | |
| 38 | |
| 39 /// Generic infomation about the class. | |
| 40 final Map<String, Generic> generics; | |
| 41 | |
| 42 Class superclass; | |
| 43 bool get isAbstract => mirror.isAbstract; | |
| 44 | |
| 45 /// Make sure that we don't check for inherited comments more than once. | |
| 46 bool _commentsEnsured = false; | |
| 47 | |
| 48 /// Returns the [Class] for the given [mirror] if it has already been created, | |
| 49 /// else creates it. | |
| 50 factory Class(ClassMirror mirror, Library owner) { | |
| 51 var clazz = getDocgenObject(mirror, owner); | |
| 52 if (clazz is DummyMirror) { | |
| 53 clazz = new Class._(mirror, owner); | |
| 54 } | |
| 55 return clazz; | |
| 56 } | |
| 57 | |
| 58 /// Called when we are constructing a superclass or interface class, but it | |
| 59 /// is not known if it belongs to the same owner as the original class. In | |
| 60 /// this case, we create an object whose owner is what the original mirror | |
| 61 /// says it is. | |
| 62 factory Class._possiblyDifferentOwner(ClassMirror mirror, | |
| 63 Library originalOwner) { | |
| 64 if (mirror.owner is LibraryMirror) { | |
| 65 var realOwner = getDocgenObject(mirror.owner); | |
| 66 if (realOwner is Library) { | |
| 67 return new Class(mirror, realOwner); | |
| 68 } else { | |
| 69 return new Class(mirror, originalOwner); | |
| 70 } | |
| 71 } else { | |
| 72 return new Class(mirror, originalOwner); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 Class._(ClassSourceMirror classMirror, Indexable owner) | |
| 77 : generics = createGenerics(classMirror), | |
| 78 super(classMirror, owner) { | |
| 79 | |
| 80 // The reason we do this madness is the superclass and interface owners may | |
| 81 // not be this class's owner!! Example: BaseClient in http pkg. | |
| 82 var superinterfaces = classMirror.superinterfaces.map( | |
| 83 (interface) => new Class._possiblyDifferentOwner(interface, owner)); | |
| 84 this.superclass = classMirror.superclass == null? null : | |
| 85 new Class._possiblyDifferentOwner(classMirror.superclass, owner); | |
| 86 | |
| 87 interfaces = superinterfaces.toList(); | |
| 88 variables = createVariables( | |
| 89 dart2js_util.variablesOf(classMirror.declarations), this); | |
| 90 methods = createMethods(classMirror.declarations.values.where( | |
| 91 (mirror) => mirror is MethodMirror), this); | |
| 92 | |
| 93 // Tell superclass that you are a subclass, unless you are not | |
| 94 // visible or an intermediary mixin class. | |
| 95 if (!classMirror.isNameSynthetic && isVisible && superclass != null) { | |
| 96 superclass.addSubclass(this); | |
| 97 } | |
| 98 | |
| 99 if (this.superclass != null) addInherited(superclass); | |
| 100 interfaces.forEach((interface) => addInherited(interface)); | |
| 101 } | |
| 102 | |
| 103 String _lookupInClassAndSuperclasses(String name) { | |
| 104 var lookupFunc = determineLookupFunc(name); | |
| 105 var classScope = this; | |
| 106 while (classScope != null) { | |
| 107 var classFunc = lookupFunc(classScope.mirror, name); | |
| 108 if (classFunc != null) { | |
| 109 return packagePrefix + getDocgenObject(classFunc, owner).docName; | |
| 110 } | |
| 111 classScope = classScope.superclass; | |
| 112 } | |
| 113 return null; | |
| 114 } | |
| 115 | |
| 116 /// Look for the specified name starting with the current member, and | |
| 117 /// progressively working outward to the current library scope. | |
| 118 String findElementInScope(String name) { | |
| 119 var lookupFunc = determineLookupFunc(name); | |
| 120 var result = _lookupInClassAndSuperclasses(name); | |
| 121 if (result != null) { | |
| 122 return result; | |
| 123 } | |
| 124 result = owner.findElementInScope(name); | |
| 125 return result == null ? super.findElementInScope(name) : result; | |
| 126 } | |
| 127 | |
| 128 String get typeName => 'class'; | |
| 129 | |
| 130 /// Add all inherited variables and methods from the provided superclass. | |
| 131 /// If [_includePrivate] is true, it also adds the variables and methods from | |
| 132 /// the superclass. | |
| 133 void addInherited(Class superclass) { | |
| 134 inheritedVariables.addAll(superclass.inheritedVariables); | |
| 135 inheritedVariables.addAll(_allButStatics(superclass.variables)); | |
| 136 addInheritedMethod(superclass, this); | |
| 137 } | |
| 138 | |
| 139 /** [newParent] refers to the actual class is currently using these methods. | |
| 140 * which may be different because with the mirror system, we only point to the | |
| 141 * original canonical superclasse's method. | |
| 142 */ | |
| 143 void addInheritedMethod(Class parent, Class newParent) { | |
| 144 parent.inheritedMethods.forEach((name, method) { | |
| 145 if (!method.mirror.isConstructor) { | |
| 146 inheritedMethods[name] = new Method(method.mirror, newParent, method); | |
| 147 } | |
| 148 }); | |
| 149 _allButStatics(parent.methods).forEach((name, method) { | |
| 150 if (!method.mirror.isConstructor) { | |
| 151 inheritedMethods[name] = new Method(method.mirror, newParent, method); | |
| 152 } | |
| 153 }); | |
| 154 } | |
| 155 | |
| 156 /// Remove statics from the map of inherited items before adding them. | |
| 157 Map _allButStatics(Map items) { | |
| 158 var result = {}; | |
| 159 items.forEach((name, item) { | |
| 160 if (!item.isStatic) { | |
| 161 result[name] = item; | |
| 162 } | |
| 163 }); | |
| 164 return result; | |
| 165 } | |
| 166 | |
| 167 /// Add the subclass to the class. | |
| 168 /// | |
| 169 /// If [this] is private (or an intermediary mixin class), it will add the | |
| 170 /// subclass to the list of subclasses in the superclasses. | |
| 171 void addSubclass(Class subclass) { | |
| 172 if (docName == 'dart-core.Object') return; | |
| 173 | |
| 174 if (!includePrivateMembers && isPrivate || mirror.isNameSynthetic) { | |
| 175 if (superclass != null) superclass.addSubclass(subclass); | |
| 176 interfaces.forEach((interface) { | |
| 177 interface.addSubclass(subclass); | |
| 178 }); | |
| 179 } else { | |
| 180 subclasses.add(subclass); | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 /// Check if this [Class] is an error or exception. | |
| 185 bool isError() { | |
| 186 if (qualifiedName == 'dart-core.Error' || | |
| 187 qualifiedName == 'dart-core.Exception') | |
| 188 return true; | |
| 189 for (var interface in interfaces) { | |
| 190 if (interface.isError()) return true; | |
| 191 } | |
| 192 if (superclass == null) return false; | |
| 193 return superclass.isError(); | |
| 194 } | |
| 195 | |
| 196 /// Makes sure that all methods with inherited equivalents have comments. | |
| 197 void ensureComments() { | |
| 198 if (_commentsEnsured) return; | |
| 199 _commentsEnsured = true; | |
| 200 if (superclass != null) superclass.ensureComments(); | |
| 201 inheritedMethods.forEach((qualifiedName, inheritedMethod) { | |
| 202 var method = methods[qualifiedName]; | |
| 203 if (method != null) { | |
| 204 // if we have overwritten this method in this class, we still provide | |
| 205 // the opportunity to inherit the comments. | |
| 206 method.ensureCommentFor(inheritedMethod); | |
| 207 } | |
| 208 }); | |
| 209 // we need to populate the comments for all methods. so that the subclasses | |
| 210 // can get for their inherited versions the comments. | |
| 211 methods.forEach((qualifiedName, method) { | |
| 212 if (!method.mirror.isConstructor) method.ensureCommentFor(method); | |
| 213 }); | |
| 214 } | |
| 215 | |
| 216 /// If a class extends a private superclass, find the closest public | |
| 217 /// superclass of the private superclass. | |
| 218 String validSuperclass() { | |
| 219 if (superclass == null) return 'dart-core.Object'; | |
| 220 if (superclass.isVisible) return superclass.qualifiedName; | |
| 221 return superclass.validSuperclass(); | |
| 222 } | |
| 223 | |
| 224 /// Generates a map describing the [Class] object. | |
| 225 Map toMap() => { | |
| 226 'name': name, | |
| 227 'qualifiedName': qualifiedName, | |
| 228 'comment': comment, | |
| 229 'isAbstract' : isAbstract, | |
| 230 'superclass': validSuperclass(), | |
| 231 'implements': interfaces.where((i) => i.isVisible) | |
| 232 .map((e) => e.qualifiedName).toList(), | |
| 233 'subclass': (subclasses.toList()..sort()) | |
| 234 .map((x) => x.qualifiedName).toList(), | |
| 235 'variables': recurseMap(variables), | |
| 236 'inheritedVariables': recurseMap(inheritedVariables), | |
| 237 'methods': expandMethodMap(methods), | |
| 238 'inheritedMethods': expandMethodMap(inheritedMethods), | |
| 239 'annotations': annotations.map((a) => a.toMap()).toList(), | |
| 240 'generics': recurseMap(generics) | |
| 241 }; | |
| 242 | |
| 243 int compareTo(Class other) => name.compareTo(other.name); | |
| 244 | |
| 245 bool isValidMirror(DeclarationMirror mirror) => mirror is ClassMirror; | |
| 246 } | |
| OLD | NEW |