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

Side by Side Diff: pkg/docgen/lib/docgen.dart

Issue 21096002: added inherited methods and variables (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/docgen/example/test.dart ('k') | pkg/docgen/test/single_library_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/docgen/example/test.dart ('k') | pkg/docgen/test/single_library_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698