Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library docgen.models.clazz; | 5 library docgen.models.clazz; |
| 6 | 6 |
| 7 import '../exports/dart2js_mirrors.dart' as dart2js_mirrors; | 7 import '../exports/dart2js_mirrors.dart' as dart2js_mirrors; |
| 8 import '../exports/mirrors_util.dart' as dart2js_util; | 8 import '../exports/mirrors_util.dart' as dart2js_util; |
| 9 import '../exports/source_mirrors.dart'; | 9 import '../exports/source_mirrors.dart'; |
| 10 | 10 |
| 11 import '../library_helpers.dart'; | 11 import '../library_helpers.dart'; |
| 12 | 12 |
| 13 import 'dummy_mirror.dart'; | 13 import 'dummy_mirror.dart'; |
| 14 import 'generic.dart'; | 14 import 'generic.dart'; |
| 15 import 'indexable.dart'; | |
| 16 import 'library.dart'; | 15 import 'library.dart'; |
| 17 import 'method.dart'; | 16 import 'method.dart'; |
| 18 import 'model_helpers.dart'; | 17 import 'model_helpers.dart'; |
| 19 import 'owned_indexable.dart'; | 18 import 'owned_indexable.dart'; |
| 20 import 'variable.dart'; | 19 import 'variable.dart'; |
| 21 | 20 |
| 22 /// A class containing contents of a Dart class. | 21 /// A class containing contents of a Dart class. |
| 23 class Class extends OwnedIndexable<dart2js_mirrors.Dart2JsInterfaceTypeMirror> | 22 class Class extends OwnedIndexable<dart2js_mirrors.Dart2JsInterfaceTypeMirror> |
| 24 implements Comparable<Class> { | 23 implements Comparable<Class> { |
| 25 | 24 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 36 final Map<String, Variable> inheritedVariables = {}; | 35 final Map<String, Variable> inheritedVariables = {}; |
| 37 | 36 |
| 38 /// Methods in the class. | 37 /// Methods in the class. |
| 39 Map<String, Method> methods; | 38 Map<String, Method> methods; |
| 40 | 39 |
| 41 final Map<String, Method> inheritedMethods = new Map<String, Method>(); | 40 final Map<String, Method> inheritedMethods = new Map<String, Method>(); |
| 42 | 41 |
| 43 /// Generic infomation about the class. | 42 /// Generic infomation about the class. |
| 44 final Map<String, Generic> generics; | 43 final Map<String, Generic> generics; |
| 45 | 44 |
| 46 Class superclass; | 45 Class _superclass; |
| 47 bool get isAbstract => mirror.isAbstract; | 46 bool get isAbstract => mirror.isAbstract; |
| 48 | 47 |
| 49 /// Make sure that we don't check for inherited comments more than once. | 48 /// Make sure that we don't check for inherited comments more than once. |
| 50 bool _commentsEnsured = false; | 49 bool _commentsEnsured = false; |
| 51 | 50 |
| 52 /// Returns the [Class] for the given [mirror] if it has already been created, | 51 /// Returns the [Class] for the given [mirror] if it has already been created, |
| 53 /// else creates it. | 52 /// else creates it. |
| 54 factory Class(ClassMirror mirror, Library owner) { | 53 factory Class(ClassMirror mirror, Library owner) { |
| 55 var clazz = getDocgenObject(mirror, owner); | 54 var clazz = getDocgenObject(mirror, owner); |
| 56 if (clazz is DummyMirror) { | 55 if (clazz is DummyMirror) { |
| 57 clazz = new Class._(mirror, owner); | 56 clazz = new Class._(mirror, owner); |
| 58 } | 57 } |
| 59 return clazz; | 58 return clazz; |
| 60 } | 59 } |
| 61 | 60 |
| 62 /// Called when we are constructing a superclass or interface class, but it | 61 /// Called when we are constructing a superclass or interface class, but it |
| 63 /// is not known if it belongs to the same owner as the original class. In | 62 /// is not known if it belongs to the same owner as the original class. In |
| 64 /// this case, we create an object whose owner is what the original mirror | 63 /// this case, we create an object whose owner is what the original mirror |
| 65 /// says it is. | 64 /// says it is. |
| 66 factory Class._possiblyDifferentOwner(ClassMirror mirror, | 65 factory Class._possiblyDifferentOwner(ClassMirror mirror, |
| 67 Library originalOwner) { | 66 Library originalOwner) { |
| 68 if (mirror.owner is LibraryMirror) { | 67 var realOwner = getDocgenObject(mirror.owner); |
|
kevmoo
2014/04/21 19:22:19
mirror.owner is always a LibraryMirror
| |
| 69 var realOwner = getDocgenObject(mirror.owner); | 68 if (realOwner is Library) { |
| 70 if (realOwner is Library) { | 69 return new Class(mirror, realOwner); |
| 71 return new Class(mirror, realOwner); | |
| 72 } else { | |
| 73 return new Class(mirror, originalOwner); | |
| 74 } | |
| 75 } else { | 70 } else { |
| 76 return new Class(mirror, originalOwner); | 71 return new Class(mirror, originalOwner); |
| 77 } | 72 } |
| 78 } | 73 } |
| 79 | 74 |
| 80 Class._(ClassSourceMirror classMirror, Indexable owner) | 75 Class._(ClassSourceMirror classMirror, Library owner) |
| 81 : generics = createGenerics(classMirror), | 76 : generics = createGenerics(classMirror), |
| 82 super(classMirror, owner) { | 77 super(classMirror, owner) { |
| 83 | 78 |
| 84 // The reason we do this madness is the superclass and interface owners may | 79 // The reason we do this madness is the superclass and interface owners may |
| 85 // not be this class's owner!! Example: BaseClient in http pkg. | 80 // not be this class's owner!! Example: BaseClient in http pkg. |
| 86 var superinterfaces = classMirror.superinterfaces.map( | 81 var superinterfaces = classMirror.superinterfaces.map( |
| 87 (interface) => new Class._possiblyDifferentOwner(interface, owner)); | 82 (interface) => new Class._possiblyDifferentOwner(interface, owner)); |
| 88 this.superclass = classMirror.superclass == null? null : | 83 this._superclass = classMirror.superclass == null? null : |
| 89 new Class._possiblyDifferentOwner(classMirror.superclass, owner); | 84 new Class._possiblyDifferentOwner(classMirror.superclass, owner); |
| 90 | 85 |
| 91 interfaces = superinterfaces.toList(); | 86 interfaces = superinterfaces.toList(); |
| 92 variables = createVariables( | 87 variables = createVariables( |
| 93 dart2js_util.variablesOf(classMirror.declarations), this); | 88 dart2js_util.variablesOf(classMirror.declarations), this); |
| 94 methods = createMethods(classMirror.declarations.values.where( | 89 methods = createMethods(classMirror.declarations.values.where( |
| 95 (mirror) => mirror is MethodMirror), this); | 90 (mirror) => mirror is MethodMirror), this); |
| 96 | 91 |
| 97 // Tell superclass that you are a subclass, unless you are not | 92 // Tell superclass that you are a subclass, unless you are not |
| 98 // visible or an intermediary mixin class. | 93 // visible or an intermediary mixin class. |
| 99 if (!classMirror.isNameSynthetic && isVisible && superclass != null) { | 94 if (!classMirror.isNameSynthetic && isVisible && _superclass != null) { |
| 100 superclass.addSubclass(this); | 95 _superclass.addSubclass(this); |
| 101 } | 96 } |
| 102 | 97 |
| 103 if (this.superclass != null) addInherited(superclass); | 98 if (this._superclass != null) addInherited(_superclass); |
| 104 interfaces.forEach((interface) => addInherited(interface)); | 99 interfaces.forEach((interface) => addInherited(interface)); |
| 105 } | 100 } |
| 106 | 101 |
| 107 String _lookupInClassAndSuperclasses(String name) { | 102 String _lookupInClassAndSuperclasses(String name) { |
| 108 var lookupFunc = determineLookupFunc(name); | 103 var lookupFunc = determineLookupFunc(name); |
| 109 var classScope = this; | 104 var classScope = this; |
| 110 while (classScope != null) { | 105 while (classScope != null) { |
| 111 var classFunc = lookupFunc(classScope.mirror, name); | 106 var classFunc = lookupFunc(classScope.mirror, name); |
| 112 if (classFunc != null) { | 107 if (classFunc != null) { |
| 113 return packagePrefix + getDocgenObject(classFunc, owner).docName; | 108 return packagePrefix + getDocgenObject(classFunc, owner).docName; |
| 114 } | 109 } |
| 115 classScope = classScope.superclass; | 110 classScope = classScope._superclass; |
| 116 } | 111 } |
| 117 return null; | 112 return null; |
| 118 } | 113 } |
| 119 | 114 |
| 120 /// Look for the specified name starting with the current member, and | 115 /// Look for the specified name starting with the current member, and |
| 121 /// progressively working outward to the current library scope. | 116 /// progressively working outward to the current library scope. |
| 122 String findElementInScope(String name) { | 117 String findElementInScope(String name) { |
| 123 var lookupFunc = determineLookupFunc(name); | 118 var lookupFunc = determineLookupFunc(name); |
| 124 var result = _lookupInClassAndSuperclasses(name); | 119 var result = _lookupInClassAndSuperclasses(name); |
| 125 if (result != null) { | 120 if (result != null) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 } | 164 } |
| 170 | 165 |
| 171 /// Add the subclass to the class. | 166 /// Add the subclass to the class. |
| 172 /// | 167 /// |
| 173 /// If [this] is private (or an intermediary mixin class), it will add the | 168 /// If [this] is private (or an intermediary mixin class), it will add the |
| 174 /// subclass to the list of subclasses in the superclasses. | 169 /// subclass to the list of subclasses in the superclasses. |
| 175 void addSubclass(Class subclass) { | 170 void addSubclass(Class subclass) { |
| 176 if (docName == 'dart-core.Object') return; | 171 if (docName == 'dart-core.Object') return; |
| 177 | 172 |
| 178 if (!includePrivateMembers && isPrivate || mirror.isNameSynthetic) { | 173 if (!includePrivateMembers && isPrivate || mirror.isNameSynthetic) { |
| 179 if (superclass != null) superclass.addSubclass(subclass); | 174 if (_superclass != null) _superclass.addSubclass(subclass); |
| 180 interfaces.forEach((interface) { | 175 interfaces.forEach((interface) { |
| 181 interface.addSubclass(subclass); | 176 interface.addSubclass(subclass); |
| 182 }); | 177 }); |
| 183 } else { | 178 } else { |
| 184 subclasses.add(subclass); | 179 subclasses.add(subclass); |
| 185 } | 180 } |
| 186 } | 181 } |
| 187 | 182 |
| 188 /// Check if this [Class] is an error or exception. | 183 /// Check if this [Class] is an error or exception. |
| 189 bool isError() { | 184 bool isError() { |
| 190 if (qualifiedName == 'dart-core.Error' || | 185 if (qualifiedName == 'dart-core.Error' || |
| 191 qualifiedName == 'dart-core.Exception') | 186 qualifiedName == 'dart-core.Exception') |
| 192 return true; | 187 return true; |
| 193 for (var interface in interfaces) { | 188 for (var interface in interfaces) { |
| 194 if (interface.isError()) return true; | 189 if (interface.isError()) return true; |
| 195 } | 190 } |
| 196 if (superclass == null) return false; | 191 if (_superclass == null) return false; |
| 197 return superclass.isError(); | 192 return _superclass.isError(); |
| 198 } | 193 } |
| 199 | 194 |
| 200 /// Makes sure that all methods with inherited equivalents have comments. | 195 /// Makes sure that all methods with inherited equivalents have comments. |
| 201 void ensureComments() { | 196 void ensureComments() { |
| 202 if (_commentsEnsured) return; | 197 if (_commentsEnsured) return; |
| 203 _commentsEnsured = true; | 198 _commentsEnsured = true; |
| 204 if (superclass != null) superclass.ensureComments(); | 199 if (_superclass != null) _superclass.ensureComments(); |
| 205 inheritedMethods.forEach((qualifiedName, inheritedMethod) { | 200 inheritedMethods.forEach((qualifiedName, inheritedMethod) { |
| 206 var method = methods[qualifiedName]; | 201 var method = methods[qualifiedName]; |
| 207 if (method != null) { | 202 if (method != null) { |
| 208 // if we have overwritten this method in this class, we still provide | 203 // if we have overwritten this method in this class, we still provide |
| 209 // the opportunity to inherit the comments. | 204 // the opportunity to inherit the comments. |
| 210 method.ensureCommentFor(inheritedMethod); | 205 method.ensureCommentFor(inheritedMethod); |
| 211 } | 206 } |
| 212 }); | 207 }); |
| 213 // we need to populate the comments for all methods. so that the subclasses | 208 // we need to populate the comments for all methods. so that the subclasses |
| 214 // can get for their inherited versions the comments. | 209 // can get for their inherited versions the comments. |
| 215 methods.forEach((qualifiedName, method) { | 210 methods.forEach((qualifiedName, method) { |
| 216 if (!method.mirror.isConstructor) method.ensureCommentFor(method); | 211 if (!method.mirror.isConstructor) method.ensureCommentFor(method); |
| 217 }); | 212 }); |
| 218 } | 213 } |
| 219 | 214 |
| 220 /// If a class extends a private superclass, find the closest public | 215 /// If a class extends a private superclass, find the closest public |
| 221 /// superclass of the private superclass. | 216 /// superclass of the private superclass. |
| 222 String validSuperclass() { | 217 String validSuperclass() { |
| 223 if (superclass == null) return 'dart-core.Object'; | 218 if (_superclass == null) return 'dart-core.Object'; |
| 224 if (superclass.isVisible) return superclass.qualifiedName; | 219 if (_superclass.isVisible) return _superclass.qualifiedName; |
| 225 return superclass.validSuperclass(); | 220 return _superclass.validSuperclass(); |
| 226 } | 221 } |
| 227 | 222 |
| 228 /// Generates a map describing the [Class] object. | 223 /// Generates a map describing the [Class] object. |
| 229 Map toMap() => { | 224 Map toMap() => { |
| 230 'name': name, | 225 'name': name, |
| 231 'qualifiedName': qualifiedName, | 226 'qualifiedName': qualifiedName, |
| 232 'comment': comment, | 227 'comment': comment, |
| 233 'isAbstract' : isAbstract, | 228 'isAbstract' : isAbstract, |
| 234 'superclass': validSuperclass(), | 229 'superclass': validSuperclass(), |
| 235 'implements': interfaces.where((i) => i.isVisible) | 230 'implements': interfaces.where((i) => i.isVisible) |
| 236 .map((e) => e.qualifiedName).toList(), | 231 .map((e) => e.qualifiedName).toList(), |
| 237 'subclass': (subclasses.toList()..sort()) | 232 'subclass': (subclasses.toList()..sort()) |
| 238 .map((x) => x.qualifiedName).toList(), | 233 .map((x) => x.qualifiedName).toList(), |
| 239 'variables': recurseMap(variables), | 234 'variables': recurseMap(variables), |
| 240 'inheritedVariables': recurseMap(inheritedVariables), | 235 'inheritedVariables': recurseMap(inheritedVariables), |
| 241 'methods': expandMethodMap(methods), | 236 'methods': expandMethodMap(methods), |
| 242 'inheritedMethods': expandMethodMap(inheritedMethods), | 237 'inheritedMethods': expandMethodMap(inheritedMethods), |
| 243 'annotations': annotations.map((a) => a.toMap()).toList(), | 238 'annotations': annotations.map((a) => a.toMap()).toList(), |
| 244 'generics': recurseMap(generics) | 239 'generics': recurseMap(generics) |
| 245 }; | 240 }; |
| 246 | 241 |
| 247 int compareTo(Class other) => name.compareTo(other.name); | 242 int compareTo(Class other) => name.compareTo(other.name); |
| 248 | 243 |
| 249 bool isValidMirror(DeclarationMirror mirror) => mirror is ClassMirror; | 244 bool isValidMirror(DeclarationMirror mirror) => mirror is ClassMirror; |
| 250 } | 245 } |
| OLD | NEW |