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

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

Issue 73113002: Generate docgen output along with api_docs as part of the build (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Changed where it's trying to upload to Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/docgen/doc/sdk-introduction.md ('k') | tools/bots/pub.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// **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 18 matching lines...) Expand all
29 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirro r.dart' 29 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirro r.dart'
30 as dart2js; 30 as dart2js;
31 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart' ; 31 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart' ;
32 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util. dart' 32 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util. dart'
33 as dart2js_util; 33 as dart2js_util;
34 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider. dart'; 34 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider. dart';
35 import '../../../sdk/lib/_internal/libraries.dart'; 35 import '../../../sdk/lib/_internal/libraries.dart';
36 36
37 var logger = new Logger('Docgen'); 37 var logger = new Logger('Docgen');
38 38
39 const DEFAULT_OUTPUT_DIRECTORY = 'docs';
40
41 var _outputDirectory;
42
39 const String USAGE = 'Usage: dart docgen.dart [OPTIONS] fooDir/barFile'; 43 const String USAGE = 'Usage: dart docgen.dart [OPTIONS] fooDir/barFile';
40 44
41 45
42 List<String> skippedAnnotations = const [ 46 List<String> skippedAnnotations = const [
43 'metadata.DocsEditable', '_js_helper.JSName', '_js_helper.Creates', 47 'metadata.DocsEditable', '_js_helper.JSName', '_js_helper.Creates',
44 '_js_helper.Returns']; 48 '_js_helper.Returns'];
45 49
46 /// Set of libraries declared in the SDK, so libraries that can be accessed 50 /// Set of libraries declared in the SDK, so libraries that can be accessed
47 /// when running dart by default. 51 /// when running dart by default.
48 Iterable<LibraryMirror> _sdkLibraries; 52 Iterable<LibraryMirror> _sdkLibraries;
49 53
50 /// The dart:core library, which contains all types that are always available 54 /// The dart:core library, which contains all types that are always available
51 /// without import. 55 /// without import.
52 LibraryMirror _coreLibrary; 56 LibraryMirror _coreLibrary;
53 57
54 /// Support for [:foo:]-style code comments to the markdown parser. 58 /// Support for [:foo:]-style code comments to the markdown parser.
55 List<markdown.InlineSyntax> markdownSyntaxes = 59 List<markdown.InlineSyntax> markdownSyntaxes =
56 [new markdown.CodeSyntax(r'\[:\s?((?:.|\n)*?)\s?:\]')]; 60 [new markdown.CodeSyntax(r'\[:\s?((?:.|\n)*?)\s?:\]')];
57 61
58 /// Index of all indexable items. This also ensures that no class is 62 /// Index of all indexable items. This also ensures that no class is
59 /// created more than once. 63 /// created more than once.
60 Map<String, Indexable> entityMap = new Map<String, Indexable>(); 64 Map<String, Indexable> entityMap = new Map<String, Indexable>();
61 65
62 /// This is set from the command line arguments flag --include-private 66 /// This is set from the command line arguments flag --include-private
63 bool _includePrivate = false; 67 bool _includePrivate = false;
64 68
69 /// Library names to explicitly exclude.
70 ///
71 /// Set from the command line option
72 /// --exclude-lib.
73 List<String> _excluded;
74
65 // TODO(janicejl): Make MDN content generic or pluggable. Maybe move 75 // TODO(janicejl): Make MDN content generic or pluggable. Maybe move
66 // MDN-specific code to its own library that is imported into the default impl? 76 // MDN-specific code to its own library that is imported into the default impl?
67 /// Map of all the comments for dom elements from MDN. 77 /// Map of all the comments for dom elements from MDN.
68 Map _mdn; 78 Map _mdn;
69 79
70 /// Docgen constructor initializes the link resolver for markdown parsing. 80 /// Docgen constructor initializes the link resolver for markdown parsing.
71 /// Also initializes the command line arguments. 81 /// Also initializes the command line arguments.
72 /// 82 ///
73 /// [packageRoot] is the packages directory of the directory being analyzed. 83 /// [packageRoot] is the packages directory of the directory being analyzed.
74 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will 84 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will
75 /// also be documented. 85 /// also be documented.
76 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. 86 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented.
77 /// This option is useful when only the SDK libraries are needed. 87 /// This option is useful when only the SDK libraries are needed.
78 /// 88 ///
79 /// Returned Future completes with true if document generation is successful. 89 /// Returned Future completes with true if document generation is successful.
80 Future<bool> docgen(List<String> files, {String packageRoot, 90 Future<bool> docgen(List<String> files, {String packageRoot,
81 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, 91 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false,
82 bool parseSdk: false, bool append: false, String introduction: ''}) { 92 bool parseSdk: false, bool append: false, String introduction: '',
93 out: DEFAULT_OUTPUT_DIRECTORY, List<String> excludeLibraries}) {
94 _excluded = excludeLibraries;
83 _includePrivate = includePrivate; 95 _includePrivate = includePrivate;
96 _outputDirectory = out;
84 if (!append) { 97 if (!append) {
85 var dir = new Directory('docs'); 98 var dir = new Directory(_outputDirectory);
86 if (dir.existsSync()) dir.deleteSync(recursive: true); 99 if (dir.existsSync()) dir.deleteSync(recursive: true);
87 } 100 }
88 101
89 if (packageRoot == null && !parseSdk) { 102 if (packageRoot == null && !parseSdk) {
90 var type = FileSystemEntity.typeSync(files.first); 103 var type = FileSystemEntity.typeSync(files.first);
91 if (type == FileSystemEntityType.DIRECTORY) { 104 if (type == FileSystemEntityType.DIRECTORY) {
92 packageRoot = _findPackageRoot(files.first); 105 packageRoot = _findPackageRoot(files.first);
93 } else if (type == FileSystemEntityType.FILE) { 106 } else if (type == FileSystemEntityType.FILE) {
94 logger.warning('WARNING: No package root defined. If Docgen fails, try ' 107 logger.warning('WARNING: No package root defined. If Docgen fails, try '
95 'again by setting the --package-root option.'); 108 'again by setting the --package-root option.');
96 } 109 }
97 } 110 }
98 logger.info('Package Root: ${packageRoot}'); 111 logger.info('Package Root: ${packageRoot}');
112 var requestedLibraries = _listLibraries(files);
113 var allLibraries = []..addAll(requestedLibraries);
114 if (includeSdk) {
115 allLibraries.addAll(_listSdk());
116 }
99 117
100 return getMirrorSystem(files, packageRoot: packageRoot, parseSdk: parseSdk) 118 return getMirrorSystem(allLibraries, packageRoot: packageRoot,
119 parseSdk: parseSdk)
101 .then((MirrorSystem mirrorSystem) { 120 .then((MirrorSystem mirrorSystem) {
102 if (mirrorSystem.libraries.isEmpty) { 121 if (mirrorSystem.libraries.isEmpty) {
103 throw new StateError('No library mirrors were created.'); 122 throw new StateError('No library mirrors were created.');
104 } 123 }
105 var librariesWeAskedFor = _listLibraries(files); 124 var availableLibraries = mirrorSystem.libraries.values.where(
106 var librariesWeGot = mirrorSystem.libraries.values.where(
107 (each) => each.uri.scheme == 'file'); 125 (each) => each.uri.scheme == 'file');
108 _sdkLibraries = mirrorSystem.libraries.values.where( 126 _sdkLibraries = mirrorSystem.libraries.values.where(
109 (each) => each.uri.scheme == 'dart'); 127 (each) => each.uri.scheme == 'dart');
110 _coreLibrary = _sdkLibraries.singleWhere((lib) => 128 _coreLibrary = _sdkLibraries.singleWhere((lib) =>
111 lib.uri.toString().startsWith('dart:core')); 129 lib.uri.toString().startsWith('dart:core'));
112 var librariesWeGotByPath = new Map.fromIterables( 130 var availableLibrariesByPath = new Map.fromIterables(
113 librariesWeGot.map((each) => each.uri.toFilePath()), 131 availableLibraries.map((each) => each.uri.toFilePath()),
114 librariesWeGot); 132 availableLibraries);
115 var librariesToDocument = librariesWeAskedFor.map( 133 var librariesToDocument = requestedLibraries.map(
116 (each) => librariesWeGotByPath.putIfAbsent(each, 134 (each) => availableLibrariesByPath.putIfAbsent(each,
117 () => throw "Missing library $each")).toList(); 135 () => throw "Missing library $each")).toList();
118 librariesToDocument.addAll((includeSdk || parseSdk) ? _sdkLibraries : []); 136 librariesToDocument.addAll((includeSdk || parseSdk) ? _sdkLibraries : []);
137 librariesToDocument.removeWhere((x) => _excluded.contains(x.simpleName));
119 _documentLibraries(librariesToDocument, includeSdk: includeSdk, 138 _documentLibraries(librariesToDocument, includeSdk: includeSdk,
120 outputToYaml: outputToYaml, append: append, parseSdk: parseSdk, 139 outputToYaml: outputToYaml, append: append, parseSdk: parseSdk,
121 introduction: introduction); 140 introduction: introduction);
122 return true; 141 return true;
123 }); 142 });
124 } 143 }
125 144
126 /// For a library's [mirror], determine the name of the package (if any) we 145 /// For a library's [mirror], determine the name of the package (if any) we
127 /// believe it came from (because of its file URI). 146 /// believe it came from (because of its file URI).
128 /// 147 ///
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 // Only add the file if it does not contain 'part of' 221 // Only add the file if it does not contain 'part of'
203 // TODO(janicejl): Remove when Issue(12406) is resolved. 222 // TODO(janicejl): Remove when Issue(12406) is resolved.
204 var contents = new File(f).readAsStringSync(); 223 var contents = new File(f).readAsStringSync();
205 if (!(contents.contains(new RegExp('\npart of ')) || 224 if (!(contents.contains(new RegExp('\npart of ')) ||
206 contents.startsWith(new RegExp('part of ')))) { 225 contents.startsWith(new RegExp('part of ')))) {
207 libraries.add(f); 226 libraries.add(f);
208 logger.info('Added to libraries: $f'); 227 logger.info('Added to libraries: $f');
209 } 228 }
210 } 229 }
211 }); 230 });
212 return libraries; 231 return libraries.map(path.absolute).map(path.normalize).toList();
213 } 232 }
214 233
215 String _findPackageRoot(String directory) { 234 String _findPackageRoot(String directory) {
216 var files = listDir(directory, recursive: true); 235 var files = listDir(directory, recursive: true);
217 // Return '' means that there was no pubspec.yaml and therefor no packageRoot. 236 // Return '' means that there was no pubspec.yaml and therefor no packageRoot.
218 String packageRoot = files.firstWhere((f) => 237 String packageRoot = files.firstWhere((f) =>
219 f.endsWith('${path.separator}pubspec.yaml'), orElse: () => ''); 238 f.endsWith('${path.separator}pubspec.yaml'), orElse: () => '');
220 if (packageRoot != '') { 239 if (packageRoot != '') {
221 packageRoot = path.join(path.dirname(packageRoot), 'packages'); 240 packageRoot = path.join(path.dirname(packageRoot), 'packages');
222 } 241 }
(...skipping 15 matching lines...) Expand all
238 if (info.documented) { 257 if (info.documented) {
239 sdk.add('dart:$name'); 258 sdk.add('dart:$name');
240 logger.info('Add to SDK: ${sdk.last}'); 259 logger.info('Add to SDK: ${sdk.last}');
241 } 260 }
242 }); 261 });
243 return sdk; 262 return sdk;
244 } 263 }
245 264
246 /// Analyzes set of libraries by getting a mirror system and triggers the 265 /// Analyzes set of libraries by getting a mirror system and triggers the
247 /// documentation of the libraries. 266 /// documentation of the libraries.
248 Future<MirrorSystem> getMirrorSystem(List<String> args, {String packageRoot, 267 Future<MirrorSystem> getMirrorSystem(List<String> libraries,
249 bool parseSdk: false}) { 268 {String packageRoot, bool parseSdk: false}) {
250 var libraries = !parseSdk ? _listLibraries(args) : _listSdk();
251 if (libraries.isEmpty) throw new StateError('No Libraries.'); 269 if (libraries.isEmpty) throw new StateError('No Libraries.');
252 // Finds the root of SDK library based off the location of docgen. 270 // Finds the root of SDK library based off the location of docgen.
253 271
254 var root = findRootDirectory(); 272 var root = findRootDirectory();
255 var sdkRoot = path.normalize(path.absolute(path.join(root, 'sdk'))); 273 var sdkRoot = path.normalize(path.absolute(path.join(root, 'sdk')));
256 logger.info('SDK Root: ${sdkRoot}'); 274 logger.info('SDK Root: ${sdkRoot}');
257 return _analyzeLibraries(libraries, sdkRoot, packageRoot: packageRoot); 275 return _analyzeLibraries(libraries, sdkRoot, packageRoot: packageRoot);
258 } 276 }
259 277
260 String findRootDirectory() { 278 String findRootDirectory() {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 // giant list of subclasses to be printed out. 334 // giant list of subclasses to be printed out.
317 if (includeSdk) (entityMap['dart-core.Object'] as Class).subclasses.clear(); 335 if (includeSdk) (entityMap['dart-core.Object'] as Class).subclasses.clear();
318 336
319 var filteredEntities = entityMap.values.where(_isVisible); 337 var filteredEntities = entityMap.values.where(_isVisible);
320 338
321 // Outputs a JSON file with all libraries and their preview comments. 339 // Outputs a JSON file with all libraries and their preview comments.
322 // This will help the viewer know what libraries are available to read in. 340 // This will help the viewer know what libraries are available to read in.
323 var libraryMap; 341 var libraryMap;
324 var linkResolver = (name) => fixReference(name, null, null, null); 342 var linkResolver = (name) => fixReference(name, null, null, null);
325 if (append) { 343 if (append) {
326 var docsDir = listDir('docs'); 344 var docsDir = listDir(_outputDirectory);
327 if (!docsDir.contains('docs/library_list.json')) { 345 if (!docsDir.contains('$_outputDirectory/library_list.json')) {
328 throw new StateError('No library_list.json'); 346 throw new StateError('No library_list.json');
329 } 347 }
330 libraryMap = 348 libraryMap =
331 JSON.decode(new File('docs/library_list.json').readAsStringSync()); 349 JSON.decode(new File('$_outputDirectory/library_list.json').readAsString Sync());
332 libraryMap['libraries'].addAll(filteredEntities 350 libraryMap['libraries'].addAll(filteredEntities
333 .where((e) => e is Library) 351 .where((e) => e is Library)
334 .map((e) => e.previewMap)); 352 .map((e) => e.previewMap));
335 if (introduction.isNotEmpty) { 353 if (introduction.isNotEmpty) {
336 var intro = libraryMap['introduction']; 354 var intro = libraryMap['introduction'];
337 if (intro.isNotEmpty) intro += '<br/><br/>'; 355 if (intro.isNotEmpty) intro += '<br/><br/>';
338 intro += markdown.markdownToHtml( 356 intro += markdown.markdownToHtml(
339 new File(introduction).readAsStringSync(), 357 new File(introduction).readAsStringSync(),
340 linkResolver: linkResolver, inlineSyntaxes: markdownSyntaxes); 358 linkResolver: linkResolver, inlineSyntaxes: markdownSyntaxes);
341 libraryMap['introduction'] = intro; 359 libraryMap['introduction'] = intro;
(...skipping 20 matching lines...) Expand all
362 // Outputs all the qualified names documented with their type. 380 // Outputs all the qualified names documented with their type.
363 // This will help generate search results. 381 // This will help generate search results.
364 _writeToFile(filteredEntities.map((e) => 382 _writeToFile(filteredEntities.map((e) =>
365 '${e.qualifiedName} ${e.typeName}').join('\n') + '\n', 383 '${e.qualifiedName} ${e.typeName}').join('\n') + '\n',
366 'index.txt', append: append); 384 'index.txt', append: append);
367 var index = new Map.fromIterables( 385 var index = new Map.fromIterables(
368 filteredEntities.map((e) => e.qualifiedName), 386 filteredEntities.map((e) => e.qualifiedName),
369 filteredEntities.map((e) => e.typeName)); 387 filteredEntities.map((e) => e.typeName));
370 if (append) { 388 if (append) {
371 var previousIndex = 389 var previousIndex =
372 JSON.decode(new File('docs/index.json').readAsStringSync()); 390 JSON.decode(new File('$_outputDirectory/index.json').readAsStringSync()) ;
373 index.addAll(previousIndex); 391 index.addAll(previousIndex);
374 } 392 }
375 _writeToFile(JSON.encode(index), 'index.json'); 393 _writeToFile(JSON.encode(index), 'index.json');
376 } 394 }
377 395
378 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { 396 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) {
379 var result = new Library(docName(library), 397 var result = new Library(docName(library),
380 (actualLibrary) => _commentToHtml(library, actualLibrary), 398 (actualLibrary) => _commentToHtml(library, actualLibrary),
381 _classes(library.classes), 399 _classes(library.classes),
382 _methods(library.functions), 400 _methods(library.functions),
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 if (mirror is ClassMirror && !mirror.isTypedef) { 782 if (mirror is ClassMirror && !mirror.isTypedef) {
765 var innerList = []; 783 var innerList = [];
766 mirror.typeArguments.forEach((e) { 784 mirror.typeArguments.forEach((e) {
767 innerList.add(new Type(docName(e), _typeGenerics(e))); 785 innerList.add(new Type(docName(e), _typeGenerics(e)));
768 }); 786 });
769 return innerList; 787 return innerList;
770 } 788 }
771 return []; 789 return [];
772 } 790 }
773 791
774 /// Writes text to a file in the 'docs' directory. 792 /// Writes text to a file in the output directory.
775 void _writeToFile(String text, String filename, {bool append: false}) { 793 void _writeToFile(String text, String filename, {bool append: false}) {
776 Directory dir = new Directory('docs'); 794 if (text == null) return;
795 Directory dir = new Directory(_outputDirectory);
777 if (!dir.existsSync()) { 796 if (!dir.existsSync()) {
778 dir.createSync(); 797 dir.createSync();
779 } 798 }
780 // We assume there's a single extra level of directory structure for packages. 799 // We assume there's a single extra level of directory structure for packages.
781 if (path.split(filename).length > 1) { 800 if (path.split(filename).length > 1) {
782 var subdir = new Directory(path.join('docs', path.dirname(filename))); 801 var subdir = new Directory(path.join(_outputDirectory, path.dirname(filename )));
783 if (!subdir.existsSync()) { 802 if (!subdir.existsSync()) {
784 subdir.createSync(); 803 subdir.createSync();
785 } 804 }
786 } 805 }
787 806 File file = new File(path.join(_outputDirectory, filename));
788 File file = new File('docs/$filename');
789 if (!file.existsSync()) {
790 file.createSync();
791 }
792 file.writeAsStringSync(text, mode: append ? FileMode.APPEND : FileMode.WRITE); 807 file.writeAsStringSync(text, mode: append ? FileMode.APPEND : FileMode.WRITE);
793 } 808 }
794 809
795 /// Transforms the map by calling toMap on each value in it. 810 /// Transforms the map by calling toMap on each value in it.
796 Map recurseMap(Map inputMap) { 811 Map recurseMap(Map inputMap) {
797 var outputMap = {}; 812 var outputMap = {};
798 inputMap.forEach((key, value) { 813 inputMap.forEach((key, value) {
799 if (value is Map) { 814 if (value is Map) {
800 outputMap[key] = recurseMap(value); 815 outputMap[key] = recurseMap(value);
801 } else { 816 } else {
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 /// Remove statics from the map of inherited items before adding them. 1449 /// Remove statics from the map of inherited items before adding them.
1435 Map _filterStatics(Map items) { 1450 Map _filterStatics(Map items) {
1436 var result = {}; 1451 var result = {};
1437 items.forEach((name, item) { 1452 items.forEach((name, item) {
1438 if (!item.isStatic) { 1453 if (!item.isStatic) {
1439 result[name] = item; 1454 result[name] = item;
1440 } 1455 }
1441 }); 1456 });
1442 return result; 1457 return result;
1443 } 1458 }
OLDNEW
« no previous file with comments | « pkg/docgen/doc/sdk-introduction.md ('k') | tools/bots/pub.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698