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

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

Issue 139993008: Additional refactoring for docgen. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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/bin/docgen.dart ('k') | no next file » | 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 /// **docgen** is a tool for creating machine readable representations of Dart 5 /// **docgen** is a tool for creating machine readable representations of Dart
6 /// code metadata, including: classes, members, comments and annotations. 6 /// code metadata, including: classes, members, comments and annotations.
7 /// 7 ///
8 /// docgen is run on a `.dart` file or a directory containing `.dart` files. 8 /// docgen is run on a `.dart` file or a directory containing `.dart` files.
9 /// 9 ///
10 /// $ dart docgen.dart [OPTIONS] [FILE/DIR] 10 /// $ dart docgen.dart [OPTIONS] [FILE/DIR]
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 * [A Tour of the Dart Libraries](http://www.dartlang.org/docs/dart-up-and-runn ing/contents/ch03.html) 89 * [A Tour of the Dart Libraries](http://www.dartlang.org/docs/dart-up-and-runn ing/contents/ch03.html)
90 90
91 This API reference is automatically generated from the source code in the 91 This API reference is automatically generated from the source code in the
92 [Dart project](https://code.google.com/p/dart/). 92 [Dart project](https://code.google.com/p/dart/).
93 If you'd like to contribute to this documentation, see 93 If you'd like to contribute to this documentation, see
94 [Contributing](https://code.google.com/p/dart/wiki/Contributing) 94 [Contributing](https://code.google.com/p/dart/wiki/Contributing)
95 and 95 and
96 [Writing API Documentation](https://code.google.com/p/dart/wiki/WritingApiDocume ntation). 96 [Writing API Documentation](https://code.google.com/p/dart/wiki/WritingApiDocume ntation).
97 """; 97 """;
98 98
99 // TODO(efortuna): The use of this field is odd (this is based on how it was
100 // originally used. Try to cleanup.
101 /// Index of all indexable items. This also ensures that no class is
102 /// created more than once.
103 Map<String, Indexable> entityMap = new Map<String, Indexable>();
104
105 /// Docgen constructor initializes the link resolver for markdown parsing. 99 /// Docgen constructor initializes the link resolver for markdown parsing.
106 /// Also initializes the command line arguments. 100 /// Also initializes the command line arguments.
107 /// 101 ///
108 /// [packageRoot] is the packages directory of the directory being analyzed. 102 /// [packageRoot] is the packages directory of the directory being analyzed.
109 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will 103 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will
110 /// also be documented. 104 /// also be documented.
111 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. 105 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented.
112 /// This option is useful when only the SDK libraries are needed. 106 /// This option is useful when only the SDK libraries are needed.
107 /// If [serve] is `true`, then after generating the documents we fire up a
108 /// simple server to view the documentation.
113 /// 109 ///
114 /// Returned Future completes with true if document generation is successful. 110 /// Returned Future completes with true if document generation is successful.
115 Future<bool> docgen(List<String> files, {String packageRoot, 111 Future<bool> docgen(List<String> files, {String packageRoot,
116 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, 112 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false,
117 bool parseSdk: false, bool append: false, String introFileName: '', 113 bool parseSdk: false, bool append: false, String introFileName: '',
118 out: _DEFAULT_OUTPUT_DIRECTORY, List<String> excludeLibraries : const [], 114 out: _DEFAULT_OUTPUT_DIRECTORY, List<String> excludeLibraries : const [],
119 bool includeDependentPackages: false}) { 115 bool includeDependentPackages: false, bool serve: false,
120 return _Generator.generateDocumentation(files, packageRoot: packageRoot, 116 bool noDocs: false}) {
121 outputToYaml: outputToYaml, includePrivate: includePrivate, 117 var result;
122 includeSdk: includeSdk, parseSdk: parseSdk, append: append, 118 if (!noDocs) {
123 introFileName: introFileName, out: out, 119 _Viewer.ensureMovedViewerCode();
124 excludeLibraries: excludeLibraries, 120 result = _Generator.generateDocumentation(files, packageRoot: packageRoot,
125 includeDependentPackages: includeDependentPackages); 121 outputToYaml: outputToYaml, includePrivate: includePrivate,
122 includeSdk: includeSdk, parseSdk: parseSdk, append: append,
123 introFileName: introFileName, out: out,
124 excludeLibraries: excludeLibraries,
125 includeDependentPackages: includeDependentPackages);
126 _Viewer.addBackViewerCode();
127 if (serve) {
128 result.then((success) {
129 if (success) {
130 _Viewer._cloneAndServe();
131 }
132 });
133 }
134 } else if (serve) {
135 _Viewer._cloneAndServe();
136 }
137 return result;
126 } 138 }
127 139
128 /// Analyzes set of libraries by getting a mirror system and triggers the 140 /// Analyzes set of libraries by getting a mirror system and triggers the
129 /// documentation of the libraries. 141 /// documentation of the libraries.
130 Future<MirrorSystem> getMirrorSystem(List<Uri> libraries, 142 Future<MirrorSystem> getMirrorSystem(List<Uri> libraries,
131 {String packageRoot, bool parseSdk: false}) { 143 {String packageRoot, bool parseSdk: false}) {
132 if (libraries.isEmpty) throw new StateError('No Libraries.'); 144 if (libraries.isEmpty) throw new StateError('No Libraries.');
133 145
134 // Finds the root of SDK library based off the location of docgen. 146 // Finds the root of SDK library based off the location of docgen.
135 var root = _Generator._rootDirectory; 147 var root = _Generator._rootDirectory;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 LibraryMirror _getOwningLibraryFromMirror(DeclarationMirror mirror) { 194 LibraryMirror _getOwningLibraryFromMirror(DeclarationMirror mirror) {
183 if (mirror is LibraryMirror) return mirror; 195 if (mirror is LibraryMirror) return mirror;
184 if (mirror == null) return null; 196 if (mirror == null) return null;
185 return _getOwningLibraryFromMirror(mirror.owner); 197 return _getOwningLibraryFromMirror(mirror.owner);
186 } 198 }
187 } 199 }
188 200
189 /// Docgen representation of an item to be documented, that wraps around a 201 /// Docgen representation of an item to be documented, that wraps around a
190 /// dart2js mirror. 202 /// dart2js mirror.
191 abstract class MirrorBased { 203 abstract class MirrorBased {
204 /// The original dart2js mirror around which this object wraps.
192 DeclarationMirror get mirror; 205 DeclarationMirror get mirror;
193 206
194 /// Returns a list of meta annotations assocated with a mirror. 207 /// Returns a list of meta annotations assocated with a mirror.
195 List<Annotation> _createAnnotations(DeclarationMirror mirror, 208 List<Annotation> _createAnnotations(DeclarationMirror mirror,
196 Library owningLibrary) { 209 Library owningLibrary) {
197 var annotationMirrors = mirror.metadata.where((e) => 210 var annotationMirrors = mirror.metadata.where((e) =>
198 e is dart2js.Dart2JsConstructedConstantMirror); 211 e is dart2js.Dart2JsConstructedConstantMirror);
199 var annotations = []; 212 var annotations = [];
200 annotationMirrors.forEach((annotation) { 213 annotationMirrors.forEach((annotation) {
201 var docgenAnnotation = new Annotation(annotation, owningLibrary); 214 var docgenAnnotation = new Annotation(annotation, owningLibrary);
202 if (!_SKIPPED_ANNOTATIONS.contains( 215 if (!_SKIPPED_ANNOTATIONS.contains(
203 docgenAnnotation.mirror.qualifiedName)) { 216 docgenAnnotation.mirror.qualifiedName)) {
204 annotations.add(docgenAnnotation); 217 annotations.add(docgenAnnotation);
205 } 218 }
206 }); 219 });
207 return annotations; 220 return annotations;
208 } 221 }
209 } 222 }
210 223
224 /// Top level documentation traversal and generation object.
225 ///
226 /// Yes, everything in this class is used statically so this technically doesn't
227 /// need to be its own class, but it's grouped together for semantic separation
228 /// from the other classes and functionality in this library.
211 class _Generator { 229 class _Generator {
212 static var _outputDirectory; 230 /// The directory where the output docs are generated.
231 static String _outputDirectory;
213 232
214 /// This is set from the command line arguments flag --include-private 233 /// This is set from the command line arguments flag --include-private
215 static bool _includePrivate = false; 234 static bool _includePrivate = false;
216 235
217 /// Library names to explicitly exclude. 236 /// Library names to explicitly exclude.
218 /// 237 ///
219 /// Set from the command line option 238 /// Set from the command line option
220 /// --exclude-lib. 239 /// --exclude-lib.
221 static List<String> _excluded; 240 static List<String> _excluded;
222 241
242 /// Logger for printing out progress of documentation generation.
223 static Logger logger = new Logger('Docgen'); 243 static Logger logger = new Logger('Docgen');
224 244
225 /// Docgen constructor initializes the link resolver for markdown parsing. 245 /// Docgen constructor initializes the link resolver for markdown parsing.
226 /// Also initializes the command line arguments. 246 /// Also initializes the command line arguments.
227 /// 247 ///
228 /// [packageRoot] is the packages directory of the directory being analyzed. 248 /// [packageRoot] is the packages directory of the directory being analyzed.
229 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will 249 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will
230 /// also be documented. 250 /// also be documented.
231 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. 251 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented.
232 /// This option is useful when only the SDK libraries are needed. 252 /// This option is useful when only the SDK libraries are needed.
(...skipping 19 matching lines...) Expand all
252 if (includeSdk) { 272 if (includeSdk) {
253 allLibraries.addAll(_listSdk()); 273 allLibraries.addAll(_listSdk());
254 } 274 }
255 275
256 return getMirrorSystem(allLibraries, packageRoot: updatedPackageRoot, 276 return getMirrorSystem(allLibraries, packageRoot: updatedPackageRoot,
257 parseSdk: parseSdk) 277 parseSdk: parseSdk)
258 .then((MirrorSystem mirrorSystem) { 278 .then((MirrorSystem mirrorSystem) {
259 if (mirrorSystem.libraries.isEmpty) { 279 if (mirrorSystem.libraries.isEmpty) {
260 throw new StateError('No library mirrors were created.'); 280 throw new StateError('No library mirrors were created.');
261 } 281 }
262 Indexable.initializeTopLevelLibraries(mirrorSystem); 282 Indexable._initializeTopLevelLibraries(mirrorSystem);
263 283
264 var availableLibraries = mirrorSystem.libraries.values.where( 284 var availableLibraries = mirrorSystem.libraries.values.where(
265 (each) => each.uri.scheme == 'file'); 285 (each) => each.uri.scheme == 'file');
266 var availableLibrariesByPath = new Map.fromIterables( 286 var availableLibrariesByPath = new Map.fromIterables(
267 availableLibraries.map((each) => each.uri), 287 availableLibraries.map((each) => each.uri),
268 availableLibraries); 288 availableLibraries);
269 var librariesToDocument = requestedLibraries.map( 289 var librariesToDocument = requestedLibraries.map(
270 (each) => availableLibrariesByPath.putIfAbsent(each, 290 (each) => availableLibrariesByPath.putIfAbsent(each,
271 () => throw "Missing library $each")).toList(); 291 () => throw "Missing library $each")).toList();
272 librariesToDocument.addAll( 292 librariesToDocument.addAll(
(...skipping 25 matching lines...) Expand all
298 if (!subdir.existsSync()) { 318 if (!subdir.existsSync()) {
299 subdir.createSync(); 319 subdir.createSync();
300 } 320 }
301 } 321 }
302 } 322 }
303 File file = new File(path.join(_outputDirectory, filename)); 323 File file = new File(path.join(_outputDirectory, filename));
304 file.writeAsStringSync(text, 324 file.writeAsStringSync(text,
305 mode: append ? FileMode.APPEND : FileMode.WRITE); 325 mode: append ? FileMode.APPEND : FileMode.WRITE);
306 } 326 }
307 327
328 /// Resolve all the links in the introductory comments for a given library or
329 /// package as specified by [filename].
330 static String _readIntroductionFile(String fileName, bool includeSdk) {
331 var linkResolver = (name) => Indexable.globalFixReference(name);
332 var defaultText = includeSdk ? _DEFAULT_SDK_INTRODUCTION : '';
333 var introText = defaultText;
334 if (fileName.isNotEmpty) {
335 var introFile = new File(fileName);
336 introText = introFile.existsSync() ? introFile.readAsStringSync() :
337 defaultText;
338 }
339 return markdown.markdownToHtml(introText,
340 linkResolver: linkResolver, inlineSyntaxes: _MARKDOWN_SYNTAXES);
341 }
342
308 /// Creates documentation for filtered libraries. 343 /// Creates documentation for filtered libraries.
309 static void _documentLibraries(List<LibraryMirror> libs, 344 static void _documentLibraries(List<LibraryMirror> libs,
310 {bool includeSdk: false, bool outputToYaml: true, bool append: false, 345 {bool includeSdk: false, bool outputToYaml: true, bool append: false,
311 bool parseSdk: false, String introFileName: ''}) { 346 bool parseSdk: false, String introFileName: ''}) {
312 libs.forEach((lib) { 347 libs.forEach((lib) {
313 // Files belonging to the SDK have a uri that begins with 'dart:'. 348 // Files belonging to the SDK have a uri that begins with 'dart:'.
314 if (includeSdk || !lib.uri.toString().startsWith('dart:')) { 349 if (includeSdk || !lib.uri.toString().startsWith('dart:')) {
315 var library = generateLibrary(lib); 350 var library = generateLibrary(lib);
316 entityMap[library.name] = library;
317 } 351 }
318 }); 352 });
319 353
320 var filteredEntities = entityMap.values.where(_isFullChainVisible); 354 var filteredEntities = new Set<Indexable>();
321 355 for (Map<String, Set<Indexable>> firstLevel in
322 /*var filteredEntities2 = new Set<MirrorBased>(); 356 Indexable._mirrorToDocgen.values) {
323 for (Map<String, Set<MirrorBased>> firstLevel in mirrorToDocgen.values) { 357 for (Set<Indexable> items in firstLevel.values) {
324 for (Set<MirrorBased> items in firstLevel.values) { 358 for (Indexable item in items) {
325 for (MirrorBased item in items) {
326 if (_isFullChainVisible(item)) { 359 if (_isFullChainVisible(item)) {
327 filteredEntities2.add(item); 360 if (item is! Method ||
361 (item is Method && item.methodInheritedFrom == null)) {
362 filteredEntities.add(item);
363 }
328 } 364 }
329 } 365 }
330 } 366 }
331 }*/ 367 }
332
333 /*print('THHHHHEEE DIFFERENCE IS');
334 var set1 = new Set.from(filteredEntities);
335 var set2 = new Set.from(filteredEntities2);
336 var aResult = set2.difference(set1);
337 for (MirrorBased r in aResult) {
338 print(' a result is $r and ${r.docName}');
339 }*/
340 //print(set1.difference(set2));
341 368
342 // Outputs a JSON file with all libraries and their preview comments. 369 // Outputs a JSON file with all libraries and their preview comments.
343 // This will help the viewer know what libraries are available to read in. 370 // This will help the viewer know what libraries are available to read in.
344 var libraryMap; 371 var libraryMap;
345 var linkResolver = (name) => Indexable.globalFixReference(name);
346
347 String readIntroductionFile(String fileName, includeSdk) {
348 var defaultText = includeSdk ? _DEFAULT_SDK_INTRODUCTION : '';
349 var introText = defaultText;
350 if (fileName.isNotEmpty) {
351 var introFile = new File(fileName);
352 introText = introFile.existsSync() ? introFile.readAsStringSync() :
353 defaultText;
354 }
355 return markdown.markdownToHtml(introText,
356 linkResolver: linkResolver, inlineSyntaxes: _MARKDOWN_SYNTAXES);
357 }
358 372
359 if (append) { 373 if (append) {
360 var docsDir = listDir(_outputDirectory); 374 var docsDir = listDir(_outputDirectory);
361 if (!docsDir.contains('$_outputDirectory/library_list.json')) { 375 if (!docsDir.contains('$_outputDirectory/library_list.json')) {
362 throw new StateError('No library_list.json'); 376 throw new StateError('No library_list.json');
363 } 377 }
364 libraryMap = 378 libraryMap =
365 JSON.decode(new File( 379 JSON.decode(new File(
366 '$_outputDirectory/library_list.json').readAsStringSync()); 380 '$_outputDirectory/library_list.json').readAsStringSync());
367 libraryMap['libraries'].addAll(filteredEntities 381 libraryMap['libraries'].addAll(filteredEntities
368 .where((e) => e is Library) 382 .where((e) => e is Library)
369 .map((e) => e.previewMap)); 383 .map((e) => e.previewMap));
370 var intro = libraryMap['introduction']; 384 var intro = libraryMap['introduction'];
371 var spacing = intro.isEmpty ? '' : '<br/><br/>'; 385 var spacing = intro.isEmpty ? '' : '<br/><br/>';
372 libraryMap['introduction'] = 386 libraryMap['introduction'] =
373 "$intro$spacing${readIntroductionFile(introFileName, includeSdk)}"; 387 "$intro$spacing${_readIntroductionFile(introFileName, includeSdk)}";
374 outputToYaml = libraryMap['filetype'] == 'yaml'; 388 outputToYaml = libraryMap['filetype'] == 'yaml';
375 } else { 389 } else {
376 libraryMap = { 390 libraryMap = {
377 'libraries' : filteredEntities.where((e) => 391 'libraries' : filteredEntities.where((e) =>
378 e is Library).map((e) => e.previewMap).toList(), 392 e is Library).map((e) => e.previewMap).toList(),
379 'introduction' : readIntroductionFile(introFileName, includeSdk), 393 'introduction' : _readIntroductionFile(introFileName, includeSdk),
380 'filetype' : outputToYaml ? 'yaml' : 'json' 394 'filetype' : outputToYaml ? 'yaml' : 'json'
381 }; 395 };
382 } 396 }
397 _writeOutputFiles(libraryMap, filteredEntities, outputToYaml, append);
398 }
399
400 /// Output all of the libraries and classes into json or yaml files for
401 /// consumption by a viewer.
402 static void _writeOutputFiles(libraryMap,
403 Iterable<Indexable> filteredEntities, bool outputToYaml, bool append) {
383 _writeToFile(JSON.encode(libraryMap), 'library_list.json'); 404 _writeToFile(JSON.encode(libraryMap), 'library_list.json');
384 405
385 // Output libraries and classes to file after all information is generated. 406 // Output libraries and classes to file after all information is generated.
386 filteredEntities.where((e) => e is Class || e is Library).forEach((output) { 407 filteredEntities.where((e) => e is Class || e is Library).forEach((output) {
387 _writeIndexableToFile(output, outputToYaml); 408 _writeIndexableToFile(output, outputToYaml);
388 }); 409 });
389 410
390 // Outputs all the qualified names documented with their type. 411 // Outputs all the qualified names documented with their type.
391 // This will help generate search results. 412 // This will help generate search results.
392 _writeToFile(filteredEntities.map((e) => 413 _writeToFile(filteredEntities.map((e) =>
393 '${e.qualifiedName} ${e.typeName}').join('\n') + '\n', 414 '${e.qualifiedName} ${e.typeName}').join('\n') + '\n',
394 'index.txt', append: append); 415 'index.txt', append: append);
395 var index = new Map.fromIterables( 416 var index = new Map.fromIterables(
396 filteredEntities.map((e) => e.qualifiedName), 417 filteredEntities.map((e) => e.qualifiedName),
397 filteredEntities.map((e) => e.typeName)); 418 filteredEntities.map((e) => e.typeName));
398 if (append) { 419 if (append) {
399 var previousIndex = 420 var previousIndex =
400 JSON.decode(new File( 421 JSON.decode(new File(
401 '$_outputDirectory/index.json').readAsStringSync()); 422 '$_outputDirectory/index.json').readAsStringSync());
402 index.addAll(previousIndex); 423 index.addAll(previousIndex);
403 } 424 }
404 _writeToFile(JSON.encode(index), 'index.json'); 425 _writeToFile(JSON.encode(index), 'index.json');
405 } 426 }
406 427
428 /// Helper method to serialize the given Indexable out to a file.
407 static void _writeIndexableToFile(Indexable result, bool outputToYaml) { 429 static void _writeIndexableToFile(Indexable result, bool outputToYaml) {
408 var outputFile = result.fileName; 430 var outputFile = result.fileName;
409 var output; 431 var output;
410 if (outputToYaml) { 432 if (outputToYaml) {
411 output = getYamlString(result.toMap()); 433 output = getYamlString(result.toMap());
412 outputFile = outputFile + '.yaml'; 434 outputFile = outputFile + '.yaml';
413 } else { 435 } else {
414 output = JSON.encode(result.toMap()); 436 output = JSON.encode(result.toMap());
415 outputFile = outputFile + '.json'; 437 outputFile = outputFile + '.json';
416 } 438 }
417 _writeToFile(output, outputFile); 439 _writeToFile(output, outputFile);
418 } 440 }
419 441
420 /// Set the location of the ouput directory, and ensure that the location is 442 /// Set the location of the ouput directory, and ensure that the location is
421 /// available on the file system. 443 /// available on the file system.
422 static void _ensureOutputDirectory(String outputDirectory, bool append) { 444 static void _ensureOutputDirectory(String outputDirectory, bool append) {
423 _outputDirectory = outputDirectory; 445 _outputDirectory = outputDirectory;
424 if (!append) { 446 if (!append) {
425 var dir = new Directory(_outputDirectory); 447 var dir = new Directory(_outputDirectory);
426 if (dir.existsSync()) dir.deleteSync(recursive: true); 448 if (dir.existsSync()) dir.deleteSync(recursive: true);
427 } 449 }
428 } 450 }
429 451
430 452 /// Helper accessor to determine the full pathname of the root of the dart
453 /// checkout.
431 static String get _rootDirectory { 454 static String get _rootDirectory {
432 var scriptDir = path.absolute(path.dirname(Platform.script.toFilePath())); 455 var scriptDir = path.absolute(path.dirname(Platform.script.toFilePath()));
433 var root = scriptDir; 456 var root = scriptDir;
434 while(path.basename(root) != 'dart') { 457 while(path.basename(root) != 'dart') {
435 root = path.dirname(root); 458 root = path.dirname(root);
436 } 459 }
437 return root; 460 return root;
438 } 461 }
439 462
440 /// Analyzes set of libraries and provides a mirror system which can be used 463 /// Analyzes set of libraries and provides a mirror system which can be used
(...skipping 24 matching lines...) Expand all
465 }); 488 });
466 } 489 }
467 490
468 /// For this run of docgen, determine the packageRoot value. 491 /// For this run of docgen, determine the packageRoot value.
469 /// 492 ///
470 /// If packageRoot is not explicitly passed, we examine the files we're 493 /// If packageRoot is not explicitly passed, we examine the files we're
471 /// documenting to attempt to find a package root. 494 /// documenting to attempt to find a package root.
472 static String _obtainPackageRoot(String packageRoot, bool parseSdk, 495 static String _obtainPackageRoot(String packageRoot, bool parseSdk,
473 List<String> files) { 496 List<String> files) {
474 if (packageRoot == null && !parseSdk) { 497 if (packageRoot == null && !parseSdk) {
475 // TODO(efortuna): This logic seems not very robust, but it's from the
476 // original version of the code, pre-refactor, so I'm leavingt it for now.
477 // Revisit to make more robust.
478 // TODO(efortuna): See lines 303-311 in
479 // https://codereview.chromium.org/116043013/diff/390001/pkg/docgen/lib/do cgen.dart
480 var type = FileSystemEntity.typeSync(files.first); 498 var type = FileSystemEntity.typeSync(files.first);
481 if (type == FileSystemEntityType.DIRECTORY) { 499 if (type == FileSystemEntityType.DIRECTORY) {
482 var files2 = listDir(files.first, recursive: true); 500 var files2 = listDir(files.first, recursive: true);
483 // Return '' means that there was no pubspec.yaml and therefor no p 501 // Return '' means that there was no pubspec.yaml and therefor no p
484 // ackageRoot. 502 // ackageRoot.
485 packageRoot = files2.firstWhere((f) => 503 packageRoot = files2.firstWhere((f) =>
486 f.endsWith('${path.separator}pubspec.yaml'), orElse: () => ''); 504 f.endsWith('${path.separator}pubspec.yaml'), orElse: () => '');
487 if (packageRoot != '') { 505 if (packageRoot != '') {
488 packageRoot = path.join(path.dirname(packageRoot), 'packages'); 506 packageRoot = path.join(path.dirname(packageRoot), 'packages');
489 } 507 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 var sdk = new List<Uri>(); 581 var sdk = new List<Uri>();
564 LIBRARIES.forEach((String name, LibraryInfo info) { 582 LIBRARIES.forEach((String name, LibraryInfo info) {
565 if (info.documented) { 583 if (info.documented) {
566 sdk.add(Uri.parse('dart:$name')); 584 sdk.add(Uri.parse('dart:$name'));
567 logger.info('Add to SDK: ${sdk.last}'); 585 logger.info('Add to SDK: ${sdk.last}');
568 } 586 }
569 }); 587 });
570 return sdk; 588 return sdk;
571 } 589 }
572 590
591 /// Return true if this item and all of its owners are all visible.
573 static bool _isFullChainVisible(Indexable item) { 592 static bool _isFullChainVisible(Indexable item) {
574 // TODO: reconcile with isVisible. 593 return _includePrivate || (!item.isPrivate && (item.owner != null ?
575 // TODO: Also should be able to take MirrorBased items in general probably.
576 var result = _includePrivate || (!item.isPrivate && (item.owner != null ?
577 _isFullChainVisible(item.owner) : true)); 594 _isFullChainVisible(item.owner) : true));
578 return result;
579 } 595 }
580 596
581 /// Currently left public for testing purposes. :-/ 597 /// Currently left public for testing purposes. :-/
582 static Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { 598 static Library generateLibrary(dart2js.Dart2JsLibraryMirror library) {
583 var result = new Library(library); 599 var result = new Library(library);
584 result._findPackage(library); 600 result._findPackage(library);
585 logger.fine('Generated library for ${result.name}'); 601 logger.fine('Generated library for ${result.name}');
586 return result; 602 return result;
587 } 603 }
588 } 604 }
589 605
606 /// Convenience methods wrapped up in a class to pull down the docgen viewer for
607 /// a viewable website, and start up a server for viewing.
608 class _Viewer {
609 static String _dartdocViewerString = path.join(Directory.current.path,
610 'dartdoc-viewer');
611 static Directory _dartdocViewerDir = new Directory(_dartdocViewerString);
612 static Directory _topLevelTempDir;
613 static bool movedViewerCode = false;
614
615 /// If our dartdoc-viewer code is already checked out, move it to a temporary
616 /// directory outside of the package directory, so we don't try to process it
617 /// for documentation.
618 static void ensureMovedViewerCode() {
619 // TODO(efortuna): This will need to be modified to run on anyone's package
620 // outside of the checkout!
621 if (_dartdocViewerDir.existsSync()) {
622 _topLevelTempDir = new Directory(
623 _Generator._rootDirectory).createTempSync();
624 _dartdocViewerDir.renameSync(_topLevelTempDir.path);
625 }
626 }
627
628 /// Move the dartdoc-viewer code back into place for "webpage deployment."
629 static void addBackViewerCode() {
630 if (movedViewerCode) _dartdocViewerDir.renameSync(_dartdocViewerString);
631 }
632
633 /// Serve up our generated documentation for viewing in a browser.
634 static void _cloneAndServe() {
635 // If the viewer code is already there, then don't clone again.
636 if (_dartdocViewerDir.existsSync()) {
637 _moveDirectoryAndServe();
638 }
639 else {
640 var processResult = Process.runSync('git', ['clone', '-b', 'master',
641 'git://github.com/dart-lang/dartdoc-viewer.git'],
642 runInShell: true);
643
644 if (processResult.exitCode == 0) {
645 _moveDirectoryAndServe();
646 } else {
647 print('Error cloning git repository:');
648 print('process output: ${processResult.stdout}');
649 print('process stderr: ${processResult.stderr}');
650 }
651 }
652 }
653
654 /// Move the generated json/yaml docs directory to the dartdoc-viewer
655 /// directory, to run as a webpage.
656 static void _moveDirectoryAndServe() {
657 var dir = new Directory(_Generator._outputDirectory == null? 'docs' :
658 _Generator._outputDirectory);
659 var webDocsDir = new Directory(path.join(_dartdocViewerDir.path, 'client',
660 'web', 'docs'));
661 if (dir.existsSync()) {
662 // Move the docs folder to dartdoc-viewer/client/web/docs
663 dir.renameSync(webDocsDir.path);
664 }
665
666 if (webDocsDir.existsSync()) {
667 // Compile the code to JavaScript so we can run on any browser.
668 print('Compile app to JavaScript for viewing.');
669 var processResult = Process.runSync('dart', ['deploy.dart'],
670 workingDirectory : path.join(_dartdocViewerDir.path, 'client'),
671 runInShell: true);
672 print('process output: ${processResult.stdout}');
673 print('process stderr: ${processResult.stderr}');
674 _runServer();
675 }
676 }
677
678 /// A simple HTTP server. Implemented here because this is part of the SDK,
679 /// so it shouldn't have any external dependencies.
680 static void _runServer() {
681 // Launch a server to serve out of the directory dartdoc-viewer/client/web.
682 HttpServer.bind('localhost', 8080).then((HttpServer httpServer) {
683 print('Server launched. Navigate your browser to: '
684 'http://localhost:${httpServer.port}');
685 httpServer.listen((HttpRequest request) {
686 var response = request.response;
687 var basePath = path.join(_dartdocViewerDir.path, 'client', 'out',
688 'web');
689 var requestPath = path.join(basePath, request.uri.path.substring(1));
690 bool found = true;
691 var file = new File(requestPath);
692 if (file.existsSync()) {
693 // Set the correct header type.
694 if (requestPath.endsWith('.html')) {
695 response.headers.set('Content-Type', 'text/html');
696 } else if (requestPath.endsWith('.js')) {
697 response.headers.set('Content-Type', 'application/javascript');
698 } else if (requestPath.endsWith('.dart')) {
699 response.headers.set('Content-Type', 'application/dart');
700 } else if (requestPath.endsWith('.css')) {
701 response.headers.set('Content-Type', 'text/css');
702 }
703 } else {
704 if (requestPath == basePath) {
705 response.headers.set('Content-Type', 'text/html');
706 file = new File(path.join(basePath, 'index.html'));
707 } else {
708 print('Path not found: $requestPath');
709 found = false;
710 response.statusCode = HttpStatus.NOT_FOUND;
711 response.close();
712 }
713 }
714
715 if (found) {
716 // Serve up file contents.
717 file.openRead().pipe(response).catchError((e) {
718 print('HttpServer: error while closing the response stream $e');
719 });
720 }
721 },
722 onError: (e) {
723 print('HttpServer: an error occured $e');
724 });
725 });
726 }
727 }
728
590 /// An item that is categorized in our mirrorToDocgen map, as a distinct, 729 /// An item that is categorized in our mirrorToDocgen map, as a distinct,
591 /// searchable element. 730 /// searchable element.
592 /// 731 ///
593 /// These are items that refer to concrete entities (a Class, for example, 732 /// These are items that refer to concrete entities (a Class, for example,
594 /// but not a Type, which is a "pointer" to a class) that we wish to be 733 /// but not a Type, which is a "pointer" to a class) that we wish to be
595 /// globally resolvable. This includes things such as class methods and 734 /// globally resolvable. This includes things such as class methods and
596 /// variables, but parameters for methods are not "Indexable" as we do not want 735 /// variables, but parameters for methods are not "Indexable" as we do not want
597 /// the user to be able to search for a method based on its parameter names! 736 /// the user to be able to search for a method based on its parameter names!
598 /// The set of indexable items also includes Typedefs, since the user can refer 737 /// The set of indexable items also includes Typedefs, since the user can refer
599 /// to them as concrete entities in a particular scope. 738 /// to them as concrete entities in a particular scope.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 map[owner.docName] = set; 779 map[owner.docName] = set;
641 _mirrorToDocgen[this.mirror.qualifiedName] = map; 780 _mirrorToDocgen[this.mirror.qualifiedName] = map;
642 } 781 }
643 782
644 /** Walk up the owner chain to find the owning library. */ 783 /** Walk up the owner chain to find the owning library. */
645 Library _getOwningLibrary(Indexable indexable) { 784 Library _getOwningLibrary(Indexable indexable) {
646 if (indexable is Library) return indexable; 785 if (indexable is Library) return indexable;
647 return _getOwningLibrary(indexable.owner); 786 return _getOwningLibrary(indexable.owner);
648 } 787 }
649 788
650 static initializeTopLevelLibraries(MirrorSystem mirrorSystem) { 789 static _initializeTopLevelLibraries(MirrorSystem mirrorSystem) {
651 _sdkLibraries = mirrorSystem.libraries.values.where( 790 _sdkLibraries = mirrorSystem.libraries.values.where(
652 (each) => each.uri.scheme == 'dart'); 791 (each) => each.uri.scheme == 'dart');
653 _coreLibrary = new Library(_sdkLibraries.singleWhere((lib) => 792 _coreLibrary = new Library(_sdkLibraries.singleWhere((lib) =>
654 lib.uri.toString().startsWith('dart:core'))); 793 lib.uri.toString().startsWith('dart:core')));
655 } 794 }
656 795
657 /// Returns this object's qualified name, but following the conventions 796 /// Returns this object's qualified name, but following the conventions
658 /// we're using in Dartdoc, which is that library names with dots in them 797 /// we're using in Dartdoc, which is that library names with dots in them
659 /// have them replaced with hyphens. 798 /// have them replaced with hyphens.
660 String get docName; 799 String get docName;
661 800
662 markdown.Node fixReferenceWithScope(String name) => null;
663
664 /// Converts all [foo] references in comments to <a>libraryName.foo</a>. 801 /// Converts all [foo] references in comments to <a>libraryName.foo</a>.
665 markdown.Node fixReference(String name) { 802 markdown.Node fixReference(String name) {
666 // Attempt the look up the whole name up in the scope. 803 // Attempt the look up the whole name up in the scope.
667 String elementName = findElementInScope(name); 804 String elementName = findElementInScope(name);
668 if (elementName != null) { 805 if (elementName != null) {
669 return new markdown.Element.text('a', elementName); 806 return new markdown.Element.text('a', elementName);
670 } 807 }
671 return _fixComplexReference(name); 808 return _fixComplexReference(name);
672 } 809 }
673 810
674 /// Look for the specified name starting with the current member, and 811 /// Look for the specified name starting with the current member, and
675 /// progressively working outward to the current library scope. 812 /// progressively working outward to the current library scope.
676 String findElementInScope(String name) => 813 String findElementInScope(String name) =>
677 _findElementInScope(name, packagePrefix); 814 _findElementInScope(name, packagePrefix);
678 815
816 /// For a given name, determine if we need to resolve it as a qualified name
817 /// or a simple name in the source mirors.
679 static determineLookupFunc(name) => name.contains('.') ? 818 static determineLookupFunc(name) => name.contains('.') ?
680 dart2js_util.lookupQualifiedInScope : 819 dart2js_util.lookupQualifiedInScope :
681 (mirror, name) => mirror.lookupInScope(name); 820 (mirror, name) => mirror.lookupInScope(name);
682 821
683 // The qualified name (for URL purposes) and the file name are the same, 822 /// The reference to this element based on where it is printed as a
684 // of the form packageName/ClassName or packageName/ClassName.methodName. 823 /// documentation file and also the unique URL to refer to this item.
685 // This defines both the URL and the directory structure. 824 ///
686 String get fileName { 825 /// The qualified name (for URL purposes) and the file name are the same,
687 return packagePrefix + ownerPrefix + name; 826 /// of the form packageName/ClassName or packageName/ClassName.methodName.
688 } 827 /// This defines both the URL and the directory structure.
828 String get fileName => packagePrefix + ownerPrefix + name;
689 829
830 /// The full docName of the owner element, appended with a '.' for this
831 /// object's name to be appended.
690 String get ownerPrefix => owner.docName != '' ? owner.docName + '.' : ''; 832 String get ownerPrefix => owner.docName != '' ? owner.docName + '.' : '';
691 833
834 /// The prefix String to refer to the package that this item is in, for URLs
835 /// and comment resolution.
836 ///
837 /// The prefix can be prepended to a qualified name to get a fully unique
838 /// name among all packages.
692 String get packagePrefix => ''; 839 String get packagePrefix => '';
693 840
694 /// Documentation comment with converted markdown. 841 /// Documentation comment with converted markdown and all links resolved.
695 String _comment; 842 String _comment;
696 843
844 /// Accessor to documentation comment with markdown converted to html and all
845 /// links resolved.
697 String get comment { 846 String get comment {
698 if (_comment != null) return _comment; 847 if (_comment != null) return _comment;
699 848
700 _comment = _commentToHtml(); 849 _comment = _commentToHtml();
701 if (_comment.isEmpty) { 850 if (_comment.isEmpty) {
702 _comment = _mdnComment(); 851 _comment = _mdnComment();
703 } 852 }
704 return _comment; 853 return _comment;
705 } 854 }
706 855
707 set comment(x) => _comment = x; 856 set comment(x) => _comment = x;
708 857
858 /// The simple name to refer to this item.
709 String get name => mirror.simpleName; 859 String get name => mirror.simpleName;
710 860
861 /// Accessor to the parent item that owns this item.
862 ///
863 /// "Owning" is defined as the object one scope-level above which this item
864 /// is defined. Ex: The owner for a top level class, would be its enclosing
865 /// library. The owner of a local variable in a method would be the enclosing
866 /// method.
711 Indexable get owner => new DummyMirror(mirror.owner); 867 Indexable get owner => new DummyMirror(mirror.owner);
712 868
713 /// Generates MDN comments from database.json. 869 /// Generates MDN comments from database.json.
714 String _mdnComment() { 870 String _mdnComment();
715 //Check if MDN is loaded.
716 if (_mdn == null) {
717 // Reading in MDN related json file.
718 var root = _Generator._rootDirectory;
719 var mdnPath = path.join(root, 'utils/apidoc/mdn/database.json');
720 _mdn = JSON.decode(new File(mdnPath).readAsStringSync());
721 }
722 // TODO: refactor OOP
723 if (this is Library) return '';
724 var domAnnotation = this.annotations.firstWhere(
725 (e) => e.mirror.qualifiedName == 'metadata.DomName',
726 orElse: () => null);
727 if (domAnnotation == null) return '';
728 var domName = domAnnotation.parameters.single;
729 var parts = domName.split('.');
730 if (parts.length == 2) return _mdnMemberComment(parts[0], parts[1]);
731 if (parts.length == 1) return _mdnTypeComment(parts[0]);
732 }
733 871
734 /// Generates the MDN Comment for variables and method DOM elements. 872 /// Generates the MDN Comment for variables and method DOM elements.
735 String _mdnMemberComment(String type, String member) { 873 String _mdnMemberComment(String type, String member) {
736 var mdnType = _mdn[type]; 874 var mdnType = _mdn[type];
737 if (mdnType == null) return ''; 875 if (mdnType == null) return '';
738 var mdnMember = mdnType['members'].firstWhere((e) => e['name'] == member, 876 var mdnMember = mdnType['members'].firstWhere((e) => e['name'] == member,
739 orElse: () => null); 877 orElse: () => null);
740 if (mdnMember == null) return ''; 878 if (mdnMember == null) return '';
741 if (mdnMember['help'] == null || mdnMember['help'] == '') return ''; 879 if (mdnMember['help'] == null || mdnMember['help'] == '') return '';
742 if (mdnMember['url'] == null) return ''; 880 if (mdnMember['url'] == null) return '';
743 return _htmlMdn(mdnMember['help'], mdnMember['url']); 881 return _htmlifyMdn(mdnMember['help'], mdnMember['url']);
744 } 882 }
745 883
746 /// Generates the MDN Comment for class DOM elements. 884 /// Generates the MDN Comment for class DOM elements.
747 String _mdnTypeComment(String type) { 885 String _mdnTypeComment(String type) {
748 var mdnType = _mdn[type]; 886 var mdnType = _mdn[type];
749 if (mdnType == null) return ''; 887 if (mdnType == null) return '';
750 if (mdnType['summary'] == null || mdnType['summary'] == "") return ''; 888 if (mdnType['summary'] == null || mdnType['summary'] == "") return '';
751 if (mdnType['srcUrl'] == null) return ''; 889 if (mdnType['srcUrl'] == null) return '';
752 return _htmlMdn(mdnType['summary'], mdnType['srcUrl']); 890 return _htmlifyMdn(mdnType['summary'], mdnType['srcUrl']);
753 } 891 }
754 892
755 String _htmlMdn(String content, String url) { 893 /// Encloses the given content in an MDN div and the original source link.
894 String _htmlifyMdn(String content, String url) {
756 return '<div class="mdn">' + content.trim() + '<p class="mdn-note">' 895 return '<div class="mdn">' + content.trim() + '<p class="mdn-note">'
757 '<a href="' + url.trim() + '">from Mdn</a></p></div>'; 896 '<a href="' + url.trim() + '">from Mdn</a></p></div>';
758 } 897 }
759 898
760 /// The type of this member to be used in index.txt. 899 /// The type of this member to be used in index.txt.
761 String get typeName => ''; 900 String get typeName => '';
762 901
763 /// Creates a [Map] with this [Indexable]'s name and a preview comment. 902 /// Creates a [Map] with this [Indexable]'s name and a preview comment.
764 Map get previewMap { 903 Map get previewMap {
765 var finalMap = { 'name' : name, 'qualifiedName' : qualifiedName }; 904 var finalMap = { 'name' : name, 'qualifiedName' : qualifiedName };
766 if (comment != '') { 905 if (comment != '') {
767 var index = comment.indexOf('</p>'); 906 var index = comment.indexOf('</p>');
768 finalMap['preview'] = '${comment.substring(0, index)}</p>'; 907 finalMap['preview'] = '${comment.substring(0, index)}</p>';
769 } 908 }
770 return finalMap; 909 return finalMap;
771 } 910 }
772 911
773 String _getCommentText() { 912 /// Accessor to obtain the raw comment text for a given item, _without_ any
913 /// of the links resolved.
914 String get _commentText {
774 String commentText; 915 String commentText;
775 mirror.metadata.forEach((metadata) { 916 mirror.metadata.forEach((metadata) {
776 if (metadata is CommentInstanceMirror) { 917 if (metadata is CommentInstanceMirror) {
777 CommentInstanceMirror comment = metadata; 918 CommentInstanceMirror comment = metadata;
778 if (comment.isDocComment) { 919 if (comment.isDocComment) {
779 if (commentText == null) { 920 if (commentText == null) {
780 commentText = comment.trimmedText; 921 commentText = comment.trimmedText;
781 } else { 922 } else {
782 commentText = '$commentText\n${comment.trimmedText}'; 923 commentText = '$commentText\n${comment.trimmedText}';
783 } 924 }
784 } 925 }
785 } 926 }
786 }); 927 });
787 return commentText; 928 return commentText;
788 } 929 }
789 930
790 /// Returns any documentation comments associated with a mirror with 931 /// Returns any documentation comments associated with a mirror with
791 /// simple markdown converted to html. 932 /// simple markdown converted to html.
792 /// 933 ///
793 /// By default we resolve any comment references within our own scope. 934 /// By default we resolve any comment references within our own scope.
794 /// However, if a method is inherited, we want the inherited comments, but 935 /// However, if a method is inherited, we want the inherited comments, but
795 /// links to the subclasses's version of the methods. 936 /// links to the subclasses's version of the methods.
796 String _commentToHtml([Indexable resolvingScope]) { 937 String _commentToHtml([Indexable resolvingScope]) {
797 if (resolvingScope == null) resolvingScope = this; 938 if (resolvingScope == null) resolvingScope = this;
798 var commentText = _getCommentText(); 939 var commentText = _commentText;
799 _unresolvedComment = commentText; 940 _unresolvedComment = commentText;
800 941
801 var linkResolver = (name) => resolvingScope.fixReferenceWithScope(name); 942 var linkResolver = (name) => resolvingScope.fixReference(name);
802 commentText = commentText == null ? '' : 943 commentText = commentText == null ? '' :
803 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver, 944 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver,
804 inlineSyntaxes: _MARKDOWN_SYNTAXES); 945 inlineSyntaxes: _MARKDOWN_SYNTAXES);
805 return commentText; 946 return commentText;
806 } 947 }
807 948
808 /// Returns a map of [Variable] objects constructed from [mirrorMap]. 949 /// Returns a map of [Variable] objects constructed from [mirrorMap].
809 /// The optional parameter [containingLibrary] is contains data for variables 950 /// The optional parameter [containingLibrary] is contains data for variables
810 /// defined at the top level of a library (potentially for exporting 951 /// defined at the top level of a library (potentially for exporting
811 /// purposes). 952 /// purposes).
812 Map<String, Variable> _createVariables(Map<String, VariableMirror> mirrorMap, 953 Map<String, Variable> _createVariables(Map<String, VariableMirror> mirrorMap,
813 Indexable owner) { 954 Indexable owner) {
814 var data = {}; 955 var data = {};
815 // TODO(janicejl): When map to map feature is created, replace the below 956 // TODO(janicejl): When map to map feature is created, replace the below
816 // with a filter. Issue(#9590). 957 // with a filter. Issue(#9590).
817 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { 958 mirrorMap.forEach((String mirrorName, VariableMirror mirror) {
818 if (_Generator._includePrivate || !_isHidden(mirror)) { 959 if (_Generator._includePrivate || !_isHidden(mirror)) {
819 var variable = new Variable(mirrorName, mirror, owner); 960 data[mirrorName] = new Variable(mirrorName, mirror, owner);
820 entityMap[variable.docName] = variable;
821 data[mirrorName] = entityMap[variable.docName];
822 } 961 }
823 }); 962 });
824 return data; 963 return data;
825 } 964 }
826 965
827 /// Returns a map of [Method] objects constructed from [mirrorMap]. 966 /// Returns a map of [Method] objects constructed from [mirrorMap].
828 /// The optional parameter [containingLibrary] is contains data for variables 967 /// The optional parameter [containingLibrary] is contains data for variables
829 /// defined at the top level of a library (potentially for exporting 968 /// defined at the top level of a library (potentially for exporting
830 /// purposes). 969 /// purposes).
831 Map<String, Method> _createMethods(Map<String, MethodMirror> mirrorMap, 970 Map<String, Method> _createMethods(Map<String, MethodMirror> mirrorMap,
832 Indexable owner) { 971 Indexable owner) {
833 var group = new Map<String, Method>(); 972 var group = new Map<String, Method>();
834 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { 973 mirrorMap.forEach((String mirrorName, MethodMirror mirror) {
835 if (_Generator._includePrivate || !mirror.isPrivate) { 974 if (_Generator._includePrivate || !mirror.isPrivate) {
836 var method = new Method(mirror, owner); 975 group[mirror.simpleName] = new Method(mirror, owner);
837 entityMap[method.docName] = method;
838 group[mirror.simpleName] = method;
839 } 976 }
840 }); 977 });
841 return group; 978 return group;
842 } 979 }
843 980
844 /// Returns a map of [Parameter] objects constructed from [mirrorList]. 981 /// Returns a map of [Parameter] objects constructed from [mirrorList].
845 Map<String, Parameter> _createParameters(List<ParameterMirror> mirrorList, 982 Map<String, Parameter> _createParameters(List<ParameterMirror> mirrorList,
846 Indexable owner) { 983 Indexable owner) {
847 var data = {}; 984 var data = {};
848 mirrorList.forEach((ParameterMirror mirror) { 985 mirrorList.forEach((ParameterMirror mirror) {
849 data[mirror.simpleName] = new Parameter(mirror, _getOwningLibrary(owner)); 986 data[mirror.simpleName] = new Parameter(mirror, _getOwningLibrary(owner));
850 }); 987 });
851 return data; 988 return data;
852 } 989 }
853 990
854 /// Returns a map of [Generic] objects constructed from the class mirror. 991 /// Returns a map of [Generic] objects constructed from the class mirror.
855 Map<String, Generic> _createGenerics(ClassMirror mirror) { 992 Map<String, Generic> _createGenerics(ClassMirror mirror) {
856 return new Map.fromIterable(mirror.typeVariables, 993 return new Map.fromIterable(mirror.typeVariables,
857 key: (e) => e.toString(), 994 key: (e) => e.toString(),
858 value: (e) => new Generic(e)); 995 value: (e) => new Generic(e));
859 } 996 }
860 997
861 /// Return an informative [Object.toString] for debugging. 998 /// Return an informative [Object.toString] for debugging.
862 String toString() => "${super.toString()}(${name.toString()})"; 999 String toString() => "${super.toString()}(${name.toString()})";
863 1000
864 /// Return a map representation of this type. 1001 /// Return a map representation of this type.
865 Map toMap() {} 1002 Map toMap();
866
867 1003
868 /// A declaration is private if itself is private, or the owner is private. 1004 /// A declaration is private if itself is private, or the owner is private.
869 // Issue(12202) - A declaration is public even if it's owner is private. 1005 // Issue(12202) - A declaration is public even if it's owner is private.
870 bool _isHidden(DeclarationMirror mirror) { 1006 bool _isHidden(DeclarationMirror mirror) {
871 if (mirror is LibraryMirror) { 1007 if (mirror is LibraryMirror) {
872 return _isLibraryPrivate(mirror); 1008 return _isLibraryPrivate(mirror);
873 } else if (mirror.owner is LibraryMirror) { 1009 } else if (mirror.owner is LibraryMirror) {
874 return (mirror.isPrivate || _isLibraryPrivate(mirror.owner) 1010 return (mirror.isPrivate || _isLibraryPrivate(mirror.owner)
875 || mirror.isNameSynthetic); 1011 || mirror.isNameSynthetic);
876 } else { 1012 } else {
877 return (mirror.isPrivate || _isHidden(mirror.owner) 1013 return (mirror.isPrivate || _isHidden(mirror.owner)
878 || owner.mirror.isNameSynthetic); 1014 || owner.mirror.isNameSynthetic);
879 } 1015 }
880 } 1016 }
881 1017
882 /// Returns true if a library name starts with an underscore, and false 1018 /// Returns true if a library name starts with an underscore, and false
883 /// otherwise. 1019 /// otherwise.
884 /// 1020 ///
885 /// An example that starts with _ is _js_helper. 1021 /// An example that starts with _ is _js_helper.
886 /// An example that contains ._ is dart._collection.dev 1022 /// An example that contains ._ is dart._collection.dev
887 // This is because LibraryMirror.isPrivate returns `false` all the time.
888 bool _isLibraryPrivate(LibraryMirror mirror) { 1023 bool _isLibraryPrivate(LibraryMirror mirror) {
1024 // This method is needed because LibraryMirror.isPrivate returns `false` all
1025 // the time.
889 var sdkLibrary = LIBRARIES[mirror.simpleName]; 1026 var sdkLibrary = LIBRARIES[mirror.simpleName];
890 if (sdkLibrary != null) { 1027 if (sdkLibrary != null) {
891 return !sdkLibrary.documented; 1028 return !sdkLibrary.documented;
892 } else if (mirror.simpleName.startsWith('_') || 1029 } else if (mirror.simpleName.startsWith('_') ||
893 mirror.simpleName.contains('._')) { 1030 mirror.simpleName.contains('._')) {
894 return true; 1031 return true;
895 } 1032 }
896 return false; 1033 return false;
897 } 1034 }
898 1035
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 return packagePrefix + result.docName; 1141 return packagePrefix + result.docName;
1005 } else { 1142 } else {
1006 return result.packagePrefix + result.docName; 1143 return result.packagePrefix + result.docName;
1007 } 1144 }
1008 } 1145 }
1009 } 1146 }
1010 } 1147 }
1011 return null; 1148 return null;
1012 } 1149 }
1013 1150
1014 Map expandMethodMap(Map<String, Method> mapToExpand) => { 1151 /// Expand the method map [mapToExpand] into a more detailed map that
1015 'setters': recurseMap(_filterMap(new Map(), mapToExpand, 1152 /// separates out setters, getters, constructors, operators, and methods.
1153 Map _expandMethodMap(Map<String, Method> mapToExpand) => {
1154 'setters': recurseMap(_filterMap(mapToExpand,
1016 (key, val) => val.mirror.isSetter)), 1155 (key, val) => val.mirror.isSetter)),
1017 'getters': recurseMap(_filterMap(new Map(), mapToExpand, 1156 'getters': recurseMap(_filterMap(mapToExpand,
1018 (key, val) => val.mirror.isGetter)), 1157 (key, val) => val.mirror.isGetter)),
1019 'constructors': recurseMap(_filterMap(new Map(), mapToExpand, 1158 'constructors': recurseMap(_filterMap(mapToExpand,
1020 (key, val) => val.mirror.isConstructor)), 1159 (key, val) => val.mirror.isConstructor)),
1021 'operators': recurseMap(_filterMap(new Map(), mapToExpand, 1160 'operators': recurseMap(_filterMap(mapToExpand,
1022 (key, val) => val.mirror.isOperator)), 1161 (key, val) => val.mirror.isOperator)),
1023 'methods': recurseMap(_filterMap(new Map(), mapToExpand, 1162 'methods': recurseMap(_filterMap(mapToExpand,
1024 (key, val) => val.mirror.isRegularMethod && !val.mirror.isOperator)) 1163 (key, val) => val.mirror.isRegularMethod && !val.mirror.isOperator))
1025 }; 1164 };
1026 1165
1027 /// Transforms the map by calling toMap on each value in it. 1166 /// Transforms the map by calling toMap on each value in it.
1028 Map recurseMap(Map inputMap) { 1167 Map recurseMap(Map inputMap) {
1029 var outputMap = {}; 1168 var outputMap = {};
1030 inputMap.forEach((key, value) { 1169 inputMap.forEach((key, value) {
1031 if (value is Map) { 1170 if (value is Map) {
1032 outputMap[key] = recurseMap(value); 1171 outputMap[key] = recurseMap(value);
1033 } else { 1172 } else {
1034 outputMap[key] = value.toMap(); 1173 outputMap[key] = value.toMap();
1035 } 1174 }
1036 }); 1175 });
1037 return outputMap; 1176 return outputMap;
1038 } 1177 }
1039 1178
1040 Map _filterMap(exported, map, test) { 1179 Map _filterMap(Map map, Function test) {
1180 var exported = new Map();
1041 map.forEach((key, value) { 1181 map.forEach((key, value) {
1042 if (test(key, value)) exported[key] = value; 1182 if (test(key, value)) exported[key] = value;
1043 }); 1183 });
1044 return exported; 1184 return exported;
1045 } 1185 }
1046 1186
1047 bool get _isVisible => _Generator._includePrivate || !isPrivate; 1187 /// Accessor to determine if this item and all of its owners are visible.
1188 bool get _isVisible => _Generator._isFullChainVisible(this);
1048 1189
1049 /// Given a Dart2jsMirror, find the corresponding Docgen [MirrorBased] object. 1190 /// Given a Dart2jsMirror, find the corresponding Docgen [MirrorBased] object.
1050 /// 1191 ///
1051 /// We have this global lookup function to avoid re-implementing looking up 1192 /// We have this global lookup function to avoid re-implementing looking up
1052 /// the scoping rules for comment resolution here (it is currently done in 1193 /// the scoping rules for comment resolution here (it is currently done in
1053 /// mirrors). If no corresponding MirrorBased object is found, we return a 1194 /// mirrors). If no corresponding MirrorBased object is found, we return a
1054 /// [DummyMirror] that simply returns the original mirror's qualifiedName 1195 /// [DummyMirror] that simply returns the original mirror's qualifiedName
1055 /// while behaving like a MirrorBased object. 1196 /// while behaving like a MirrorBased object.
1056 static Indexable getDocgenObject(DeclarationMirror mirror, 1197 static Indexable getDocgenObject(DeclarationMirror mirror,
1057 [Indexable owner]) { 1198 [Indexable owner]) {
(...skipping 25 matching lines...) Expand all
1083 } 1224 }
1084 } 1225 }
1085 1226
1086 if (results.length > 0) { 1227 if (results.length > 0) {
1087 // This might occur if we didn't specify an "owner." 1228 // This might occur if we didn't specify an "owner."
1088 return results.first; 1229 return results.first;
1089 } 1230 }
1090 return new DummyMirror(mirror, owner); 1231 return new DummyMirror(mirror, owner);
1091 } 1232 }
1092 1233
1234 /// Returns true if [mirror] is the correct type of mirror that this Docgen
1235 /// object wraps. (Workaround for the fact that Types are not first class.)
1093 bool _isValidMirror(DeclarationMirror mirror); 1236 bool _isValidMirror(DeclarationMirror mirror);
1094 } 1237 }
1095 1238
1096 /// A class containing contents of a Dart library. 1239 /// A class containing contents of a Dart library.
1097 class Library extends Indexable { 1240 class Library extends Indexable {
1098 1241
1099 /// Top-level variables in the library. 1242 /// Top-level variables in the library.
1100 Map<String, Variable> variables; 1243 Map<String, Variable> variables;
1101 1244
1102 /// Top-level functions in the library. 1245 /// Top-level functions in the library.
1103 Map<String, Method> functions; 1246 Map<String, Method> functions;
1104 1247
1105 Map<String, Class> classes = {}; 1248 Map<String, Class> classes = {};
1106 Map<String, Typedef> typedefs = {}; 1249 Map<String, Typedef> typedefs = {};
1107 Map<String, Class> errors = {}; 1250 Map<String, Class> errors = {};
1108 1251
1109 String packageName = ''; 1252 String packageName = '';
1110 bool hasBeenCheckedForPackage = false; 1253 bool _hasBeenCheckedForPackage = false;
1111 String packageIntro; 1254 String packageIntro;
1112 1255
1113 /// Returns the [Library] for the given [mirror] if it has already been 1256 /// Returns the [Library] for the given [mirror] if it has already been
1114 /// created, else creates it. 1257 /// created, else creates it.
1115 factory Library(LibraryMirror mirror) { 1258 factory Library(LibraryMirror mirror) {
1116 var library = Indexable.getDocgenObject(mirror); 1259 var library = Indexable.getDocgenObject(mirror);
1117 if (library is DummyMirror) { 1260 if (library is DummyMirror) {
1118 library = new Library._(mirror); 1261 library = new Library._(mirror);
1119 } 1262 }
1120 return library; 1263 return library;
1121 } 1264 }
1122 1265
1123 Library._(LibraryMirror libraryMirror) : super(libraryMirror) { 1266 Library._(LibraryMirror libraryMirror) : super(libraryMirror) {
1124 var exported = _calcExportedItems(libraryMirror); 1267 var exported = _calcExportedItems(libraryMirror);
1125 var exportedClasses = exported['classes']..addAll(libraryMirror.classes); 1268 var exportedClasses = exported['classes']..addAll(libraryMirror.classes);
1126 _findPackage(mirror); 1269 _findPackage(mirror);
1127 classes = {}; 1270 classes = {};
1128 typedefs = {}; 1271 typedefs = {};
1129 errors = {}; 1272 errors = {};
1130 exportedClasses.forEach((String mirrorName, ClassMirror classMirror) { 1273 exportedClasses.forEach((String mirrorName, ClassMirror classMirror) {
1131 if (classMirror.isTypedef) { 1274 if (classMirror.isTypedef) {
1132 // This is actually a Dart2jsTypedefMirror, and it does define value, 1275 // This is actually a Dart2jsTypedefMirror, and it does define value,
1133 // but we don't have visibility to that type. 1276 // but we don't have visibility to that type.
1134 var mirror = classMirror; 1277 var mirror = classMirror;
1135 if (_Generator._includePrivate || !mirror.isPrivate) { 1278 if (_Generator._includePrivate || !mirror.isPrivate) {
1136 var aTypedef = new Typedef(mirror, this); 1279 typedefs[mirror.simpleName] = new Typedef(mirror, this);
1137 entityMap[Indexable.getDocgenObject(mirror).docName] = aTypedef;
1138 typedefs[mirror.simpleName] = aTypedef;
1139 } 1280 }
1140 } else { 1281 } else {
1141 var clazz = new Class(classMirror, this); 1282 var clazz = new Class(classMirror, this);
1142 1283
1143 if (clazz.isError()) { 1284 if (clazz.isError()) {
1144 errors[classMirror.simpleName] = clazz; 1285 errors[classMirror.simpleName] = clazz;
1145 } else if (classMirror.isClass) { 1286 } else if (classMirror.isClass) {
1146 classes[classMirror.simpleName] = clazz; 1287 classes[classMirror.simpleName] = clazz;
1147 } else { 1288 } else {
1148 throw new ArgumentError( 1289 throw new ArgumentError(
(...skipping 13 matching lines...) Expand all
1162 var lookupFunc = Indexable.determineLookupFunc(name); 1303 var lookupFunc = Indexable.determineLookupFunc(name);
1163 var libraryScope = lookupFunc(mirror, name); 1304 var libraryScope = lookupFunc(mirror, name);
1164 if (libraryScope != null) { 1305 if (libraryScope != null) {
1165 var result = Indexable.getDocgenObject(libraryScope, this); 1306 var result = Indexable.getDocgenObject(libraryScope, this);
1166 if (result is DummyMirror) return packagePrefix + result.docName; 1307 if (result is DummyMirror) return packagePrefix + result.docName;
1167 return result.packagePrefix + result.docName; 1308 return result.packagePrefix + result.docName;
1168 } 1309 }
1169 return super.findElementInScope(name); 1310 return super.findElementInScope(name);
1170 } 1311 }
1171 1312
1313 String _mdnComment() => '';
1314
1172 /// For a library's [mirror], determine the name of the package (if any) we 1315 /// For a library's [mirror], determine the name of the package (if any) we
1173 /// believe it came from (because of its file URI). 1316 /// believe it came from (because of its file URI).
1174 /// 1317 ///
1175 /// If no package could be determined, we return an empty string. 1318 /// If no package could be determined, we return an empty string.
1176 String _findPackage(LibraryMirror mirror) { 1319 String _findPackage(LibraryMirror mirror) {
1177 if (mirror == null) return ''; 1320 if (mirror == null) return '';
1178 if (hasBeenCheckedForPackage) return packageName; 1321 if (_hasBeenCheckedForPackage) return packageName;
1179 hasBeenCheckedForPackage = true; 1322 _hasBeenCheckedForPackage = true;
1180 if (mirror.uri.scheme != 'file') return ''; 1323 if (mirror.uri.scheme != 'file') return '';
1181 // We assume that we are documenting only libraries under package/lib 1324 // We assume that we are documenting only libraries under package/lib
1182 packageName = _packageName(mirror); 1325 packageName = _packageName(mirror);
1183 // Associate the package readme with all the libraries. This is a bit 1326 // Associate the package readme with all the libraries. This is a bit
1184 // wasteful, but easier than trying to figure out which partial match 1327 // wasteful, but easier than trying to figure out which partial match
1185 // is best. 1328 // is best.
1186 packageIntro = _packageIntro(_getRootdir(mirror)); 1329 packageIntro = _packageIntro(_getRootdir(mirror));
1187 return packageName; 1330 return packageName;
1188 } 1331 }
1189 1332
(...skipping 24 matching lines...) Expand all
1214 if (mirror.uri.scheme != 'file') return ''; 1357 if (mirror.uri.scheme != 'file') return '';
1215 var rootdir = _getRootdir(mirror); 1358 var rootdir = _getRootdir(mirror);
1216 var pubspecName = path.join(rootdir, 'pubspec.yaml'); 1359 var pubspecName = path.join(rootdir, 'pubspec.yaml');
1217 File pubspec = new File(pubspecName); 1360 File pubspec = new File(pubspecName);
1218 if (!pubspec.existsSync()) return ''; 1361 if (!pubspec.existsSync()) return '';
1219 var contents = pubspec.readAsStringSync(); 1362 var contents = pubspec.readAsStringSync();
1220 var spec = loadYaml(contents); 1363 var spec = loadYaml(contents);
1221 return spec["name"]; 1364 return spec["name"];
1222 } 1365 }
1223 1366
1224 markdown.Node fixReferenceWithScope(String name) => fixReference(name);
1225
1226 String get packagePrefix => packageName == null || packageName.isEmpty ? 1367 String get packagePrefix => packageName == null || packageName.isEmpty ?
1227 '' : '$packageName/'; 1368 '' : '$packageName/';
1228 1369
1229 Map get previewMap { 1370 Map get previewMap {
1230 var basic = super.previewMap; 1371 var basic = super.previewMap;
1231 basic['packageName'] = packageName; 1372 basic['packageName'] = packageName;
1232 if (packageIntro != null) { 1373 if (packageIntro != null) {
1233 basic['packageIntro'] = packageIntro; 1374 basic['packageIntro'] = packageIntro;
1234 } 1375 }
1235 return basic; 1376 return basic;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 // library. Ex: "export foo show bar" 1436 // library. Ex: "export foo show bar"
1296 // Otherwise, add all items, and then remove the hidden ones. 1437 // Otherwise, add all items, and then remove the hidden ones.
1297 // Ex: "export foo hide bar" 1438 // Ex: "export foo hide bar"
1298 _populateExports(export, 1439 _populateExports(export,
1299 export.combinators.any((combinator) => combinator.isShow)); 1440 export.combinators.any((combinator) => combinator.isShow));
1300 } 1441 }
1301 return exports; 1442 return exports;
1302 } 1443 }
1303 1444
1304 /// Checks if the given name is a key for any of the Class Maps. 1445 /// Checks if the given name is a key for any of the Class Maps.
1305 bool containsKey(String name) { 1446 bool containsKey(String name) =>
1306 return classes.containsKey(name) || errors.containsKey(name); 1447 classes.containsKey(name) || errors.containsKey(name);
1307 }
1308 1448
1309 /// Generates a map describing the [Library] object. 1449 /// Generates a map describing the [Library] object.
1310 Map toMap() => { 1450 Map toMap() => {
1311 'name': name, 1451 'name': name,
1312 'qualifiedName': qualifiedName, 1452 'qualifiedName': qualifiedName,
1313 'comment': comment, 1453 'comment': comment,
1314 'variables': recurseMap(variables), 1454 'variables': recurseMap(variables),
1315 'functions': expandMethodMap(functions), 1455 'functions': _expandMethodMap(functions),
1316 'classes': { 1456 'classes': {
1317 'class': classes.values.where((c) => c._isVisible) 1457 'class': classes.values.where((c) => c._isVisible)
1318 .map((e) => e.previewMap).toList(), 1458 .map((e) => e.previewMap).toList(),
1319 'typedef': recurseMap(typedefs), 1459 'typedef': recurseMap(typedefs),
1320 'error': errors.values.where((e) => e._isVisible) 1460 'error': errors.values.where((e) => e._isVisible)
1321 .map((e) => e.previewMap).toList() 1461 .map((e) => e.previewMap).toList()
1322 }, 1462 },
1323 'packageName': packageName, 1463 'packageName': packageName,
1324 'packageIntro' : packageIntro 1464 'packageIntro' : packageIntro
1325 }; 1465 };
1326 1466
1327 String get typeName => 'library'; 1467 String get typeName => 'library';
1328 1468
1329 bool _isValidMirror(DeclarationMirror mirror) => mirror is LibraryMirror; 1469 bool _isValidMirror(DeclarationMirror mirror) => mirror is LibraryMirror;
1330 } 1470 }
1331 1471
1332 abstract class OwnedIndexable extends Indexable { 1472 abstract class OwnedIndexable extends Indexable {
1473 /// The object one scope-level above which this item is defined.
1474 ///
1475 /// Ex: The owner for a top level class, would be its enclosing library.
1476 /// The owner of a local variable in a method would be the enclosing method.
1333 Indexable owner; 1477 Indexable owner;
1334 1478
1479 /// List of the meta annotations on this item.
1480 List<Annotation> annotations;
1481
1335 /// Returns this object's qualified name, but following the conventions 1482 /// Returns this object's qualified name, but following the conventions
1336 /// we're using in Dartdoc, which is that library names with dots in them 1483 /// we're using in Dartdoc, which is that library names with dots in them
1337 /// have them replaced with hyphens. 1484 /// have them replaced with hyphens.
1338 String get docName => owner.docName + '.' + mirror.simpleName; 1485 String get docName => owner.docName + '.' + mirror.simpleName;
1339 1486
1340 OwnedIndexable(DeclarationMirror mirror, this.owner) : super(mirror); 1487 OwnedIndexable(DeclarationMirror mirror, this.owner) : super(mirror);
1488
1489 /// Generates MDN comments from database.json.
1490 String _mdnComment() {
1491 //Check if MDN is loaded.
1492 if (Indexable._mdn == null) {
1493 // Reading in MDN related json file.
1494 var root = _Generator._rootDirectory;
1495 var mdnPath = path.join(root, 'utils/apidoc/mdn/database.json');
1496 Indexable._mdn = JSON.decode(new File(mdnPath).readAsStringSync());
1497 }
1498 var domAnnotation = this.annotations.firstWhere(
1499 (e) => e.mirror.qualifiedName == 'metadata.DomName',
1500 orElse: () => null);
1501 if (domAnnotation == null) return '';
1502 var domName = domAnnotation.parameters.single;
1503 var parts = domName.split('.');
1504 if (parts.length == 2) return _mdnMemberComment(parts[0], parts[1]);
1505 if (parts.length == 1) return _mdnTypeComment(parts[0]);
1506 }
1341 } 1507 }
1342 1508
1343 /// A class containing contents of a Dart class. 1509 /// A class containing contents of a Dart class.
1344 class Class extends OwnedIndexable implements Comparable { 1510 class Class extends OwnedIndexable implements Comparable {
1345 1511
1346 /// List of the names of interfaces that this class implements. 1512 /// List of the names of interfaces that this class implements.
1347 List<Class> interfaces = []; 1513 List<Class> interfaces = [];
1348 1514
1349 /// Names of classes that extends or implements this class. 1515 /// Names of classes that extends or implements this class.
1350 Set<Class> subclasses = new Set<Class>(); 1516 Set<Class> subclasses = new Set<Class>();
1351 1517
1352 /// Top-level variables in the class. 1518 /// Top-level variables in the class.
1353 Map<String, Variable> variables; 1519 Map<String, Variable> variables;
1354 1520
1355 /// Inherited variables in the class. 1521 /// Inherited variables in the class.
1356 Map<String, Variable> inheritedVariables; 1522 Map<String, Variable> inheritedVariables;
1357 1523
1358 /// Methods in the class. 1524 /// Methods in the class.
1359 Map<String, Method> methods; 1525 Map<String, Method> methods;
1360 1526
1361 Map<String, Method> inheritedMethods; 1527 Map<String, Method> inheritedMethods;
1362 1528
1363 /// Generic infomation about the class. 1529 /// Generic infomation about the class.
1364 Map<String, Generic> generics; 1530 Map<String, Generic> generics;
1365 1531
1366 Class superclass; 1532 Class superclass;
1367 bool isAbstract; 1533 bool isAbstract;
1368 1534
1369 /// List of the meta annotations on the class.
1370 List<Annotation> annotations;
1371
1372 /// Make sure that we don't check for inherited comments more than once. 1535 /// Make sure that we don't check for inherited comments more than once.
1373 bool _commentsEnsured = false; 1536 bool _commentsEnsured = false;
1374 1537
1375 /// Returns the [Class] for the given [mirror] if it has already been created, 1538 /// Returns the [Class] for the given [mirror] if it has already been created,
1376 /// else creates it. 1539 /// else creates it.
1377 factory Class(ClassMirror mirror, Library owner) { 1540 factory Class(ClassMirror mirror, Library owner) {
1378 var clazz = Indexable.getDocgenObject(mirror, owner); 1541 var clazz = Indexable.getDocgenObject(mirror, owner);
1379 if (clazz is DummyMirror) { 1542 if (clazz is DummyMirror) {
1380 clazz = new Class._(mirror, owner); 1543 clazz = new Class._(mirror, owner);
1381 entityMap[clazz.docName] = clazz;
1382 } 1544 }
1383 return clazz; 1545 return clazz;
1384 } 1546 }
1385 1547
1386 /// Called when we are constructing a superclass or interface class, but it 1548 /// Called when we are constructing a superclass or interface class, but it
1387 /// is not known if it belongs to the same owner as the original class. In 1549 /// is not known if it belongs to the same owner as the original class. In
1388 /// this case, we create an object whose owner is what the original mirror 1550 /// this case, we create an object whose owner is what the original mirror
1389 /// says it is. 1551 /// says it is.
1390 factory Class._possiblyDifferentOwner(ClassMirror mirror, 1552 factory Class._possiblyDifferentOwner(ClassMirror mirror,
1391 Library originalOwner) { 1553 Library originalOwner) {
(...skipping 21 matching lines...) Expand all
1413 new Class._possiblyDifferentOwner(classMirror.superclass, owner); 1575 new Class._possiblyDifferentOwner(classMirror.superclass, owner);
1414 1576
1415 interfaces = superinterfaces.toList(); 1577 interfaces = superinterfaces.toList();
1416 variables = _createVariables(classMirror.variables, this); 1578 variables = _createVariables(classMirror.variables, this);
1417 methods = _createMethods(classMirror.methods, this); 1579 methods = _createMethods(classMirror.methods, this);
1418 annotations = _createAnnotations(classMirror, _getOwningLibrary(owner)); 1580 annotations = _createAnnotations(classMirror, _getOwningLibrary(owner));
1419 generics = _createGenerics(classMirror); 1581 generics = _createGenerics(classMirror);
1420 isAbstract = classMirror.isAbstract; 1582 isAbstract = classMirror.isAbstract;
1421 inheritedMethods = new Map<String, Method>(); 1583 inheritedMethods = new Map<String, Method>();
1422 1584
1423 // Tell all superclasses that you are a subclass, unless you are not 1585 // Tell superclass that you are a subclass, unless you are not
1424 // visible or an intermediary mixin class. 1586 // visible or an intermediary mixin class.
1425 if (!classMirror.isNameSynthetic && _isVisible) { 1587 if (!classMirror.isNameSynthetic && _isVisible && superclass != null) {
1426 parentChain().forEach((parentClass) { 1588 superclass.addSubclass(this);
1427 parentClass.addSubclass(this);
1428 });
1429 } 1589 }
1430 1590
1431 if (this.superclass != null) addInherited(superclass); 1591 if (this.superclass != null) addInherited(superclass);
1432 interfaces.forEach((interface) => addInherited(interface)); 1592 interfaces.forEach((interface) => addInherited(interface));
1433 } 1593 }
1434 1594
1435 String get packagePrefix => owner.packagePrefix; 1595 String get packagePrefix => owner.packagePrefix;
1436 1596
1437 String _lookupInClassAndSuperclasses(String name) { 1597 String _lookupInClassAndSuperclasses(String name) {
1438 var lookupFunc = Indexable.determineLookupFunc(name); 1598 var lookupFunc = Indexable.determineLookupFunc(name);
(...skipping 13 matching lines...) Expand all
1452 String findElementInScope(String name) { 1612 String findElementInScope(String name) {
1453 var lookupFunc = Indexable.determineLookupFunc(name); 1613 var lookupFunc = Indexable.determineLookupFunc(name);
1454 var result = _lookupInClassAndSuperclasses(name); 1614 var result = _lookupInClassAndSuperclasses(name);
1455 if (result != null) { 1615 if (result != null) {
1456 return result; 1616 return result;
1457 } 1617 }
1458 result = owner.findElementInScope(name); 1618 result = owner.findElementInScope(name);
1459 return result == null ? super.findElementInScope(name) : result; 1619 return result == null ? super.findElementInScope(name) : result;
1460 } 1620 }
1461 1621
1462 markdown.Node fixReferenceWithScope(String name) => fixReference(name);
1463
1464 String get typeName => 'class'; 1622 String get typeName => 'class';
1465 1623
1466 /// Returns a list of all the parent classes.
1467 List<Class> parentChain() {
1468 // TODO(efortuna): Seems like we can get rid of this method.
1469 var parent = superclass == null ? [] : [superclass];
1470 return parent;
1471 }
1472
1473 /// Add all inherited variables and methods from the provided superclass. 1624 /// Add all inherited variables and methods from the provided superclass.
1474 /// If [_includePrivate] is true, it also adds the variables and methods from 1625 /// If [_includePrivate] is true, it also adds the variables and methods from
1475 /// the superclass. 1626 /// the superclass.
1476 void addInherited(Class superclass) { 1627 void addInherited(Class superclass) {
1477 inheritedVariables.addAll(superclass.inheritedVariables); 1628 inheritedVariables.addAll(superclass.inheritedVariables);
1478 inheritedVariables.addAll(_allButStatics(superclass.variables)); 1629 inheritedVariables.addAll(_allButStatics(superclass.variables));
1479 addInheritedMethod(superclass, this); 1630 addInheritedMethod(superclass, this);
1480 } 1631 }
1481 1632
1482 /** [newParent] refers to the actual class is currently using these methods. 1633 /** [newParent] refers to the actual class is currently using these methods.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1570 'qualifiedName': qualifiedName, 1721 'qualifiedName': qualifiedName,
1571 'comment': comment, 1722 'comment': comment,
1572 'isAbstract' : isAbstract, 1723 'isAbstract' : isAbstract,
1573 'superclass': validSuperclass(), 1724 'superclass': validSuperclass(),
1574 'implements': interfaces.where((i) => i._isVisible) 1725 'implements': interfaces.where((i) => i._isVisible)
1575 .map((e) => e.qualifiedName).toList(), 1726 .map((e) => e.qualifiedName).toList(),
1576 'subclass': (subclasses.toList()..sort()) 1727 'subclass': (subclasses.toList()..sort())
1577 .map((x) => x.qualifiedName).toList(), 1728 .map((x) => x.qualifiedName).toList(),
1578 'variables': recurseMap(variables), 1729 'variables': recurseMap(variables),
1579 'inheritedVariables': recurseMap(inheritedVariables), 1730 'inheritedVariables': recurseMap(inheritedVariables),
1580 'methods': expandMethodMap(methods), 1731 'methods': _expandMethodMap(methods),
1581 'inheritedMethods': expandMethodMap(inheritedMethods), 1732 'inheritedMethods': _expandMethodMap(inheritedMethods),
1582 'annotations': annotations.map((a) => a.toMap()).toList(), 1733 'annotations': annotations.map((a) => a.toMap()).toList(),
1583 'generics': recurseMap(generics) 1734 'generics': recurseMap(generics)
1584 }; 1735 };
1585 1736
1586 int compareTo(aClass) => name.compareTo(aClass.name); 1737 int compareTo(aClass) => name.compareTo(aClass.name);
1587 1738
1588 bool _isValidMirror(DeclarationMirror mirror) => mirror is ClassMirror; 1739 bool _isValidMirror(DeclarationMirror mirror) => mirror is ClassMirror;
1589 } 1740 }
1590 1741
1591 class Typedef extends OwnedIndexable { 1742 class Typedef extends OwnedIndexable {
1592 String returnType; 1743 String returnType;
1593 1744
1594 Map<String, Parameter> parameters; 1745 Map<String, Parameter> parameters;
1595 1746
1596 /// Generic information about the typedef. 1747 /// Generic information about the typedef.
1597 Map<String, Generic> generics; 1748 Map<String, Generic> generics;
1598 1749
1599 /// List of the meta annotations on the typedef.
1600 List<Annotation> annotations;
1601
1602 /// Returns the [Library] for the given [mirror] if it has already been 1750 /// Returns the [Library] for the given [mirror] if it has already been
1603 /// created, else creates it. 1751 /// created, else creates it.
1604 factory Typedef(TypedefMirror mirror, Library owningLibrary) { 1752 factory Typedef(TypedefMirror mirror, Library owningLibrary) {
1605 var aTypedef = Indexable.getDocgenObject(mirror, owningLibrary); 1753 var aTypedef = Indexable.getDocgenObject(mirror, owningLibrary);
1606 if (aTypedef is DummyMirror) { 1754 if (aTypedef is DummyMirror) {
1607 aTypedef = new Typedef._(mirror, owningLibrary); 1755 aTypedef = new Typedef._(mirror, owningLibrary);
1608 } 1756 }
1609 return aTypedef; 1757 return aTypedef;
1610 } 1758 }
1611 1759
1612 Typedef._(TypedefMirror mirror, Library owningLibrary) : 1760 Typedef._(TypedefMirror mirror, Library owningLibrary) :
1613 super(mirror, owningLibrary) { 1761 super(mirror, owningLibrary) {
1614 returnType = Indexable.getDocgenObject(mirror.value.returnType).docName; 1762 returnType = Indexable.getDocgenObject(mirror.value.returnType).docName;
1615 generics = _createGenerics(mirror); 1763 generics = _createGenerics(mirror);
1616 parameters = _createParameters(mirror.value.parameters, owningLibrary); 1764 parameters = _createParameters(mirror.value.parameters, owningLibrary);
1617 annotations = _createAnnotations(mirror, owningLibrary); 1765 annotations = _createAnnotations(mirror, owningLibrary);
1618 } 1766 }
1619 1767
1620 Map toMap() => { 1768 Map toMap() => {
1621 'name': name, 1769 'name': name,
1622 'qualifiedName': qualifiedName, 1770 'qualifiedName': qualifiedName,
1623 'comment': comment, 1771 'comment': comment,
1624 'return': returnType, 1772 'return': returnType,
1625 'parameters': recurseMap(parameters), 1773 'parameters': recurseMap(parameters),
1626 'annotations': annotations.map((a) => a.toMap()).toList(), 1774 'annotations': annotations.map((a) => a.toMap()).toList(),
1627 'generics': recurseMap(generics) 1775 'generics': recurseMap(generics)
1628 }; 1776 };
1629 1777
1778 markdown.Node fixReference(String name) => null;
1779
1630 String get typeName => 'typedef'; 1780 String get typeName => 'typedef';
1631 1781
1632 bool _isValidMirror(DeclarationMirror mirror) => mirror is TypedefMirror; 1782 bool _isValidMirror(DeclarationMirror mirror) => mirror is TypedefMirror;
1633 } 1783 }
1634 1784
1635 /// A class containing properties of a Dart variable. 1785 /// A class containing properties of a Dart variable.
1636 class Variable extends OwnedIndexable { 1786 class Variable extends OwnedIndexable {
1637 1787
1638 bool isFinal; 1788 bool isFinal;
1639 bool isStatic; 1789 bool isStatic;
1640 bool isConst; 1790 bool isConst;
1641 Type type; 1791 Type type;
1642 String _variableName; 1792 String _variableName;
1643 1793
1644 /// List of the meta annotations on the variable.
1645 List<Annotation> annotations;
1646
1647 factory Variable(String variableName, VariableMirror mirror, 1794 factory Variable(String variableName, VariableMirror mirror,
1648 Indexable owner) { 1795 Indexable owner) {
1649 var variable = Indexable.getDocgenObject(mirror); 1796 var variable = Indexable.getDocgenObject(mirror);
1650 if (variable is DummyMirror) { 1797 if (variable is DummyMirror) {
1651 return new Variable._(variableName, mirror, owner); 1798 return new Variable._(variableName, mirror, owner);
1652 } 1799 }
1653 return variable; 1800 return variable;
1654 } 1801 }
1655 1802
1656 Variable._(this._variableName, VariableMirror mirror, Indexable owner) : 1803 Variable._(this._variableName, VariableMirror mirror, Indexable owner) :
(...skipping 24 matching lines...) Expand all
1681 String get typeName => 'property'; 1828 String get typeName => 'property';
1682 1829
1683 get comment { 1830 get comment {
1684 if (_comment != null) return _comment; 1831 if (_comment != null) return _comment;
1685 if (owner is Class) { 1832 if (owner is Class) {
1686 (owner as Class).ensureComments(); 1833 (owner as Class).ensureComments();
1687 } 1834 }
1688 return super.comment; 1835 return super.comment;
1689 } 1836 }
1690 1837
1691 markdown.Node fixReferenceWithScope(String name) => fixReference(name);
1692
1693 String findElementInScope(String name) { 1838 String findElementInScope(String name) {
1694 var lookupFunc = Indexable.determineLookupFunc(name); 1839 var lookupFunc = Indexable.determineLookupFunc(name);
1695 var result = lookupFunc(mirror, name); 1840 var result = lookupFunc(mirror, name);
1696 if (result != null) { 1841 if (result != null) {
1697 result = Indexable.getDocgenObject(result); 1842 result = Indexable.getDocgenObject(result);
1698 if (result is DummyMirror) return packagePrefix + result.docName; 1843 if (result is DummyMirror) return packagePrefix + result.docName;
1699 return result.packagePrefix + result.docName; 1844 return result.packagePrefix + result.docName;
1700 } 1845 }
1701 1846
1702 if (owner != null) { 1847 if (owner != null) {
(...skipping 16 matching lines...) Expand all
1719 1864
1720 bool isStatic; 1865 bool isStatic;
1721 bool isAbstract; 1866 bool isAbstract;
1722 bool isConst; 1867 bool isConst;
1723 Type returnType; 1868 Type returnType;
1724 Method methodInheritedFrom; 1869 Method methodInheritedFrom;
1725 1870
1726 /// Qualified name to state where the comment is inherited from. 1871 /// Qualified name to state where the comment is inherited from.
1727 String commentInheritedFrom = ""; 1872 String commentInheritedFrom = "";
1728 1873
1729 /// List of the meta annotations on the method. 1874 factory Method(MethodMirror mirror, Indexable owner,
1730 List<Annotation> annotations;
1731
1732 factory Method(MethodMirror mirror, Indexable owner, // Indexable newOwner.
1733 [Method methodInheritedFrom]) { 1875 [Method methodInheritedFrom]) {
1734 var method = Indexable.getDocgenObject(mirror, owner); 1876 var method = Indexable.getDocgenObject(mirror, owner);
1735 if (method is DummyMirror) { 1877 if (method is DummyMirror) {
1736 method = new Method._(mirror, owner, methodInheritedFrom); 1878 method = new Method._(mirror, owner, methodInheritedFrom);
1737 } 1879 }
1738 return method; 1880 return method;
1739 } 1881 }
1740 1882
1741 Method._(MethodMirror mirror, Indexable owner, this.methodInheritedFrom) 1883 Method._(MethodMirror mirror, Indexable owner, this.methodInheritedFrom)
1742 : super(mirror, owner) { 1884 : super(mirror, owner) {
1743 isStatic = mirror.isStatic; 1885 isStatic = mirror.isStatic;
1744 isAbstract = mirror.isAbstract; 1886 isAbstract = mirror.isAbstract;
1745 isConst = mirror.isConstConstructor; 1887 isConst = mirror.isConstConstructor;
1746 returnType = new Type(mirror.returnType, _getOwningLibrary(owner)); 1888 returnType = new Type(mirror.returnType, _getOwningLibrary(owner));
1747 parameters = _createParameters(mirror.parameters, owner); 1889 parameters = _createParameters(mirror.parameters, owner);
1748 annotations = _createAnnotations(mirror, _getOwningLibrary(owner)); 1890 annotations = _createAnnotations(mirror, _getOwningLibrary(owner));
1749 } 1891 }
1750 1892
1751 String get packagePrefix => owner.packagePrefix; 1893 String get packagePrefix => owner.packagePrefix;
1752 1894
1753 Method get originallyInheritedFrom => methodInheritedFrom == null ? 1895 Method get originallyInheritedFrom => methodInheritedFrom == null ?
1754 this : methodInheritedFrom.originallyInheritedFrom; 1896 this : methodInheritedFrom.originallyInheritedFrom;
1755 1897
1756 markdown.Node fixReferenceWithScope(String name) => fixReference(name);
1757
1758 /// Look for the specified name starting with the current member, and 1898 /// Look for the specified name starting with the current member, and
1759 /// progressively working outward to the current library scope. 1899 /// progressively working outward to the current library scope.
1760 String findElementInScope(String name) { 1900 String findElementInScope(String name) {
1761 var lookupFunc = Indexable.determineLookupFunc(name); 1901 var lookupFunc = Indexable.determineLookupFunc(name);
1762 1902
1763 var memberScope = lookupFunc(this.mirror, name); 1903 var memberScope = lookupFunc(this.mirror, name);
1764 if (memberScope != null) { 1904 if (memberScope != null) {
1765 // do we check for a dummy mirror returned here and look up with an owner 1905 // do we check for a dummy mirror returned here and look up with an owner
1766 // higher ooooor in getDocgenObject do we include more things in our 1906 // higher ooooor in getDocgenObject do we include more things in our
1767 // lookup 1907 // lookup
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1831 return 'method'; 1971 return 'method';
1832 } 1972 }
1833 1973
1834 get comment { 1974 get comment {
1835 if (_comment != null) return _comment; 1975 if (_comment != null) return _comment;
1836 if (owner is Class) { 1976 if (owner is Class) {
1837 (owner as Class).ensureComments(); 1977 (owner as Class).ensureComments();
1838 } 1978 }
1839 var result = super.comment; 1979 var result = super.comment;
1840 if (result == '' && methodInheritedFrom != null) { 1980 if (result == '' && methodInheritedFrom != null) {
1841 // this should be NOT from the MIRROR, but from the COMMENT 1981 // This should be NOT from the MIRROR, but from the COMMENT.
1982 methodInheritedFrom.comment; // Ensure comment field has been populated.
1842 _unresolvedComment = methodInheritedFrom._unresolvedComment; 1983 _unresolvedComment = methodInheritedFrom._unresolvedComment;
1843 1984
1844 var linkResolver = (name) => fixReferenceWithScope(name); 1985 var linkResolver = (name) => fixReference(name);
1845 comment = _unresolvedComment == null ? '' : 1986 comment = _unresolvedComment == null ? '' :
1846 markdown.markdownToHtml(_unresolvedComment.trim(), 1987 markdown.markdownToHtml(_unresolvedComment.trim(),
1847 linkResolver: linkResolver, inlineSyntaxes: _MARKDOWN_SYNTAXES); 1988 linkResolver: linkResolver, inlineSyntaxes: _MARKDOWN_SYNTAXES);
1848 commentInheritedFrom = methodInheritedFrom.commentInheritedFrom; 1989 commentInheritedFrom = comment != '' ?
1990 methodInheritedFrom.commentInheritedFrom : '';
1849 result = comment; 1991 result = comment;
1850 } 1992 }
1851 return result; 1993 return result;
1852 } 1994 }
1853 1995
1854 bool _isValidMirror(DeclarationMirror mirror) => mirror is MethodMirror; 1996 bool _isValidMirror(DeclarationMirror mirror) => mirror is MethodMirror;
1855 } 1997 }
1856 1998
1857 /// Docgen wrapper around the dart2js mirror for a Dart 1999 /// Docgen wrapper around the dart2js mirror for a Dart
1858 /// method/function parameter. 2000 /// method/function parameter.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 .map((e) => originalMirror.getField(e.simpleName).reflectee) 2113 .map((e) => originalMirror.getField(e.simpleName).reflectee)
1972 .where((e) => e != null) 2114 .where((e) => e != null)
1973 .toList(); 2115 .toList();
1974 } 2116 }
1975 2117
1976 Map toMap() => { 2118 Map toMap() => {
1977 'name': Indexable.getDocgenObject(mirror, owningLibrary).docName, 2119 'name': Indexable.getDocgenObject(mirror, owningLibrary).docName,
1978 'parameters': parameters 2120 'parameters': parameters
1979 }; 2121 };
1980 } 2122 }
OLDNEW
« no previous file with comments | « pkg/docgen/bin/docgen.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698