| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// **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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |