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

Side by Side Diff: lib/dartdoc/dartdoc.dart

Issue 10809035: Several new features and improvements for dartdoc. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * To generate docs for a library, run this script with the path to an 6 * To generate docs for a library, run this script with the path to an
7 * entrypoint .dart file, like: 7 * entrypoint .dart file, like:
8 * 8 *
9 * $ dart dartdoc.dart foo.dart 9 * $ dart dartdoc.dart foo.dart
10 * 10 *
11 * This will create a "docs" directory with the docs for your libraries. To 11 * This will create a "docs" directory with the docs for your libraries. To
12 * create these beautiful docs, dartdoc parses your library and every library 12 * create these beautiful docs, dartdoc parses your library and every library
13 * it imports (recursively). From each library, it parses all classes and 13 * it imports (recursively). From each library, it parses all classes and
14 * members, finds the associated doc comments and builds crosslinked docs from 14 * members, finds the associated doc comments and builds crosslinked docs from
15 * them. 15 * them.
16 */ 16 */
17 #library('dartdoc'); 17 #library('dartdoc');
18 18
19 #import('dart:io'); 19 #import('dart:io');
20 #import('dart:uri'); 20 #import('dart:uri');
21 #import('dart:json'); 21 #import('dart:json');
22 #import('mirrors/mirrors.dart'); 22 #import('mirrors/mirrors.dart');
23 #import('mirrors/mirrors_util.dart'); 23 #import('mirrors/mirrors_util.dart');
24 #import('mirrors/dart2js_mirror.dart', prefix: 'dart2js'); 24 #import('mirrors/dart2js_mirror.dart', prefix: 'dart2js');
25 #import('classify.dart'); 25 #import('classify.dart');
26 #import('markdown.dart', prefix: 'md'); 26 #import('markdown.dart', prefix: 'md');
27 #import('../compiler/implementation/scanner/scannerlib.dart', 27 #import('../compiler/implementation/scanner/scannerlib.dart',
28 prefix: 'dart2js'); 28 prefix: 'dart2js');
29 #import('../compiler/implementation/library_map.dart');
29 30
30 #source('comment_map.dart'); 31 #source('comment_map.dart');
31 #source('utils.dart'); 32 #source('utils.dart');
32 33
33 // TODO(johnniwinther): Note that [IN_SDK] gets initialized to true when this 34 // TODO(johnniwinther): Note that [IN_SDK] gets initialized to true when this
34 // file is modified by the SDK deployment script. If you change, be sure to test 35 // file is modified by the SDK deployment script. If you change, be sure to test
35 // that dartdoc still works when run from the built SDK directory. 36 // that dartdoc still works when run from the built SDK directory.
36 final bool IN_SDK = false; 37 final bool IN_SDK = false;
37 38
38 /** 39 /**
(...skipping 10 matching lines...) Expand all
49 * 50 *
50 * This dramatically reduces the generated size of the HTML since a large 51 * This dramatically reduces the generated size of the HTML since a large
51 * fraction of each static page is just redundant navigation links. 52 * fraction of each static page is just redundant navigation links.
52 * 53 *
53 * In this mode, the browser will do a XHR for nav.json which means that to 54 * In this mode, the browser will do a XHR for nav.json which means that to
54 * preview docs locally, you will need to enable requesting file:// links in 55 * preview docs locally, you will need to enable requesting file:// links in
55 * your browser or run a little local server like `python -m SimpleHTTPServer`. 56 * your browser or run a little local server like `python -m SimpleHTTPServer`.
56 */ 57 */
57 final MODE_LIVE_NAV = 1; 58 final MODE_LIVE_NAV = 1;
58 59
60 final API_LOCATION = 'http://api.dartlang.org/';
61
59 /** 62 /**
60 * Run this from the `lib/dartdoc` directory. 63 * Run this from the `lib/dartdoc` directory.
61 */ 64 */
62 void main() { 65 void main() {
63 final args = new Options().arguments; 66 final args = new Options().arguments;
64 67
65 // Parse the dartdoc options. 68 final dartdoc = new Dartdoc();
66 bool includeSource;
67 int mode;
68 Path outputDir;
69 bool generateAppCache;
70 bool omitGenerationTime;
71 bool verbose;
72 69
73 if (args.isEmpty()) { 70 if (args.isEmpty()) {
74 print('No arguments provided.'); 71 print('No arguments provided.');
75 printUsage(); 72 printUsage();
76 return; 73 return;
77 } 74 }
78 75
79 for (int i = 0; i < args.length - 1; i++) { 76 List<Path> entrypoints = new List<Path>();
Bob Nystrom 2012/07/23 17:04:31 final entrypoints = <Path>[];
Johnni Winther 2012/07/24 08:49:16 Done.
77
78 var i = 0;
79 while (i < args.length) {
80 final arg = args[i]; 80 final arg = args[i];
81 if (!arg.startsWith('--')) {
82 // The remaining arguments must be entry points.
83 break;
84 }
81 85
82 switch (arg) { 86 switch (arg) {
83 case '--no-code': 87 case '--no-code':
84 includeSource = false; 88 dartdoc.includeSource = false;
85 break; 89 break;
86 90
87 case '--mode=static': 91 case '--mode=static':
88 mode = MODE_STATIC; 92 dartdoc.mode = MODE_STATIC;
89 break; 93 break;
90 94
91 case '--mode=live-nav': 95 case '--mode=live-nav':
92 mode = MODE_LIVE_NAV; 96 dartdoc.mode = MODE_LIVE_NAV;
93 break; 97 break;
94 98
95 case '--generate-app-cache': 99 case '--generate-app-cache':
96 case '--generate-app-cache=true': 100 case '--generate-app-cache=true':
97 generateAppCache = true; 101 dartdoc.generateAppCache = true;
98 break; 102 break;
99 103
100 case '--omit-generation-time': 104 case '--omit-generation-time':
101 omitGenerationTime = true; 105 dartdoc.omitGenerationTime = true;
102 break; 106 break;
103 case '--verbose': 107 case '--verbose':
104 verbose = true; 108 dartdoc.verbose = true;
109 break;
110 case '--include-api':
111 dartdoc.includeAPI = true;
Bob Nystrom 2012/07/23 17:04:31 Should be "includeApi".
Johnni Winther 2012/07/24 08:49:16 Done.
112 break;
113 case '--link-api':
114 dartdoc.linkToApi = true;
105 break; 115 break;
106 116
107 default: 117 default:
108 if (arg.startsWith('--out=')) { 118 if (arg.startsWith('--out=')) {
109 outputDir = new Path.fromNative(arg.substring('--out='.length)); 119 dartdoc.outputDir =
120 new Path.fromNative(arg.substring('--out='.length));
121 } else if (arg.startsWith('--include-lib=')) {
122 dartdoc.includeLibraries =
123 arg.substring('--include-lib='.length).split(',');
124 } else if (arg.startsWith('--exclude-lib=')) {
125 dartdoc.excludeLibraries =
126 arg.substring('--exclude-lib='.length).split(',');
110 } else { 127 } else {
111 print('Unknown option: $arg'); 128 print('Unknown option: $arg');
112 printUsage(); 129 printUsage();
113 return; 130 return;
114 } 131 }
115 break; 132 break;
116 } 133 }
134 i++;
135 }
136 while (i < args.length) {
137 final arg = args[i];
138 entrypoints.add(new Path.fromNative(arg));
139 i++;
117 } 140 }
118 141
119 final entrypoint = new Path.fromNative(args[args.length - 1]); 142 if (entrypoints.isEmpty()) {
120 143 print('No entrypoints provided.');
121 final dartdoc = new Dartdoc(); 144 printUsage();
122 145 return;
123 if (includeSource != null) dartdoc.includeSource = includeSource;
124 if (mode != null) dartdoc.mode = mode;
125 if (outputDir != null) dartdoc.outputDir = outputDir;
126 if (generateAppCache != null) dartdoc.generateAppCache = generateAppCache;
127 if (omitGenerationTime != null) {
128 dartdoc.omitGenerationTime = omitGenerationTime;
129 } 146 }
130 if (verbose != null) dartdoc.verbose = verbose;
131 147
132 cleanOutputDirectory(dartdoc.outputDir); 148 cleanOutputDirectory(dartdoc.outputDir);
133 149
134 dartdoc.documentEntryPoint(entrypoint, libPath); 150 dartdoc.documentLibraries(entrypoints, libPath);
135 151
136 // Compile the client-side code to JS. 152 // Compile the client-side code to JS.
137 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav'; 153 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav';
138 Future compiled = compileScript( 154 Future compiled = compileScript(
139 scriptDir.append('client-$clientScript.dart'), 155 scriptDir.append('client-$clientScript.dart'),
140 dartdoc.outputDir.append('client-$clientScript.js')); 156 dartdoc.outputDir.append('client-$clientScript.js'));
141 157
142 Future filesCopied = copyDirectory(scriptDir.append('static'), 158 Future filesCopied = copyDirectory(scriptDir.append('static'),
143 dartdoc.outputDir); 159 dartdoc.outputDir);
144 160
145 Futures.wait([compiled, filesCopied]).then((_) { 161 Futures.wait([compiled, filesCopied]).then((_) {
146 print('Documented ${dartdoc._totalLibraries} libraries, ' 162 print('Documented ${dartdoc._totalLibraries} libraries, '
147 '${dartdoc._totalTypes} types, and ' 163 '${dartdoc._totalTypes} types, and '
148 '${dartdoc._totalMembers} members.'); 164 '${dartdoc._totalMembers} members.');
149 }); 165 });
150 } 166 }
151 167
152 void printUsage() { 168 void printUsage() {
153 print(''' 169 print('''
154 Usage dartdoc [options] <entrypoint> 170 Usage dartdoc [options] <entrypoint(s)>
155 [options] include 171 [options] include
156 --no-code Do not include source code in the documentation. 172 --no-code Do not include source code in the documentation.
157 173
158 --mode=static Generates completely static HTML containing 174 --mode=static Generates completely static HTML containing
159 everything you need to browse the docs. The only 175 everything you need to browse the docs. The only
160 client side behavior is trivial stuff like syntax 176 client side behavior is trivial stuff like syntax
161 highlighting code. 177 highlighting code.
162 178
163 --mode=live-nav (default) Generated docs do not include baked HTML 179 --mode=live-nav (default) Generated docs do not include baked HTML
164 navigation. Instead, a single `nav.json` file is 180 navigation. Instead, a single `nav.json` file is
165 created and the appropriate navigation is generated 181 created and the appropriate navigation is generated
166 client-side by parsing that and building HTML. 182 client-side by parsing that and building HTML.
167 This dramatically reduces the generated size of 183 This dramatically reduces the generated size of
168 the HTML since a large fraction of each static page 184 the HTML since a large fraction of each static page
169 is just redundant navigation links. 185 is just redundant navigation links.
170 In this mode, the browser will do a XHR for 186 In this mode, the browser will do a XHR for
171 nav.json which means that to preview docs locally, 187 nav.json which means that to preview docs locally,
172 you will need to enable requesting file:// links in 188 you will need to enable requesting file:// links in
173 your browser or run a little local server like 189 your browser or run a little local server like
174 `python -m SimpleHTTPServer`. 190 `python -m SimpleHTTPServer`.
175 191
176 --generate-app-cache Generates the App Cache manifest file, enabling 192 --generate-app-cache Generates the App Cache manifest file, enabling
177 offline doc viewing. 193 offline doc viewing.
178 194
179 --out=<dir> Generates files into directory <dir>. If omitted 195 --out=<dir> Generates files into directory <dir>. If omitted
180 the files are generated into ./docs/ 196 the files are generated into ./docs/
181 197
198 --link-api Link to the online language API in the generated
199 documentation. The option overrides inclusion
200 through --include-api or --include-lib.
201
202 --include-api Include the used API libraries in the generated
203 documentation. If the --link-api option is used,
204 this option is ignored.
205
206 --include-lib=<libs> Use this option to explicitly specify which
207 libraries to include in the documentation. If
208 omitted, all used libraries are included by
209 default. <libs> is comma-separated list of library
210 names.
211
212 --exclude-lib=<libs> Use this option to explicitly specify which
213 libraries to exclude from the documentation. If
214 omitted, no libraries are excluded. <libs> is
215 comma-separated list of library names.
216
182 --verbose Print verbose information during generation. 217 --verbose Print verbose information during generation.
183 '''); 218 ''');
184 } 219 }
185 220
186 /** 221 /**
187 * Gets the full path to the directory containing the entrypoint of the current 222 * Gets the full path to the directory containing the entrypoint of the current
188 * script. In other words, if you invoked dartdoc, directly, it will be the 223 * script. In other words, if you invoked dartdoc, directly, it will be the
189 * path to the directory containing `dartdoc.dart`. If you're running a script 224 * path to the directory containing `dartdoc.dart`. If you're running a script
190 * that imports dartdoc, it will be the path to that script. 225 * that imports dartdoc, it will be the path to that script.
191 */ 226 */
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 340
306 /** Set this to add content before the footer */ 341 /** Set this to add content before the footer */
307 String preFooterText = ''; 342 String preFooterText = '';
308 343
309 /** Set this to omit generation timestamp from output */ 344 /** Set this to omit generation timestamp from output */
310 bool omitGenerationTime = false; 345 bool omitGenerationTime = false;
311 346
312 /** Set by Dartdoc user to print extra information during generation. */ 347 /** Set by Dartdoc user to print extra information during generation. */
313 bool verbose = false; 348 bool verbose = false;
314 349
315 /** Set this to select the libraries to document */ 350 /** Set this to include API libraries in the documentation. */
316 List<String> libraries = null; 351 bool includeAPI = false;
352
353 /** Set this to generate link to the online API. */
floitsch 2012/07/23 10:43:56 links
Johnni Winther 2012/07/24 08:49:16 Done.
354 bool linkToApi = false;
355
356 /** Set this to select the libraries to include in the documentation */
floitsch 2012/07/23 10:43:56 documentation.
Johnni Winther 2012/07/24 08:49:16 Done.
357 List<String> includeLibraries = null;
floitsch 2012/07/23 10:43:56 Wouldn't it be easier, if you initialized this wit
Bob Nystrom 2012/07/23 17:04:31 +1. Also, I would name it "includedLibraries", or
Johnni Winther 2012/07/24 08:49:16 Done.
Johnni Winther 2012/07/24 08:49:16 Done.
358
359 /** Set this to select the libraries to exclude from the documentation */
floitsch 2012/07/23 10:43:56 documentation.
Johnni Winther 2012/07/24 08:49:16 Done.
360 List<String> excludeLibraries = null;
floitsch 2012/07/23 10:43:56 ditto (empty list).
Bob Nystrom 2012/07/23 17:04:31 "excludedLibraries"
Johnni Winther 2012/07/24 08:49:16 Done.
Johnni Winther 2012/07/24 08:49:16 Done.
317 361
318 /** 362 /**
319 * This list contains the libraries sorted in by the library name. 363 * This list contains the libraries sorted in by the library name.
320 */ 364 */
321 List<LibraryMirror> _sortedLibraries; 365 List<LibraryMirror> _sortedLibraries;
322 366
323 CommentMap _comments; 367 CommentMap _comments;
324 368
325 /** The library that we're currently generating docs for. */ 369 /** The library that we're currently generating docs for. */
326 LibraryMirror _currentLibrary; 370 LibraryMirror _currentLibrary;
(...skipping 19 matching lines...) Expand all
346 // Patch in support for [:...:]-style code to the markdown parser. 390 // Patch in support for [:...:]-style code to the markdown parser.
347 // TODO(rnystrom): Markdown already has syntax for this. Phase this out? 391 // TODO(rnystrom): Markdown already has syntax for this. Phase this out?
348 md.InlineParser.syntaxes.insertRange(0, 1, 392 md.InlineParser.syntaxes.insertRange(0, 1,
349 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]')); 393 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]'));
350 394
351 md.setImplicitLinkResolver((name) => resolveNameReference(name, 395 md.setImplicitLinkResolver((name) => resolveNameReference(name,
352 currentLibrary: _currentLibrary, currentType: _currentType, 396 currentLibrary: _currentLibrary, currentType: _currentType,
353 currentMember: _currentMember)); 397 currentMember: _currentMember));
354 } 398 }
355 399
356 bool includeLibrary(LibraryMirror library) { 400 bool includeLibrary(LibraryMirror library) {
floitsch 2012/07/23 10:43:56 not a boolean name. shouldIncludeLibrary?
Bob Nystrom 2012/07/23 17:04:31 +1. Also, needs a doc comment.
357 if (libraries != null) { 401 if (linkLibrary(library)) {
Bob Nystrom 2012/07/23 17:04:31 It's up to you, but if you like, the style guide d
358 return libraries.indexOf(library.simpleName()) != -1; 402 return false;
403 }
404 String libraryName = library.simpleName();
405 if (includeLibraries != null) {
406 if (includeLibraries.indexOf(libraryName) != -1) {
407 return true;
408 }
409 }
410 if (excludeLibraries != null) {
411 if (excludeLibraries.indexOf(libraryName) != -1) {
412 return false;
413 }
414 }
415 if (libraryName.startsWith('dart:')) {
416 String suffix = libraryName.substring('dart:'.length);
floitsch 2012/07/23 10:43:56 This code is duplicated here and below. Maybe crea
Johnni Winther 2012/07/24 08:49:16 They are slightly different.
417 LibraryInfo info = DART2JS_LIBRARY_MAP[suffix];
418 if (info != null) {
419 return !info.internal && includeAPI;
420 }
359 } 421 }
360 return true; 422 return true;
361 } 423 }
362 424
425 bool linkLibrary(LibraryMirror library) {
floitsch 2012/07/23 10:43:56 that's not a boolean name. shouldLinkToPublicApi ?
Johnni Winther 2012/07/24 08:49:16 Done.
426 if (linkToApi) {
427 String libraryName = library.simpleName();
428 if (libraryName.startsWith('dart:')) {
429 String suffix = libraryName.substring('dart:'.length);
430 LibraryInfo info = DART2JS_LIBRARY_MAP[suffix];
431 if (info != null) {
432 return !info.internal;
433 }
434 }
435 }
436 return false;
437 }
438
363 String get footerContent(){ 439 String get footerContent(){
364 var footerItems = []; 440 var footerItems = [];
365 if(!omitGenerationTime) { 441 if(!omitGenerationTime) {
366 footerItems.add("This page was generated at ${new Date.now()}"); 442 footerItems.add("This page was generated at ${new Date.now()}");
367 } 443 }
368 if(footerText != null) { 444 if(footerText != null) {
369 footerItems.add(footerText); 445 footerItems.add(footerText);
370 } 446 }
371 var content = ''; 447 var content = '';
372 for (int i = 0; i < footerItems.length; i++) { 448 for (int i = 0; i < footerItems.length; i++) {
(...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 if (type.isTypeVariable) { 1350 if (type.isTypeVariable) {
1275 // If we're using a type parameter within the body of a generic class then 1351 // If we're using a type parameter within the body of a generic class then
1276 // just link back up to the class. 1352 // just link back up to the class.
1277 write(a(typeUrl(enclosingType), type.simpleName())); 1353 write(a(typeUrl(enclosingType), type.simpleName()));
1278 return; 1354 return;
1279 } 1355 }
1280 1356
1281 assert(type is InterfaceMirror); 1357 assert(type is InterfaceMirror);
1282 1358
1283 // Link to the type. 1359 // Link to the type.
1284 if (includeLibrary(type.library())) { 1360 if (linkLibrary(type.library())) {
1361 write('<a href="$API_LOCATION${typeUrl(type)}">${type.simpleName()}</a>');
1362 } else if (includeLibrary(type.library())) {
1285 write(a(typeUrl(type), type.simpleName())); 1363 write(a(typeUrl(type), type.simpleName()));
1286 } else { 1364 } else {
1287 write(type.simpleName()); 1365 write(type.simpleName());
1288 } 1366 }
1289 1367
1290 if (type.isDeclaration) { 1368 if (type.isDeclaration) {
1291 // Avoid calling [:typeArguments():] on a declaration. 1369 // Avoid calling [:typeArguments():] on a declaration.
1292 return; 1370 return;
1293 } 1371 }
1294 1372
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1498 } 1576 }
1499 1577
1500 /** 1578 /**
1501 * Returns [:true:] if [type] should be regarded as an exception. 1579 * Returns [:true:] if [type] should be regarded as an exception.
1502 */ 1580 */
1503 bool isException(TypeMirror type) { 1581 bool isException(TypeMirror type) {
1504 return type.simpleName().endsWith('Exception'); 1582 return type.simpleName().endsWith('Exception');
1505 } 1583 }
1506 } 1584 }
1507 1585
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698