| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /** | 5 /** |
| 6 * **docgen** is a tool for creating machine readable representations of Dart | 6 * **docgen** is a tool for creating machine readable representations of Dart |
| 7 * code metadata, including: classes, members, comments and annotations. | 7 * code metadata, including: classes, members, comments and annotations. |
| 8 * | 8 * |
| 9 * docgen is run on a `.dart` file or a directory containing `.dart` files. | 9 * docgen is run on a `.dart` file or a directory containing `.dart` files. |
| 10 * | 10 * |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 /// Current class being documented to be used for comment links. | 44 /// Current class being documented to be used for comment links. |
| 45 ClassMirror _currentClass; | 45 ClassMirror _currentClass; |
| 46 | 46 |
| 47 /// Current member being documented to be used for comment links. | 47 /// Current member being documented to be used for comment links. |
| 48 MemberMirror _currentMember; | 48 MemberMirror _currentMember; |
| 49 | 49 |
| 50 /// Resolves reference links in doc comments. | 50 /// Resolves reference links in doc comments. |
| 51 markdown.Resolver linkResolver; | 51 markdown.Resolver linkResolver; |
| 52 | 52 |
| 53 /// Index of all the qualified names documented. | 53 /// Index of all indexable items. This also ensures that no class is |
| 54 Set<String> qualifiedNameIndex = new Set<String>(); | 54 /// created more than once. |
| 55 Map<String, Indexable> entityMap = new Map<String, Indexable>(); |
| 56 |
| 57 /// This is set from the command line arguments flag --include-private |
| 58 bool _includePrivate = false; |
| 55 | 59 |
| 56 /** | 60 /** |
| 57 * Docgen constructor initializes the link resolver for markdown parsing. | 61 * Docgen constructor initializes the link resolver for markdown parsing. |
| 58 * Also initializes the command line arguments. | 62 * Also initializes the command line arguments. |
| 59 * | 63 * |
| 60 * [packageRoot] is the packages directory of the directory being analyzed. | 64 * [packageRoot] is the packages directory of the directory being analyzed. |
| 61 * If [includeSdk] is `true`, then any SDK libraries explicitly imported will | 65 * If [includeSdk] is `true`, then any SDK libraries explicitly imported will |
| 62 * also be documented. | 66 * also be documented. |
| 63 * If [parseSdk] is `true`, then all Dart SDK libraries will be documented. | 67 * If [parseSdk] is `true`, then all Dart SDK libraries will be documented. |
| 64 * This option is useful when only the SDK libraries are needed. | 68 * This option is useful when only the SDK libraries are needed. |
| 65 * | 69 * |
| 66 * Returns `true` if docgen sucessfuly completes. | 70 * Returns `true` if docgen sucessfuly completes. |
| 67 */ | 71 */ |
| 68 Future<bool> docgen(List<String> files, {String packageRoot, | 72 Future<bool> docgen(List<String> files, {String packageRoot, |
| 69 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, | 73 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, |
| 70 bool parseSdk: false, bool append: false}) { | 74 bool parseSdk: false, bool append: false}) { |
| 75 _includePrivate = includePrivate; |
| 71 if (!append) { | 76 if (!append) { |
| 72 var dir = new Directory('docs'); | 77 var dir = new Directory('docs'); |
| 73 if (dir.existsSync()) dir.deleteSync(recursive: true); | 78 if (dir.existsSync()) dir.deleteSync(recursive: true); |
| 74 } | 79 } |
| 75 | 80 |
| 76 if (packageRoot == null && !parseSdk) { | 81 if (packageRoot == null && !parseSdk) { |
| 77 var type = FileSystemEntity.typeSync(files.first); | 82 var type = FileSystemEntity.typeSync(files.first); |
| 78 if (type == FileSystemEntityType.DIRECTORY) { | 83 if (type == FileSystemEntityType.DIRECTORY) { |
| 79 packageRoot = _findPackageRoot(files.first); | 84 packageRoot = _findPackageRoot(files.first); |
| 80 } else if (type == FileSystemEntityType.FILE) { | 85 } else if (type == FileSystemEntityType.FILE) { |
| 81 logger.warning('WARNING: No package root defined. If Docgen fails, try ' | 86 logger.warning('WARNING: No package root defined. If Docgen fails, try ' |
| 82 'again by setting the --package-root option.'); | 87 'again by setting the --package-root option.'); |
| 83 } | 88 } |
| 84 } | 89 } |
| 85 logger.info('Package Root: ${packageRoot}'); | 90 logger.info('Package Root: ${packageRoot}'); |
| 86 | 91 |
| 87 linkResolver = (name) => | 92 linkResolver = (name) => |
| 88 fixReference(name, _currentLibrary, _currentClass, _currentMember); | 93 fixReference(name, _currentLibrary, _currentClass, _currentMember); |
| 89 | 94 |
| 90 return getMirrorSystem(files, packageRoot: packageRoot, parseSdk: parseSdk) | 95 return getMirrorSystem(files, packageRoot: packageRoot, parseSdk: parseSdk) |
| 91 .then((MirrorSystem mirrorSystem) { | 96 .then((MirrorSystem mirrorSystem) { |
| 92 if (mirrorSystem.libraries.isEmpty) { | 97 if (mirrorSystem.libraries.isEmpty) { |
| 93 throw new StateError('No library mirrors were created.'); | 98 throw new StateError('No library mirrors were created.'); |
| 94 } | 99 } |
| 95 _documentLibraries(mirrorSystem.libraries.values, | 100 _documentLibraries(mirrorSystem.libraries.values, |
| 96 includeSdk: includeSdk, includePrivate: includePrivate, | 101 includeSdk: includeSdk, outputToYaml: outputToYaml, append: append); |
| 97 outputToYaml: outputToYaml, append: append); | |
| 98 | 102 |
| 99 return true; | 103 return true; |
| 100 }); | 104 }); |
| 101 } | 105 } |
| 102 | 106 |
| 103 List<String> _listLibraries(List<String> args) { | 107 List<String> _listLibraries(List<String> args) { |
| 104 if (args.length != 1) throw new UnsupportedError(USAGE); | 108 if (args.length != 1) throw new UnsupportedError(USAGE); |
| 105 var libraries = new List<String>(); | 109 var libraries = new List<String>(); |
| 106 var type = FileSystemEntity.typeSync(args[0]); | 110 var type = FileSystemEntity.typeSync(args[0]); |
| 107 | 111 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 // Currently, a string is thrown when it fails to create a mirror | 193 // Currently, a string is thrown when it fails to create a mirror |
| 190 // system, and it is not possible to use the stack trace. BUG(#11622) | 194 // system, and it is not possible to use the stack trace. BUG(#11622) |
| 191 // To avoid printing the stack trace. | 195 // To avoid printing the stack trace. |
| 192 exit(1); | 196 exit(1); |
| 193 }); | 197 }); |
| 194 } | 198 } |
| 195 | 199 |
| 196 /** | 200 /** |
| 197 * Creates documentation for filtered libraries. | 201 * Creates documentation for filtered libraries. |
| 198 */ | 202 */ |
| 199 void _documentLibraries(List<LibraryMirror> libraries, | 203 void _documentLibraries(List<LibraryMirror> libs, |
| 200 {bool includeSdk: false, bool includePrivate: false, | 204 {bool includeSdk: false, bool outputToYaml: true, bool append: false}) { |
| 201 bool outputToYaml: true, bool append: false}) { | 205 libs.forEach((lib) { |
| 202 libraries.forEach((lib) { | |
| 203 // Files belonging to the SDK have a uri that begins with 'dart:'. | 206 // Files belonging to the SDK have a uri that begins with 'dart:'. |
| 204 if (includeSdk || !lib.uri.toString().startsWith('dart:')) { | 207 if (includeSdk || !lib.uri.toString().startsWith('dart:')) { |
| 205 var library = generateLibrary(lib, includePrivate: includePrivate); | 208 var library = generateLibrary(lib); |
| 206 _writeLibraryToFile(library, outputToYaml); | 209 entityMap[library.qualifiedName] = library; |
| 207 } | 210 } |
| 208 }); | 211 }); |
| 209 // Outputs a text file with a list of files available after creating all | 212 // After everything is created, do a pass through all classes to make sure no |
| 210 // the libraries. This will help the viewer know what files are available | 213 // intermediate classes created by mixins are included. |
| 214 entityMap.values.where((e) => e is Class).forEach((c) => c.makeValid()); |
| 215 // Everything is a subclass of Object, therefore empty the list to avoid a |
| 216 // giant list of subclasses to be printed out. |
| 217 entityMap['dart.core.Object'].subclasses.clear(); |
| 218 |
| 219 var filteredEntities = entityMap.values.where((e) => _filterPrivate(e)); |
| 220 // Output libraries and classes to file after all information is generated. |
| 221 filteredEntities.where((e) => e is Class || e is Library).forEach((output) { |
| 222 _writeIndexableToFile(output, outputToYaml); |
| 223 }); |
| 224 // Outputs a text file with a list of libraries available after creating all |
| 225 // the libraries. This will help the viewer know what libraries are available |
| 211 // to read in. | 226 // to read in. |
| 212 _writeToFile(listDir('docs').join('\n').replaceAll('docs/', ''), | 227 _writeToFile(filteredEntities.where((e) => e is Library) |
| 213 'library_list.txt', append: append); | 228 .map((e) => e.qualifiedName).join('\n'), 'library_list.txt', |
| 229 append: append); |
| 214 // Outputs all the qualified names documented. This will help generate search | 230 // Outputs all the qualified names documented. This will help generate search |
| 215 // results. | 231 // results. |
| 216 _writeToFile(qualifiedNameIndex.join('\n'), 'index.txt', append: append); | 232 _writeToFile(filteredEntities.map((e) => e.qualifiedName).join('\n'), |
| 233 'index.txt', append: append); |
| 217 } | 234 } |
| 218 | 235 |
| 219 Library generateLibrary(dart2js.Dart2JsLibraryMirror library, | 236 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { |
| 220 {bool includePrivate: false}) { | |
| 221 _currentLibrary = library; | 237 _currentLibrary = library; |
| 222 var result = new Library(library.qualifiedName, _getComment(library), | 238 var result = new Library(library.qualifiedName, _commentToHtml(library), |
| 223 _getVariables(library.variables, includePrivate), | 239 _variables(library.variables), |
| 224 _getMethods(library.functions, includePrivate), | 240 _methods(library.functions), |
| 225 _getClasses(library.classes, includePrivate)); | 241 _classes(library.classes), _isPrivate(library)); |
| 226 logger.fine('Generated library for ${result.name}'); | 242 logger.fine('Generated library for ${result.name}'); |
| 227 return result; | 243 return result; |
| 228 } | 244 } |
| 229 | 245 |
| 230 void _writeLibraryToFile(Library result, bool outputToYaml) { | 246 void _writeIndexableToFile(Indexable result, bool outputToYaml) { |
| 231 if (outputToYaml) { | 247 if (outputToYaml) { |
| 232 _writeToFile(getYamlString(result.toMap()), '${result.name}.yaml'); | 248 _writeToFile(getYamlString(result.toMap()), '${result.qualifiedName}.yaml'); |
| 233 } else { | 249 } else { |
| 234 _writeToFile(stringify(result.toMap()), '${result.name}.json'); | 250 _writeToFile(stringify(result.toMap()), '${result.qualifiedName}.json'); |
| 235 } | 251 } |
| 252 } |
| 236 | 253 |
| 254 /** |
| 255 * Returns true if a library name starts with an underscore, and false |
| 256 * otherwise. |
| 257 * |
| 258 * An example that starts with _ is _js_helper. |
| 259 * An example that contains ._ is dart._collection.dev |
| 260 */ |
| 261 // This is because LibraryMirror.isPrivate returns `false` all the time. |
| 262 bool _isLibraryPrivate(LibraryMirror mirror) { |
| 263 if (mirror.simpleName.startsWith('_') || mirror.simpleName.contains('._')) { |
| 264 return true; |
| 265 } |
| 266 return false; |
| 267 } |
| 268 |
| 269 /** |
| 270 * A declaration is private if itself is private, or the owner is private. |
| 271 */ |
| 272 bool _isPrivate(DeclarationMirror mirror) { |
| 273 if (mirror is LibraryMirror) { |
| 274 return _isLibraryPrivate(mirror); |
| 275 } else if (mirror.owner is LibraryMirror) { |
| 276 return (mirror.isPrivate || _isLibraryPrivate(mirror.owner)); |
| 277 } else { |
| 278 return (mirror.isPrivate || _isPrivate(mirror.owner)); |
| 279 } |
| 280 } |
| 281 |
| 282 bool _filterPrivate(Indexable item) { |
| 283 return _includePrivate || !item.isPrivate; |
| 237 } | 284 } |
| 238 | 285 |
| 239 /** | 286 /** |
| 240 * Returns a list of meta annotations assocated with a mirror. | 287 * Returns a list of meta annotations assocated with a mirror. |
| 241 */ | 288 */ |
| 242 List<String> _getAnnotations(DeclarationMirror mirror) { | 289 List<String> _annotations(DeclarationMirror mirror) { |
| 243 var annotations = mirror.metadata.where((e) => | 290 var annotations = mirror.metadata.where((e) => |
| 244 e is dart2js.Dart2JsConstructedConstantMirror); | 291 e is dart2js.Dart2JsConstructedConstantMirror); |
| 245 return annotations.map((e) => e.type.qualifiedName).toList(); | 292 return annotations.map((e) => e.type.qualifiedName).toList(); |
| 246 } | 293 } |
| 247 | 294 |
| 248 /** | 295 /** |
| 249 * Returns any documentation comments associated with a mirror with | 296 * Returns any documentation comments associated with a mirror with |
| 250 * simple markdown converted to html. | 297 * simple markdown converted to html. |
| 251 */ | 298 */ |
| 252 String _getComment(DeclarationMirror mirror) { | 299 String _commentToHtml(DeclarationMirror mirror) { |
| 253 String commentText; | 300 String commentText; |
| 254 mirror.metadata.forEach((metadata) { | 301 mirror.metadata.forEach((metadata) { |
| 255 if (metadata is CommentInstanceMirror) { | 302 if (metadata is CommentInstanceMirror) { |
| 256 CommentInstanceMirror comment = metadata; | 303 CommentInstanceMirror comment = metadata; |
| 257 if (comment.isDocComment) { | 304 if (comment.isDocComment) { |
| 258 if (commentText == null) { | 305 if (commentText == null) { |
| 259 commentText = comment.trimmedText; | 306 commentText = comment.trimmedText; |
| 260 } else { | 307 } else { |
| 261 commentText = '$commentText ${comment.trimmedText}'; | 308 commentText = '$commentText ${comment.trimmedText}'; |
| 262 } | 309 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 282 var classScope = currentClass == null ? | 329 var classScope = currentClass == null ? |
| 283 null : currentClass.lookupInScope(name); | 330 null : currentClass.lookupInScope(name); |
| 284 reference = classScope != null ? classScope.qualifiedName : name; | 331 reference = classScope != null ? classScope.qualifiedName : name; |
| 285 } | 332 } |
| 286 return new markdown.Element.text('a', reference); | 333 return new markdown.Element.text('a', reference); |
| 287 } | 334 } |
| 288 | 335 |
| 289 /** | 336 /** |
| 290 * Returns a map of [Variable] objects constructed from [mirrorMap]. | 337 * Returns a map of [Variable] objects constructed from [mirrorMap]. |
| 291 */ | 338 */ |
| 292 Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap, | 339 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { |
| 293 bool includePrivate) { | |
| 294 var data = {}; | 340 var data = {}; |
| 295 // TODO(janicejl): When map to map feature is created, replace the below with | 341 // TODO(janicejl): When map to map feature is created, replace the below with |
| 296 // a filter. Issue(#9590). | 342 // a filter. Issue(#9590). |
| 297 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | 343 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { |
| 298 if (includePrivate || !mirror.isPrivate) { | 344 _currentMember = mirror; |
| 299 _currentMember = mirror; | 345 if (_includePrivate || !_isPrivate(mirror)) { |
| 300 data[mirrorName] = new Variable(mirrorName, mirror.isFinal, | 346 entityMap[mirror.qualifiedName] = new Variable(mirrorName, mirror.isFinal, |
| 301 mirror.isStatic, mirror.isConst, _type(mirror.type), | 347 mirror.isStatic, mirror.isConst, _type(mirror.type), |
| 302 _getComment(mirror), _getAnnotations(mirror), mirror.qualifiedName); | 348 _commentToHtml(mirror), _annotations(mirror), mirror.qualifiedName, |
| 349 _isPrivate(mirror), mirror.owner.qualifiedName); |
| 350 data[mirrorName] = entityMap[mirror.qualifiedName]; |
| 303 } | 351 } |
| 304 }); | 352 }); |
| 305 return data; | 353 return data; |
| 306 } | 354 } |
| 307 | 355 |
| 308 /** | 356 /** |
| 309 * Returns a map of [Method] objects constructed from [mirrorMap]. | 357 * Returns a map of [Method] objects constructed from [mirrorMap]. |
| 310 */ | 358 */ |
| 311 Map<String, Map<String, Method>> _getMethods | 359 MethodGroup _methods(Map<String, MethodMirror> mirrorMap) { |
| 312 (Map<String, MethodMirror> mirrorMap, bool includePrivate) { | 360 var group = new MethodGroup(); |
| 313 | |
| 314 var setters = {}; | |
| 315 var getters = {}; | |
| 316 var constructors = {}; | |
| 317 var operators = {}; | |
| 318 var methods = {}; | |
| 319 | |
| 320 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { | 361 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { |
| 321 if (includePrivate || !mirror.isPrivate) { | 362 if (_includePrivate || !_isPrivate(mirror)) { |
| 322 var method = new Method(mirrorName, mirror.isStatic, mirror.isAbstract, | 363 group.addMethod(mirror); |
| 323 mirror.isConstConstructor, _type(mirror.returnType), | |
| 324 _getComment(mirror), _getParameters(mirror.parameters), | |
| 325 _getAnnotations(mirror), mirror.qualifiedName); | |
| 326 _currentMember = mirror; | |
| 327 if (mirror.isSetter) { | |
| 328 setters[mirrorName] = method; | |
| 329 } else if (mirror.isGetter) { | |
| 330 getters[mirrorName] = method; | |
| 331 } else if (mirror.isConstructor) { | |
| 332 constructors[mirrorName] = method; | |
| 333 } else if (mirror.isOperator) { | |
| 334 operators[mirrorName] = method; | |
| 335 } else if (mirror.isRegularMethod) { | |
| 336 methods[mirrorName] = method; | |
| 337 } else { | |
| 338 throw new ArgumentError('$mirrorName - no method type match'); | |
| 339 } | |
| 340 } | 364 } |
| 341 }); | 365 }); |
| 342 return { | 366 return group; |
| 343 'setters': setters, | |
| 344 'getters': getters, | |
| 345 'constructors': constructors, | |
| 346 'operators': operators, | |
| 347 'methods': methods | |
| 348 }; | |
| 349 } | 367 } |
| 350 | 368 |
| 351 /** | 369 /** |
| 370 * Returns the [Class] for the given [mirror] has already been created, and if |
| 371 * it does not exist, creates it. |
| 372 */ |
| 373 Class _class(ClassMirror mirror) { |
| 374 var clazz = entityMap[mirror.qualifiedName]; |
| 375 if (clazz == null) { |
| 376 var superclass = mirror.superclass != null ? |
| 377 _class(mirror.superclass) : null; |
| 378 var interfaces = |
| 379 mirror.superinterfaces.map((interface) => _class(interface)); |
| 380 clazz = new Class(mirror.simpleName, superclass, _commentToHtml(mirror), |
| 381 interfaces.toList(), _variables(mirror.variables), |
| 382 _methods(mirror.methods), _annotations(mirror), _generics(mirror), |
| 383 mirror.qualifiedName, _isPrivate(mirror), mirror.owner.qualifiedName); |
| 384 entityMap[mirror.qualifiedName] = clazz; |
| 385 } |
| 386 return clazz; |
| 387 } |
| 388 |
| 389 /** |
| 352 * Returns a map of [Class] objects constructed from [mirrorMap]. | 390 * Returns a map of [Class] objects constructed from [mirrorMap]. |
| 353 */ | 391 */ |
| 354 Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap, | 392 ClassGroup _classes(Map<String, ClassMirror> mirrorMap) { |
| 355 bool includePrivate) { | 393 var group = new ClassGroup(); |
| 356 | |
| 357 var abstractClasses = {}; | |
| 358 var classes = {}; | |
| 359 var typedefs = {}; | |
| 360 var errors = {}; | |
| 361 | |
| 362 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { | 394 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { |
| 363 if (includePrivate || !mirror.isPrivate) { | 395 group.addClass(mirror); |
| 364 var superclass = (mirror.superclass != null) ? | |
| 365 mirror.superclass.qualifiedName : ''; | |
| 366 var interfaces = | |
| 367 mirror.superinterfaces.map((interface) => interface.qualifiedName); | |
| 368 var clazz = new Class(mirrorName, superclass, _getComment(mirror), | |
| 369 interfaces.toList(), _getVariables(mirror.variables, includePrivate), | |
| 370 _getMethods(mirror.methods, includePrivate), | |
| 371 _getAnnotations(mirror), _getGenerics(mirror), mirror.qualifiedName); | |
| 372 _currentClass = mirror; | |
| 373 | |
| 374 if (isError(mirror.qualifiedName)) { | |
| 375 errors[mirrorName] = clazz; | |
| 376 } else if (mirror.isTypedef) { | |
| 377 typedefs[mirrorName] = new Typedef(mirrorName, | |
| 378 mirror.value.returnType.qualifiedName, _getComment(mirror), | |
| 379 _getGenerics(mirror), _getParameters(mirror.value.parameters), | |
| 380 _getAnnotations(mirror), mirror.qualifiedName); | |
| 381 } else if (mirror.isAbstract) { | |
| 382 abstractClasses[mirrorName] = clazz; | |
| 383 } else if (mirror.isClass) { | |
| 384 classes[mirrorName] = clazz; | |
| 385 } else { | |
| 386 throw new ArgumentError('$mirrorName - no class type match. '); | |
| 387 } | |
| 388 } | |
| 389 }); | 396 }); |
| 390 return { | 397 return group; |
| 391 'abstract': abstractClasses, | |
| 392 'class': classes, | |
| 393 'typedef': typedefs, | |
| 394 'error': errors | |
| 395 }; | |
| 396 } | 398 } |
| 397 | 399 |
| 398 /** | 400 /** |
| 399 * Returns a map of [Parameter] objects constructed from [mirrorList]. | 401 * Returns a map of [Parameter] objects constructed from [mirrorList]. |
| 400 */ | 402 */ |
| 401 Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) { | 403 Map<String, Parameter> _parameters(List<ParameterMirror> mirrorList) { |
| 402 var data = {}; | 404 var data = {}; |
| 403 mirrorList.forEach((ParameterMirror mirror) { | 405 mirrorList.forEach((ParameterMirror mirror) { |
| 404 _currentMember = mirror; | 406 _currentMember = mirror; |
| 405 data[mirror.simpleName] = new Parameter(mirror.simpleName, | 407 data[mirror.simpleName] = new Parameter(mirror.simpleName, |
| 406 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, | 408 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, |
| 407 _type(mirror.type), mirror.defaultValue, | 409 _type(mirror.type), mirror.defaultValue, |
| 408 _getAnnotations(mirror)); | 410 _annotations(mirror)); |
| 409 }); | 411 }); |
| 410 return data; | 412 return data; |
| 411 } | 413 } |
| 412 | 414 |
| 413 /** | 415 /** |
| 414 * Returns a map of [Generic] objects constructed from the class mirror. | 416 * Returns a map of [Generic] objects constructed from the class mirror. |
| 415 */ | 417 */ |
| 416 Map<String, Generic> _getGenerics(ClassMirror mirror) { | 418 Map<String, Generic> _generics(ClassMirror mirror) { |
| 417 return new Map.fromIterable(mirror.typeVariables, | 419 return new Map.fromIterable(mirror.typeVariables, |
| 418 key: (e) => e.toString(), | 420 key: (e) => e.toString(), |
| 419 value: (e) => new Generic(e.toString(), e.upperBound.qualifiedName)); | 421 value: (e) => new Generic(e.toString(), e.upperBound.qualifiedName)); |
| 420 } | 422 } |
| 421 | 423 |
| 422 /** | 424 /** |
| 423 * Returns a single [Type] object constructed from the Method.returnType | 425 * Returns a single [Type] object constructed from the Method.returnType |
| 424 * Type mirror. | 426 * Type mirror. |
| 425 */ | 427 */ |
| 426 Type _type(TypeMirror mirror) { | 428 Type _type(TypeMirror mirror) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 return qualifiedName.toLowerCase().contains('error') || | 477 return qualifiedName.toLowerCase().contains('error') || |
| 476 qualifiedName.toLowerCase().contains('exception'); | 478 qualifiedName.toLowerCase().contains('exception'); |
| 477 } | 479 } |
| 478 | 480 |
| 479 /** | 481 /** |
| 480 * A class representing all programming constructs, like library or class. | 482 * A class representing all programming constructs, like library or class. |
| 481 */ | 483 */ |
| 482 class Indexable { | 484 class Indexable { |
| 483 String name; | 485 String name; |
| 484 String qualifiedName; | 486 String qualifiedName; |
| 487 bool isPrivate; |
| 485 | 488 |
| 486 /// Documentation comment with converted markdown. | 489 /// Documentation comment with converted markdown. |
| 487 String comment; | 490 String comment; |
| 488 | 491 |
| 489 Indexable(this.name, this.comment, String qualifiedName) { | 492 /// Qualified Name of the owner of this Indexable Item. |
| 490 this.qualifiedName = qualifiedName; | 493 /// For Library, owner will be ""; |
| 491 qualifiedNameIndex.add(qualifiedName); | 494 String owner; |
| 492 } | 495 |
| 496 Indexable(this.name, this.comment, this.qualifiedName, this.isPrivate, |
| 497 this.owner); |
| 493 } | 498 } |
| 494 | 499 |
| 495 /** | 500 /** |
| 496 * A class containing contents of a Dart library. | 501 * A class containing contents of a Dart library. |
| 497 */ | 502 */ |
| 498 class Library extends Indexable { | 503 class Library extends Indexable { |
| 499 | 504 |
| 500 /// Top-level variables in the library. | 505 /// Top-level variables in the library. |
| 501 Map<String, Variable> variables; | 506 Map<String, Variable> variables; |
| 502 | 507 |
| 503 /// Top-level functions in the library. | 508 /// Top-level functions in the library. |
| 504 Map<String, Map<String, Method>> functions; | 509 MethodGroup functions; |
| 505 | 510 |
| 506 /// Classes defined within the library | 511 /// Classes defined within the library |
| 507 Map<String, Class> classes; | 512 ClassGroup classes; |
| 508 | 513 |
| 509 Library(String name, String comment, this.variables, | 514 Library(String name, String comment, this.variables, |
| 510 this.functions, this.classes) : super(name, comment, name) {} | 515 this.functions, this.classes, bool isPrivate) : super(name, comment, |
| 516 name, isPrivate, "") {} |
| 511 | 517 |
| 512 /// Generates a map describing the [Library] object. | 518 /// Generates a map describing the [Library] object. |
| 513 Map toMap() => { | 519 Map toMap() => { |
| 514 'name': name, | 520 'name': name, |
| 515 'qualifiedname': qualifiedName, | 521 'qualifiedname': qualifiedName, |
| 516 'comment': comment, | 522 'comment': comment, |
| 517 'variables': recurseMap(variables), | 523 'variables': recurseMap(variables), |
| 518 'functions': recurseMap(functions), | 524 'functions': functions.toMap(), |
| 519 'classes': recurseMap(classes) | 525 'classes': classes.toMap() |
| 520 }; | 526 }; |
| 521 } | 527 } |
| 522 | 528 |
| 523 /** | 529 /** |
| 524 * A class containing contents of a Dart class. | 530 * A class containing contents of a Dart class. |
| 525 */ | 531 */ |
| 526 class Class extends Indexable { | 532 class Class extends Indexable { |
| 527 | 533 |
| 528 /// List of the names of interfaces that this class implements. | 534 /// List of the names of interfaces that this class implements. |
| 529 List<String> interfaces; | 535 List<Class> interfaces = []; |
| 536 |
| 537 /// Names of classes that extends or implements this class. |
| 538 Set<String> subclasses = new Set<String>(); |
| 530 | 539 |
| 531 /// Top-level variables in the class. | 540 /// Top-level variables in the class. |
| 532 Map<String, Variable> variables; | 541 Map<String, Variable> variables; |
| 542 |
| 543 /// Inherited variables in the class. |
| 544 Map<String, Variable> inheritedVariables = {}; |
| 533 | 545 |
| 534 /// Methods in the class. | 546 /// Methods in the class. |
| 535 Map<String, Map<String, Method>> methods; | 547 MethodGroup methods; |
| 548 |
| 549 /// Inherited methods in the class. |
| 550 MethodGroup inheritedMethods = new MethodGroup(); |
| 536 | 551 |
| 537 /// Generic infomation about the class. | 552 /// Generic infomation about the class. |
| 538 Map<String, Generic> generics; | 553 Map<String, Generic> generics; |
| 539 | 554 |
| 540 String superclass; | 555 Class superclass; |
| 541 | 556 |
| 542 /// List of the meta annotations on the class. | 557 /// List of the meta annotations on the class. |
| 543 List<String> annotations; | 558 List<String> annotations; |
| 544 | 559 |
| 545 Class(String name, this.superclass, String comment, this.interfaces, | 560 Class(String name, this.superclass, String comment, this.interfaces, |
| 546 this.variables, this.methods, this.annotations, this.generics, | 561 this.variables, this.methods, this.annotations, this.generics, |
| 547 String qualifiedName) : super(name, comment, qualifiedName) {} | 562 String qualifiedName, bool isPrivate, String owner) : super(name, comment, |
| 563 qualifiedName, isPrivate, owner) {} |
| 548 | 564 |
| 565 /** |
| 566 * Returns a list of all the parent classes. |
| 567 */ |
| 568 List<Class> parent() { |
| 569 var parent = superclass == null ? [] : [superclass]; |
| 570 parent.addAll(interfaces); |
| 571 return parent; |
| 572 } |
| 573 |
| 574 /** |
| 575 * Add all inherited variables and methods from the provided superclass. |
| 576 * If [_includePrivate] is true, it also adds the variables and methods from |
| 577 * the superclass. |
| 578 */ |
| 579 void addInherited(Class superclass) { |
| 580 inheritedVariables.addAll(superclass.inheritedVariables); |
| 581 if (_filterPrivate(superclass)) { |
| 582 inheritedVariables.addAll(superclass.variables); |
| 583 } |
| 584 inheritedMethods.addInherited(superclass); |
| 585 } |
| 586 |
| 587 /** |
| 588 * Add the subclass to the class. |
| 589 * |
| 590 * If [this] is private, it will add the subclass to the list of subclasses in |
| 591 * the superclasses. |
| 592 */ |
| 593 void addSubclass(Class subclass) { |
| 594 if (!_includePrivate && isPrivate) { |
| 595 if (superclass != null) superclass.addSubclass(subclass); |
| 596 interfaces.forEach((interface) { |
| 597 interface.addSubclass(subclass); |
| 598 }); |
| 599 } else { |
| 600 subclasses.add(subclass.qualifiedName); |
| 601 } |
| 602 } |
| 603 |
| 604 /** |
| 605 * Check that the class exists in the owner library. |
| 606 * |
| 607 * If it does not exist in the owner library, it is a mixin applciation and |
| 608 * should be removed. |
| 609 */ |
| 610 void makeValid() { |
| 611 var library = entityMap[owner]; |
| 612 if (!library.classes.containsKey(name)) { |
| 613 this.isPrivate = true; |
| 614 // Since we are now making the mixin a private class, make all elements |
| 615 // with the mixin as an owner private too. |
| 616 entityMap.values.where((e) => e.owner == qualifiedName) |
| 617 .forEach((element) => element.isPrivate = true); |
| 618 // Move the subclass up to the next public superclass |
| 619 subclasses.forEach((subclass) => addSubclass(entityMap[subclass])); |
| 620 } |
| 621 } |
| 622 |
| 549 /// Generates a map describing the [Class] object. | 623 /// Generates a map describing the [Class] object. |
| 550 Map toMap() => { | 624 Map toMap() => { |
| 551 'name': name, | 625 'name': name, |
| 552 'qualifiedname': qualifiedName, | 626 'qualifiedname': qualifiedName, |
| 553 'comment': comment, | 627 'comment': comment, |
| 554 'superclass': superclass, | 628 'superclass': superclass == null ? "" : (_filterPrivate(superclass)) ? |
| 555 'implements': new List.from(interfaces), | 629 superclass.qualifiedName : "", |
| 556 'variables': recurseMap(variables), | 630 'implements': new List.from(interfaces.where((e) => _filterPrivate(e)) |
| 557 'methods': recurseMap(methods), | 631 .map((e) => e.qualifiedName)), |
| 558 'annotations': new List.from(annotations), | 632 'subclass': new List.from(subclasses), |
| 559 'generics': recurseMap(generics) | 633 'variables': recurseMap(variables), |
| 560 }; | 634 'inheritedvariables': recurseMap(inheritedVariables), |
| 635 'methods': methods.toMap(), |
| 636 'inheritedmethods': inheritedMethods.toMap(), |
| 637 'annotations': new List.from(annotations), |
| 638 'generics': recurseMap(generics) |
| 639 }; |
| 640 } |
| 641 |
| 642 /** |
| 643 * A container to categorize classes into the following groups: abstract |
| 644 * classes, regular classes, typedefs, and errors. |
| 645 */ |
| 646 class ClassGroup { |
| 647 Map<String, Class> abstractClasses = {}; |
| 648 Map<String, Class> regularClasses = {}; |
| 649 Map<String, Typedef> typedefs = {}; |
| 650 Map<String, Class> errors = {}; |
| 651 |
| 652 void addClass(ClassMirror mirror) { |
| 653 _currentClass = mirror; |
| 654 var clazz = _class(mirror); |
| 655 |
| 656 // Adding inherited parent variables and methods. |
| 657 clazz.parent().forEach((parent) { |
| 658 if (_filterPrivate(clazz)) { |
| 659 parent.addSubclass(clazz); |
| 660 } |
| 661 clazz.addInherited(parent); |
| 662 }); |
| 663 |
| 664 if (isError(mirror.qualifiedName)) { |
| 665 errors[mirror.simpleName] = clazz; |
| 666 } else if (mirror.isTypedef) { |
| 667 if (_includePrivate || !mirror.isPrivate) { |
| 668 entityMap[mirror.qualifiedName] = new Typedef(mirror.simpleName, |
| 669 mirror.value.returnType.qualifiedName, _commentToHtml(mirror), |
| 670 _generics(mirror), _parameters(mirror.value.parameters), |
| 671 _annotations(mirror), mirror.qualifiedName, _isPrivate(mirror), |
| 672 mirror.owner.qualifiedName); |
| 673 typedefs[mirror.simpleName] = entityMap[mirror.qualifiedName]; |
| 674 } |
| 675 } else if (mirror.isAbstract) { |
| 676 abstractClasses[mirror.simpleName] = clazz; |
| 677 } else if (mirror.isClass) { |
| 678 regularClasses[mirror.simpleName] = clazz; |
| 679 } else { |
| 680 throw new ArgumentError('${mirror.simpleName} - no class type match. '); |
| 681 } |
| 682 } |
| 683 |
| 684 /** |
| 685 * Checks if the given name is a key for any of the Class Maps. |
| 686 */ |
| 687 bool containsKey(String name) { |
| 688 return abstractClasses.containsKey(name) || |
| 689 regularClasses.containsKey(name) || |
| 690 errors.containsKey(name); |
| 691 } |
| 692 |
| 693 Map toMap() => { |
| 694 'abstract': new List.from(abstractClasses.values |
| 695 .where((e) => _filterPrivate(e)).map((e) => e.qualifiedName)), |
| 696 'class': new List.from(regularClasses.values |
| 697 .where((e) => _filterPrivate(e)).map((e) => e.qualifiedName)), |
| 698 'typedef': recurseMap(typedefs), |
| 699 'error': new List.from(errors.values |
| 700 .where((e) => _filterPrivate(e)).map((e) => e.qualifiedName)) |
| 701 }; |
| 561 } | 702 } |
| 562 | 703 |
| 563 class Typedef extends Indexable { | 704 class Typedef extends Indexable { |
| 564 String returnType; | 705 String returnType; |
| 565 | 706 |
| 566 Map<String, Parameter> parameters; | 707 Map<String, Parameter> parameters; |
| 567 | 708 |
| 568 /// Generic information about the typedef. | 709 /// Generic information about the typedef. |
| 569 Map<String, Generic> generics; | 710 Map<String, Generic> generics; |
| 570 | 711 |
| 571 /// List of the meta annotations on the typedef. | 712 /// List of the meta annotations on the typedef. |
| 572 List<String> annotations; | 713 List<String> annotations; |
| 573 | 714 |
| 574 Typedef(String name, this.returnType, String comment, this.generics, | 715 Typedef(String name, this.returnType, String comment, this.generics, |
| 575 this.parameters, this.annotations, | 716 this.parameters, this.annotations, |
| 576 String qualifiedName) : super(name, comment, qualifiedName) {} | 717 String qualifiedName, bool isPrivate, String owner) : super(name, comment, |
| 718 qualifiedName, isPrivate, owner) {} |
| 577 | 719 |
| 578 Map toMap() => { | 720 Map toMap() => { |
| 579 'name': name, | 721 'name': name, |
| 580 'qualifiedname': qualifiedName, | 722 'qualifiedname': qualifiedName, |
| 581 'comment': comment, | 723 'comment': comment, |
| 582 'return': returnType, | 724 'return': returnType, |
| 583 'parameters': recurseMap(parameters), | 725 'parameters': recurseMap(parameters), |
| 584 'annotations': new List.from(annotations), | 726 'annotations': new List.from(annotations), |
| 585 'generics': recurseMap(generics) | 727 'generics': recurseMap(generics) |
| 586 }; | 728 }; |
| 587 } | 729 } |
| 588 | 730 |
| 589 /** | 731 /** |
| 590 * A class containing properties of a Dart variable. | 732 * A class containing properties of a Dart variable. |
| 591 */ | 733 */ |
| 592 class Variable extends Indexable { | 734 class Variable extends Indexable { |
| 593 | 735 |
| 594 bool isFinal; | 736 bool isFinal; |
| 595 bool isStatic; | 737 bool isStatic; |
| 596 bool isConst; | 738 bool isConst; |
| 597 Type type; | 739 Type type; |
| 598 | 740 |
| 599 /// List of the meta annotations on the variable. | 741 /// List of the meta annotations on the variable. |
| 600 List<String> annotations; | 742 List<String> annotations; |
| 601 | 743 |
| 602 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, | 744 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, |
| 603 String comment, this.annotations, String qualifiedName) : super(name, | 745 String comment, this.annotations, String qualifiedName, bool isPrivate, |
| 604 comment, qualifiedName); | 746 String owner) : super(name, comment, qualifiedName, isPrivate, owner); |
| 605 | 747 |
| 606 /// Generates a map describing the [Variable] object. | 748 /// Generates a map describing the [Variable] object. |
| 607 Map toMap() => { | 749 Map toMap() => { |
| 608 'name': name, | 750 'name': name, |
| 609 'qualifiedname': qualifiedName, | 751 'qualifiedname': qualifiedName, |
| 610 'comment': comment, | 752 'comment': comment, |
| 611 'final': isFinal.toString(), | 753 'final': isFinal.toString(), |
| 612 'static': isStatic.toString(), | 754 'static': isStatic.toString(), |
| 613 'constant': isConst.toString(), | 755 'constant': isConst.toString(), |
| 614 'type': new List.filled(1, type.toMap()), | 756 'type': new List.filled(1, type.toMap()), |
| 615 'annotations': new List.from(annotations) | 757 'annotations': new List.from(annotations) |
| 616 }; | 758 }; |
| 617 } | 759 } |
| 618 | 760 |
| 619 /** | 761 /** |
| 620 * A class containing properties of a Dart method. | 762 * A class containing properties of a Dart method. |
| 621 */ | 763 */ |
| 622 class Method extends Indexable { | 764 class Method extends Indexable { |
| 623 | 765 |
| 624 /// Parameters for this method. | 766 /// Parameters for this method. |
| 625 Map<String, Parameter> parameters; | 767 Map<String, Parameter> parameters; |
| 626 | 768 |
| 627 bool isStatic; | 769 bool isStatic; |
| 628 bool isAbstract; | 770 bool isAbstract; |
| 629 bool isConst; | 771 bool isConst; |
| 630 Type returnType; | 772 Type returnType; |
| 631 | 773 |
| 632 /// List of the meta annotations on the method. | 774 /// List of the meta annotations on the method. |
| 633 List<String> annotations; | 775 List<String> annotations; |
| 634 | 776 |
| 635 Method(String name, this.isStatic, this.isAbstract, this.isConst, | 777 Method(String name, this.isStatic, this.isAbstract, this.isConst, |
| 636 this.returnType, String comment, this.parameters, this.annotations, | 778 this.returnType, String comment, this.parameters, this.annotations, |
| 637 String qualifiedName) | 779 String qualifiedName, bool isPrivate, String owner) : super(name, comment, |
| 638 : super(name, comment, qualifiedName); | 780 qualifiedName, isPrivate, owner); |
| 639 | 781 |
| 640 /// Generates a map describing the [Method] object. | 782 /// Generates a map describing the [Method] object. |
| 641 Map toMap() => { | 783 Map toMap() => { |
| 642 'name': name, | 784 'name': name, |
| 643 'qualifiedname': qualifiedName, | 785 'qualifiedname': qualifiedName, |
| 644 'comment': comment, | 786 'comment': comment, |
| 645 'static': isStatic.toString(), | 787 'static': isStatic.toString(), |
| 646 'abstract': isAbstract.toString(), | 788 'abstract': isAbstract.toString(), |
| 647 'constant': isConst.toString(), | 789 'constant': isConst.toString(), |
| 648 'return': new List.filled(1, returnType.toMap()), | 790 'return': new List.filled(1, returnType.toMap()), |
| 649 'parameters': recurseMap(parameters), | 791 'parameters': recurseMap(parameters), |
| 650 'annotations': new List.from(annotations) | 792 'annotations': new List.from(annotations) |
| 651 }; | 793 }; |
| 652 } | 794 } |
| 653 | 795 |
| 654 /** | 796 /** |
| 797 * A container to categorize methods into the following groups: setters, |
| 798 * getters, constructors, operators, regular methods. |
| 799 */ |
| 800 class MethodGroup { |
| 801 Map<String, Method> setters = {}; |
| 802 Map<String, Method> getters = {}; |
| 803 Map<String, Method> constructors = {}; |
| 804 Map<String, Method> operators = {}; |
| 805 Map<String, Method> regularMethods = {}; |
| 806 |
| 807 void addMethod(MethodMirror mirror) { |
| 808 var method = new Method(mirror.simpleName, mirror.isStatic, |
| 809 mirror.isAbstract, mirror.isConstConstructor, _type(mirror.returnType), |
| 810 _commentToHtml(mirror), _parameters(mirror.parameters), |
| 811 _annotations(mirror), mirror.qualifiedName, _isPrivate(mirror), |
| 812 mirror.owner.qualifiedName); |
| 813 entityMap[mirror.qualifiedName] = method; |
| 814 _currentMember = mirror; |
| 815 if (mirror.isSetter) { |
| 816 setters[mirror.simpleName] = method; |
| 817 } else if (mirror.isGetter) { |
| 818 getters[mirror.simpleName] = method; |
| 819 } else if (mirror.isConstructor) { |
| 820 constructors[mirror.simpleName] = method; |
| 821 } else if (mirror.isOperator) { |
| 822 operators[mirror.simpleName] = method; |
| 823 } else if (mirror.isRegularMethod) { |
| 824 regularMethods[mirror.simpleName] = method; |
| 825 } else { |
| 826 throw new ArgumentError('${mirror.simpleName} - no method type match'); |
| 827 } |
| 828 } |
| 829 |
| 830 void addInherited(Class parent) { |
| 831 setters.addAll(parent.inheritedMethods.setters); |
| 832 getters.addAll(parent.inheritedMethods.getters); |
| 833 operators.addAll(parent.inheritedMethods.operators); |
| 834 regularMethods.addAll(parent.inheritedMethods.regularMethods); |
| 835 if (_filterPrivate(parent)) { |
| 836 setters.addAll(parent.methods.setters); |
| 837 getters.addAll(parent.methods.getters); |
| 838 operators.addAll(parent.methods.operators); |
| 839 regularMethods.addAll(parent.methods.regularMethods); |
| 840 } |
| 841 } |
| 842 |
| 843 Map toMap() => { |
| 844 'setters': recurseMap(setters), |
| 845 'getters': recurseMap(getters), |
| 846 'constructors': recurseMap(constructors), |
| 847 'operators': recurseMap(operators), |
| 848 'methods': recurseMap(regularMethods) |
| 849 }; |
| 850 } |
| 851 |
| 852 /** |
| 655 * A class containing properties of a Dart method/function parameter. | 853 * A class containing properties of a Dart method/function parameter. |
| 656 */ | 854 */ |
| 657 class Parameter { | 855 class Parameter { |
| 658 | 856 |
| 659 String name; | 857 String name; |
| 660 bool isOptional; | 858 bool isOptional; |
| 661 bool isNamed; | 859 bool isNamed; |
| 662 bool hasDefaultValue; | 860 bool hasDefaultValue; |
| 663 Type type; | 861 Type type; |
| 664 String defaultValue; | 862 String defaultValue; |
| 665 | 863 |
| 666 /// List of the meta annotations on the parameter. | 864 /// List of the meta annotations on the parameter. |
| 667 List<String> annotations; | 865 List<String> annotations; |
| 668 | 866 |
| 669 Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue, | 867 Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue, |
| 670 this.type, this.defaultValue, this.annotations); | 868 this.type, this.defaultValue, this.annotations); |
| 671 | 869 |
| 672 /// Generates a map describing the [Parameter] object. | 870 /// Generates a map describing the [Parameter] object. |
| 673 Map toMap() => { | 871 Map toMap() => { |
| 674 'name': name, | 872 'name': name, |
| 675 'optional': isOptional.toString(), | 873 'optional': isOptional.toString(), |
| 676 'named': isNamed.toString(), | 874 'named': isNamed.toString(), |
| 677 'default': hasDefaultValue.toString(), | 875 'default': hasDefaultValue.toString(), |
| 678 'type': new List.filled(1, type.toMap()), | 876 'type': new List.filled(1, type.toMap()), |
| 679 'value': defaultValue, | 877 'value': defaultValue, |
| 680 'annotations': new List.from(annotations) | 878 'annotations': new List.from(annotations) |
| 681 }; | 879 }; |
| 682 } | 880 } |
| 683 | 881 |
| 684 /** | 882 /** |
| 685 * A class containing properties of a Generic. | 883 * A class containing properties of a Generic. |
| 686 */ | 884 */ |
| 687 class Generic { | 885 class Generic { |
| 688 String name; | 886 String name; |
| 689 String type; | 887 String type; |
| 690 | 888 |
| 691 Generic(this.name, this.type); | 889 Generic(this.name, this.type); |
| 692 | 890 |
| 693 Map toMap() => { | 891 Map toMap() => { |
| 694 'name': name, | 892 'name': name, |
| 695 'type': type | 893 'type': type |
| 696 }; | 894 }; |
| 697 } | 895 } |
| 698 | 896 |
| 699 /** | 897 /** |
| 700 * Holds the name of a return type, and its generic type parameters. | 898 * Holds the name of a return type, and its generic type parameters. |
| 701 * | 899 * |
| 702 * Return types are of a form [outer]<[inner]>. | 900 * Return types are of a form [outer]<[inner]>. |
| 703 * If there is no [inner] part, [inner] will be an empty list. | 901 * If there is no [inner] part, [inner] will be an empty list. |
| 704 * | 902 * |
| 705 * For example: | 903 * For example: |
| 706 * int size() | 904 * int size() |
| (...skipping 19 matching lines...) Expand all Loading... |
| 726 * - "outer" : "dart.core.int" | 924 * - "outer" : "dart.core.int" |
| 727 * "inner" : | 925 * "inner" : |
| 728 */ | 926 */ |
| 729 class Type { | 927 class Type { |
| 730 String outer; | 928 String outer; |
| 731 List<Type> inner; | 929 List<Type> inner; |
| 732 | 930 |
| 733 Type(this.outer, this.inner); | 931 Type(this.outer, this.inner); |
| 734 | 932 |
| 735 Map toMap() => { | 933 Map toMap() => { |
| 736 'outer': outer, | 934 'outer': outer, |
| 737 'inner': new List.from(inner.map((e) => e.toMap())) | 935 'inner': new List.from(inner.map((e) => e.toMap())) |
| 738 }; | 936 }; |
| 739 } | 937 } |
| OLD | NEW |