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

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

Issue 10453097: Frog now called directly in dartdoc (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Frog called directly from dartdoc Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/minfrogc.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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:json'); 20 #import('dart:json');
21 #import('../../frog/lang.dart'); 21 #import('../../frog/lang.dart');
22 #import('../../frog/file_system.dart'); 22 #import('../../frog/file_system.dart');
23 #import('../../frog/file_system_vm.dart'); 23 #import('../../frog/file_system_vm.dart');
24 #import('classify.dart'); 24 #import('classify.dart');
25 #import('markdown.dart', prefix: 'md'); 25 #import('markdown.dart', prefix: 'md');
26 #import('../../frog/minfrogc.dart', prefix: 'frog');
26 27
27 #source('comment_map.dart'); 28 #source('comment_map.dart');
28 #source('utils.dart'); 29 #source('utils.dart');
29 30
30 /** 31 /**
31 * Generates completely static HTML containing everything you need to browse 32 * Generates completely static HTML containing everything you need to browse
32 * the docs. The only client side behavior is trivial stuff like syntax 33 * the docs. The only client side behavior is trivial stuff like syntax
33 * highlighting code. 34 * highlighting code.
34 */ 35 */
35 final MODE_STATIC = 0; 36 final MODE_STATIC = 0;
(...skipping 16 matching lines...) Expand all
52 * Run this from the `lib/dartdoc` directory. 53 * Run this from the `lib/dartdoc` directory.
53 */ 54 */
54 void main() { 55 void main() {
55 final args = new Options().arguments; 56 final args = new Options().arguments;
56 57
57 // Parse the dartdoc options. 58 // Parse the dartdoc options.
58 bool includeSource; 59 bool includeSource;
59 int mode; 60 int mode;
60 String outputDir; 61 String outputDir;
61 bool generateAppCache; 62 bool generateAppCache;
63
64 if (args.isEmpty()) {
65 print('No arguments provided.');
66 printUsage();
67 return;
68 }
62 69
63 for (int i = 0; i < args.length - 1; i++) { 70 for (int i = 0; i < args.length - 1; i++) {
64 final arg = args[i]; 71 final arg = args[i];
65 72
66 switch (arg) { 73 switch (arg) {
67 case '--no-code': 74 case '--no-code':
68 includeSource = false; 75 includeSource = false;
69 break; 76 break;
70 77
71 case '--mode=static': 78 case '--mode=static':
72 mode = MODE_STATIC; 79 mode = MODE_STATIC;
73 break; 80 break;
74 81
75 case '--mode=live-nav': 82 case '--mode=live-nav':
76 mode = MODE_LIVE_NAV; 83 mode = MODE_LIVE_NAV;
77 break; 84 break;
78 85
79 case '--generate-app-cache': 86 case '--generate-app-cache':
80 case '--generate-app-cache=true': 87 case '--generate-app-cache=true':
81 generateAppCache = true; 88 generateAppCache = true;
82 break; 89 break;
83 90
84 default: 91 default:
85 if (arg.startsWith('--out=')) { 92 if (arg.startsWith('--out=')) {
86 outputDir = arg.substring('--out='.length); 93 outputDir = arg.substring('--out='.length);
87 } else { 94 } else {
88 print('Unknown option: $arg'); 95 print('Unknown option: $arg');
96 printUsage();
89 return; 97 return;
90 } 98 }
91 break; 99 break;
92 } 100 }
93 } 101 }
94 102
95 // The entrypoint of the library to generate docs for. 103 // The entrypoint of the library to generate docs for.
96 final entrypoint = args[args.length - 1]; 104 final entrypoint = args[args.length - 1];
97 105
98 final files = new VMFileSystem(); 106 final files = new VMFileSystem();
99 107
100 // TODO(rnystrom): Note that the following lines get munged by create-sdk to 108 // TODO(rnystrom): Note that the following lines get munged by create-sdk to
101 // work with the SDK's different file layout. If you change, be sure to test 109 // work with the SDK's different file layout. If you change, be sure to test
102 // that dartdoc still works when run from the built SDK directory. 110 // that dartdoc still works when run from the built SDK directory.
103 final frogPath = joinPaths(scriptDir, '../../frog/'); 111 final frogPath = joinPaths(scriptDir, '../../frog/');
104 final libDir = joinPaths(frogPath, 'lib'); 112 final libDir = joinPaths(frogPath, 'lib');
105 final compilerPath = joinPaths(frogPath, 'minfrog');
106 113
107 parseOptions(frogPath, ['', '', '--libdir=$libDir'], files); 114 parseOptions(frogPath, ['', '', '--libdir=$libDir'], files);
108 initializeWorld(files); 115 initializeWorld(files);
109 116
110 final dartdoc = new Dartdoc(); 117 final dartdoc = new Dartdoc();
111 118
112 if (includeSource != null) dartdoc.includeSource = includeSource; 119 if (includeSource != null) dartdoc.includeSource = includeSource;
113 if (mode != null) dartdoc.mode = mode; 120 if (mode != null) dartdoc.mode = mode;
114 if (outputDir != null) dartdoc.outputDir = outputDir; 121 if (outputDir != null) dartdoc.outputDir = outputDir;
115 if (generateAppCache != null) dartdoc.generateAppCache = generateAppCache; 122 if (generateAppCache != null) dartdoc.generateAppCache = generateAppCache;
116 123
117 cleanOutputDirectory(dartdoc.outputDir); 124 cleanOutputDirectory(dartdoc.outputDir);
118 125
119 // Compile the client-side code to JS. 126 // Compile the client-side code to JS.
120 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav'; 127 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav';
121 final Future scriptCompiled = compileScript(compilerPath, libDir, 128 final Future scriptCompiled = compileScript(libDir,
Bob Nystrom 2012/05/31 17:53:42 Local variables don't need type annotations.
122 '$scriptDir/client-$clientScript.dart', 129 '$scriptDir/client-$clientScript.dart',
123 '${dartdoc.outputDir}/client-$clientScript.js'); 130 '${dartdoc.outputDir}/client-$clientScript.js');
124 131
125 final Future filesCopied = copyFiles('$scriptDir/static', dartdoc.outputDir); 132 final Future filesCopied = copyFiles('$scriptDir/static', dartdoc.outputDir);
126 133
127 Futures.wait([scriptCompiled, filesCopied]).then((_) { 134 Futures.wait([scriptCompiled, filesCopied]).then((_) {
128 dartdoc.document(entrypoint); 135 dartdoc.document(entrypoint);
136
137 print('Documented ${dartdoc._totalLibraries} libraries, '
138 '${dartdoc._totalTypes} types, and '
139 '${dartdoc._totalMembers} members.');
129 }); 140 });
130 141
131 print('Documented ${dartdoc._totalLibraries} libraries, ' + 142 }
132 '${dartdoc._totalTypes} types, and ' + 143
133 '${dartdoc._totalMembers} members.'); 144 void printUsage() {
145 print('''
146 Usage dartdoc [options] <entrypoint>
147 [options] include
Bob Nystrom 2012/05/31 17:53:42 Nice!
148 --no-code Do not include source code in the documentation.
149
150 --mode=static Generates completely static HTML containing
151 everything you need to browse the docs. The only
152 client side behavior is trivial stuff like syntax
153 highlighting code.
154
155 --mode=live-nav (default) Generated docs do not include baked HTML
156 navigation. Instead, a single `nav.json` file is
157 created and the appropriate navigation is generated
158 client-side by parsing that and building HTML.
159 This dramatically reduces the generated size of
160 the HTML since a large fraction of each static page
161 is just redundant navigation links.
162 In this mode, the browser will do a XHR for
163 nav.json which means that to preview docs locally,
164 you will need to enable requesting file:// links in
165 your browser or run a little local server like
166 `python -m SimpleHTTPServer`.
167
168 --generate-app-cache Generates the App Cache manifest file, enabling
169 offline doc viewing.
170 --generate-app-cache=true --''--
171
172 --out=<dir> Generates files into directory <dir>. If omitted
173 the files are generated into ./docs/
174 ''');
134 } 175 }
135 176
136 /** 177 /**
137 * Gets the full path to the directory containing the entrypoint of the current 178 * Gets the full path to the directory containing the entrypoint of the current
138 * script. In other words, if you invoked dartdoc, directly, it will be the 179 * script. In other words, if you invoked dartdoc, directly, it will be the
139 * path to the directory containing `dartdoc.dart`. If you're running a script 180 * path to the directory containing `dartdoc.dart`. If you're running a script
140 * that imports dartdoc, it will be the path to that script. 181 * that imports dartdoc, it will be the path to that script.
141 */ 182 */
142 String get scriptDir() { 183 String get scriptDir() {
143 return dirname(new File(new Options().script).fullPathSync()); 184 return dirname(new File(new Options().script).fullPathSync());
144 } 185 }
145 186
146 /** 187 /**
147 * Deletes and recreates the output directory at [path] if it exists. 188 * Deletes and recreates the output directory at [path] if it exists.
148 */ 189 */
149 void cleanOutputDirectory(String path) { 190 void cleanOutputDirectory(String path) {
150 final outputDir = new Directory(path); 191 final outputDir = new Directory(path);
151 if (outputDir.existsSync()) { 192 if (outputDir.existsSync()) {
152 outputDir.deleteRecursivelySync(); 193 outputDir.deleteRecursivelySync();
153 } 194 }
154 195
155 outputDir.createSync(); 196 try {
197 // TODO(johnniwinther): hack to avoid 'file already exists' exception thrown
198 // due to invalid result from dir.existsSync() (probably due to race
199 // conditions).
200 outputDir.createSync();
201 } catch (DirectoryIOException e) {
202 // Ignore.
203 }
156 } 204 }
157 205
158 /** 206 /**
159 * Copies all of the files in the directory [from] to [to]. Does *not* 207 * Copies all of the files in the directory [from] to [to]. Does *not*
160 * recursively copy subdirectories. 208 * recursively copy subdirectories.
161 * 209 *
162 * Note: runs asynchronously, so you won't see any files copied until after the 210 * Note: runs asynchronously, so you won't see any files copied until after the
163 * event loop has had a chance to pump (i.e. after `main()` has returned). 211 * event loop has had a chance to pump (i.e. after `main()` has returned).
164 */ 212 */
165 Future copyFiles(String from, String to) { 213 Future copyFiles(String from, String to) {
(...skipping 12 matching lines...) Expand all
178 stream.write(bytes, copyBuffer: false); 226 stream.write(bytes, copyBuffer: false);
179 stream.close(); 227 stream.close();
180 }); 228 });
181 }; 229 };
182 lister.onDone = (done) => completer.complete(true); 230 lister.onDone = (done) => completer.complete(true);
183 return completer.future; 231 return completer.future;
184 } 232 }
185 233
186 /** 234 /**
187 * Compiles the given Dart script to a JavaScript file at [jsPath] using the 235 * Compiles the given Dart script to a JavaScript file at [jsPath] using the
188 * Dart-to-JS compiler located at [compilerPath]. 236 * Frog compiler.
189 */ 237 */
190 Future compileScript(String compilerPath, String libDir, 238 Future compileScript(String libDir, String dartPath, String jsPath) {
Bob Nystrom 2012/05/31 17:53:42 Since this is no longer asynchronous, can you get
191 String dartPath, String jsPath) {
192 final completer = new Completer(); 239 final completer = new Completer();
193 onExit(ProcessResult result) { 240 print('Compiling $dartPath to $jsPath');
194 if (result.exitCode != 0) { 241
195 final message = 'Non-zero exit code from $compilerPath'; 242 var result = true;
243 try {
244 result = frog.internalMain([
245 '--libdir=$libDir', '--out=$jsPath',
246 '--compile-only', '--enable-type-checks', '--warnings-as-errors',
247 dartPath]);
248 if (!result) {
249 final message = 'Non-zero exit code from the compiler';
196 print('$message.'); 250 print('$message.');
197 print(result.stdout); 251 completer.completeException(message);
198 print(result.stderr); 252 } else {
199 throw message; 253 completer.complete(result);
200 } 254 }
201 completer.complete(true); 255 } catch (Object error) {
256 final message = 'Error trying to execute the compiler. Error: $error';
257 print('$message.');
258 completer.completeException(message);
202 } 259 }
203 260
204 onError(error) {
205 final message = 'Error trying to execute $compilerPath. Error: $error';
206 print('$message.');
207 throw message;
208 }
209
210 print('Compiling $dartPath to $jsPath');
211 var processFuture = Process.run(compilerPath, [
212 '--libdir=$libDir', '--out=$jsPath',
213 '--compile-only', '--enable-type-checks', '--warnings-as-errors',
214 dartPath]);
215
216 processFuture.handleException(onError);
217 processFuture.then(onExit);
218
219 return completer.future; 261 return completer.future;
220 } 262 }
221 263
222 class Dartdoc { 264 class Dartdoc {
223 265
224 /** Set to `false` to not include the source code in the generated docs. */ 266 /** Set to `false` to not include the source code in the generated docs. */
225 bool includeSource = true; 267 bool includeSource = true;
226 268
227 /** 269 /**
228 * Dartdoc can generate docs in a few different ways based on how dynamic you 270 * Dartdoc can generate docs in a few different ways based on how dynamic you
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 386
345 void startFile(String path) { 387 void startFile(String path) {
346 _filePath = path; 388 _filePath = path;
347 _file = new StringBuffer(); 389 _file = new StringBuffer();
348 } 390 }
349 391
350 void endFile() { 392 void endFile() {
351 final outPath = '$outputDir/$_filePath'; 393 final outPath = '$outputDir/$_filePath';
352 final dir = new Directory(dirname(outPath)); 394 final dir = new Directory(dirname(outPath));
353 if (!dir.existsSync()) { 395 if (!dir.existsSync()) {
354 dir.createSync(); 396 //TODO(johnniwinther) hack to avoid 'file already exists' exception thrown
397 // due to invalid result from dir.existsSync() (probably due to race
398 // conditions)
Bob Nystrom 2012/05/31 17:53:42 This worries me. I've never seen race conditions w
399 try {
400 dir.createSync();
401 } catch (DirectoryIOException e) {
402 // ignore
403 }
355 } 404 }
356 405
357 world.files.writeString(outPath, _file.toString()); 406 world.files.writeString(outPath, _file.toString());
358 _filePath = null; 407 _filePath = null;
359 _file = null; 408 _file = null;
360 } 409 }
361 410
362 void write(String s) { 411 void write(String s) {
363 _file.add(s); 412 _file.add(s);
364 } 413 }
(...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after
1348 toCache.onFile = (filename) { 1397 toCache.onFile = (filename) {
1349 if (filename.endsWith('appcache.manifest')) { 1398 if (filename.endsWith('appcache.manifest')) {
1350 return; 1399 return;
1351 } 1400 }
1352 var relativePath = filename.substring(pathPrefixLength + 1); 1401 var relativePath = filename.substring(pathPrefixLength + 1);
1353 write("$relativePath\n"); 1402 write("$relativePath\n");
1354 }; 1403 };
1355 toCache.onDone = (done) => endFile(); 1404 toCache.onDone = (done) => endFile();
1356 toCache.list(recursive: true); 1405 toCache.list(recursive: true);
1357 } 1406 }
1358 } 1407 }
OLDNEW
« no previous file with comments | « frog/minfrogc.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698