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

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

Issue 8572044: Clean and create output directory when generating docs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Respond to review. Created 9 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 | « utils/dartdoc/.gitignore ('k') | utils/dartdoc/docs/grid-22.png » ('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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** An awesome documentation generator. */ 5 /** An awesome documentation generator. */
6 #library('dartdoc'); 6 #library('dartdoc');
7 7
8 #import('../../frog/lang.dart'); 8 #import('../../frog/lang.dart');
9 #import('../../frog/file_system.dart');
9 #import('../../frog/file_system_node.dart'); 10 #import('../../frog/file_system_node.dart');
10 11
11 #source('classify.dart'); 12 #source('classify.dart');
12 13
13 /** Path to corePath library. */ 14 /** Path to corePath library. */
14 final corePath = 'lib'; 15 final corePath = 'lib';
15 16
16 /** Path to generate html files into. */ 17 /** Path to generate html files into. */
17 final outdir = 'docs'; 18 final outdir = 'docs';
18 19
19 /** Special comment position used to store the library-level doc comment. */ 20 /** Special comment position used to store the library-level doc comment. */
20 final _libraryDoc = -1; 21 final _libraryDoc = -1;
21 22
22 /** The file currently being written to. */ 23 /** The file currently being written to. */
23 StringBuffer _file; 24 StringBuffer _file;
24 25
25 /** 26 /**
26 * The cached lookup-table to associate doc comments with spans. The outer map 27 * The cached lookup-table to associate doc comments with spans. The outer map
27 * is from filenames to doc comments in that file. The inner map maps from the 28 * is from filenames to doc comments in that file. The inner map maps from the
28 * token positions to doc comments. Each position is the starting offset of the 29 * token positions to doc comments. Each position is the starting offset of the
29 * next non-comment token *following* the doc comment. For example, the position 30 * next non-comment token *following* the doc comment. For example, the position
30 * for this comment would be the position of the "Map" token below. 31 * for this comment would be the position of the "Map" token below.
31 */ 32 */
32 Map<String, Map<int, String>> _comments; 33 Map<String, Map<int, String>> _comments;
33 34
34 int _totalLibraries = 0; 35 int _totalLibraries = 0;
35 int _totalTypes = 0; 36 int _totalTypes = 0;
36 int _totalMembers = 0; 37 int _totalMembers = 0;
37 38
39 FileSystem files;
40
38 /** 41 /**
39 * Run this from the frog/samples directory. Before running, you need 42 * Run this from the frog/samples directory. Before running, you need
40 * to create a docs dir with 'mkdir docs' - since Dart currently doesn't 43 * to create a docs dir with 'mkdir docs' - since Dart currently doesn't
41 * support creating new directories. 44 * support creating new directories.
42 */ 45 */
43 void main() { 46 void main() {
44 // The entrypoint of the library to generate docs for. 47 // The entrypoint of the library to generate docs for.
45 final libPath = process.argv[2]; 48 final libPath = process.argv[2];
46 49
47 // TODO(rnystrom): Get options and homedir like frog.dart does. 50 files = new NodeFileSystem();
48 final files = new NodeFileSystem();
49 parseOptions('../../frog', [] /* args */, files); 51 parseOptions('../../frog', [] /* args */, files);
50 52
51 final elapsed = time(() { 53 final elapsed = time(() {
54 _comments = <String, Map<int, String>>{};
55
52 initializeWorld(files); 56 initializeWorld(files);
53 57
54 world.processScript(libPath); 58 world.processScript(libPath);
55 world.resolveAll(); 59 world.resolveAll();
56 60
57 _comments = <String, Map<int, String>>{}; 61 // Clean the output directory.
62 if (files.fileExists(outdir)) {
63 files.removeDirectory(outdir, recursive: true);
64 }
65 files.createDirectory(outdir, recursive: true);
58 66
59 for (var library in world.libraries.getValues()) { 67 // Copy over the static files.
68 for (final file in ['interact.js', 'styles.css']) {
69 copyStatic(file);
70 }
71
72 // Generate the docs.
73 for (final library in world.libraries.getValues()) {
60 docLibrary(library); 74 docLibrary(library);
61 } 75 }
62 76
63 docIndex(world.libraries.getValues()); 77 docIndex(world.libraries.getValues());
64 }); 78 });
65 79
66 print('Documented $_totalLibraries libraries, $_totalTypes types, and ' + 80 print('Documented $_totalLibraries libraries, $_totalTypes types, and ' +
67 '$_totalMembers members in ${elapsed}msec.'); 81 '$_totalMembers members in ${elapsed}msec.');
68 } 82 }
69 83
84 /** Copies the static file at 'static/file' to the output directory. */
85 copyStatic(String file) {
86 var contents = files.readAll(joinPaths('static', file));
87 files.writeString(joinPaths(outdir, file), contents);
88 }
89
70 num time(callback()) { 90 num time(callback()) {
71 // Unlike world.withTiming, returns the elapsed time. 91 // Unlike world.withTiming, returns the elapsed time.
72 final watch = new Stopwatch(); 92 final watch = new Stopwatch();
73 watch.start(); 93 watch.start();
74 callback(); 94 callback();
75 watch.stop(); 95 watch.stop();
76 return watch.elapsedInMs(); 96 return watch.elapsedInMs();
77 } 97 }
78 98
79 startFile() { 99 startFile() {
(...skipping 24 matching lines...) Expand all
104 ''' 124 '''
105 <html><head> 125 <html><head>
106 <title>Index</title> 126 <title>Index</title>
107 <link rel="stylesheet" type="text/css" href="styles.css" /> 127 <link rel="stylesheet" type="text/css" href="styles.css" />
108 </head> 128 </head>
109 <body> 129 <body>
110 <div class="content"> 130 <div class="content">
111 <ul> 131 <ul>
112 '''); 132 ''');
113 133
114 var sorted = new List<Library>.from(libraries); 134 final sorted = new List<Library>.from(libraries);
115 sorted.sort((a, b) => a.name.compareTo(b.name)); 135 sorted.sort((a, b) => a.name.compareTo(b.name));
116 136
117 for (var library in sorted) { 137 for (final library in sorted) {
118 writeln( 138 writeln(
119 ''' 139 '''
120 <li><a href="${sanitize(library.name)}.html"> 140 <li><a href="${sanitize(library.name)}.html">
121 Library ${library.name}</a> 141 Library ${library.name}</a>
122 </li> 142 </li>
123 '''); 143 ''');
124 } 144 }
125 145
126 writeln( 146 writeln(
127 ''' 147 '''
(...skipping 25 matching lines...) Expand all
153 173
154 bool needsSeparator = false; 174 bool needsSeparator = false;
155 175
156 // Look for a comment for the entire library. 176 // Look for a comment for the entire library.
157 final comment = findCommentInFile(library.baseSource, _libraryDoc); 177 final comment = findCommentInFile(library.baseSource, _libraryDoc);
158 if (comment != null) { 178 if (comment != null) {
159 writeln('<div class="doc"><p>$comment</p></div>'); 179 writeln('<div class="doc"><p>$comment</p></div>');
160 needsSeparator = true; 180 needsSeparator = true;
161 } 181 }
162 182
163 for (var type in library.types.getValues()) { 183 for (final type in library.types.getValues()) {
164 if (needsSeparator) writeln('<hr/>'); 184 if (needsSeparator) writeln('<hr/>');
165 if (docType(type)) needsSeparator = true; 185 if (docType(type)) needsSeparator = true;
166 } 186 }
167 187
168 writeln( 188 writeln(
169 ''' 189 '''
170 </div> 190 </div>
171 </body></html> 191 </body></html>
172 '''); 192 ''');
173 193
(...skipping 20 matching lines...) Expand all
194 '''); 214 ''');
195 215
196 docInheritance(type); 216 docInheritance(type);
197 docCode(type.span); 217 docCode(type.span);
198 docConstructors(type); 218 docConstructors(type);
199 219
200 wroteSomething = true; 220 wroteSomething = true;
201 } 221 }
202 222
203 // Collect the different kinds of members. 223 // Collect the different kinds of members.
204 var methods = []; 224 final methods = [];
205 var fields = []; 225 final fields = [];
206 226
207 for (var member in orderValuesByKeys(type.members)) { 227 for (final member in orderValuesByKeys(type.members)) {
208 if (member.isMethod && 228 if (member.isMethod &&
209 (member.definition != null) && 229 (member.definition != null) &&
210 !member.name.startsWith('_')) { 230 !member.name.startsWith('_')) {
211 methods.add(member); 231 methods.add(member);
212 } else if (member.isProperty) { 232 } else if (member.isProperty) {
213 if (member.canGet) methods.add(member.getter); 233 if (member.canGet) methods.add(member.getter);
214 if (member.canSet) methods.add(member.setter); 234 if (member.canSet) methods.add(member.setter);
215 } else if (member.isField && !member.name.startsWith('_')) { 235 } else if (member.isField && !member.name.startsWith('_')) {
216 fields.add(member); 236 fields.add(member);
217 } 237 }
218 } 238 }
219 239
220 if (methods.length > 0) { 240 if (methods.length > 0) {
221 writeln('<h3>Methods</h3>'); 241 writeln('<h3>Methods</h3>');
222 for (var method in methods) docMethod(type.name, method); 242 for (final method in methods) docMethod(type.name, method);
223 } 243 }
224 244
225 if (fields.length > 0) { 245 if (fields.length > 0) {
226 writeln('<h3>Fields</h3>'); 246 writeln('<h3>Fields</h3>');
227 for (var field in fields) docField(type.name, field); 247 for (final field in fields) docField(type.name, field);
228 } 248 }
229 249
230 return wroteSomething || methods.length > 0 || fields.length > 0; 250 return wroteSomething || methods.length > 0 || fields.length > 0;
231 } 251 }
232 252
233 /** Document the superclass and superinterfaces of [Type]. */ 253 /** Document the superclass and superinterfaces of [Type]. */
234 docInheritance(Type type) { 254 docInheritance(Type type) {
235 // Show the superclass and superinterface(s). 255 // Show the superclass and superinterface(s).
236 if ((type.parent != null) && (type.parent.isObject) || 256 if ((type.parent != null) && (type.parent.isObject) ||
237 (type.interfaces != null && type.interfaces.length > 0)) { 257 (type.interfaces != null && type.interfaces.length > 0)) {
238 writeln('<p>'); 258 writeln('<p>');
239 259
240 if (type.parent != null) { 260 if (type.parent != null) {
241 write('Extends ${typeRef(type.parent)}. '); 261 write('Extends ${typeRef(type.parent)}. ');
242 } 262 }
243 263
244 if (type.interfaces != null) { 264 if (type.interfaces != null) {
245 var interfaces = []; 265 final interfaces = [];
246 switch (type.interfaces.length) { 266 switch (type.interfaces.length) {
247 case 0: 267 case 0:
248 // Do nothing. 268 // Do nothing.
249 break; 269 break;
250 270
251 case 1: 271 case 1:
252 write('Implements ${typeRef(type.interfaces[0])}.'); 272 write('Implements ${typeRef(type.interfaces[0])}.');
253 break; 273 break;
254 274
255 case 2: 275 case 2:
256 write('''Implements ${typeRef(type.interfaces[0])} and 276 write('''Implements ${typeRef(type.interfaces[0])} and
257 ${typeRef(type.interfaces[1])}.'''); 277 ${typeRef(type.interfaces[1])}.''');
258 break; 278 break;
259 279
260 default: 280 default:
261 write('Implements '); 281 write('Implements ');
262 for (var i = 0; i < type.interfaces.length; i++) { 282 for (final i = 0; i < type.interfaces.length; i++) {
263 write('${typeRef(type.interfaces[i])}'); 283 write('${typeRef(type.interfaces[i])}');
264 if (i < type.interfaces.length - 1) { 284 if (i < type.interfaces.length - 1) {
265 write(', '); 285 write(', ');
266 } else { 286 } else {
267 write(' and '); 287 write(' and ');
268 } 288 }
269 } 289 }
270 write('.'); 290 write('.');
271 break; 291 break;
272 } 292 }
273 } 293 }
274 } 294 }
275 } 295 }
276 296
277 /** Document the constructors for [Type], if any. */ 297 /** Document the constructors for [Type], if any. */
278 docConstructors(Type type) { 298 docConstructors(Type type) {
279 if (type.constructors.length > 0) { 299 if (type.constructors.length > 0) {
280 writeln('<h3>Constructors</h3>'); 300 writeln('<h3>Constructors</h3>');
281 for (var name in type.constructors.getKeys()) { 301 for (final name in type.constructors.getKeys()) {
282 var constructor = type.constructors[name]; 302 final constructor = type.constructors[name];
283 docMethod(type.name, constructor, namedConstructor: name); 303 docMethod(type.name, constructor, namedConstructor: name);
284 } 304 }
285 } 305 }
286 } 306 }
287 307
288 /** 308 /**
289 * Documents the [method] in a type named [typeName]. Handles all kinds of 309 * Documents the [method] in a type named [typeName]. Handles all kinds of
290 * methods including getters, setters, and constructors. 310 * methods including getters, setters, and constructors.
291 */ 311 */
292 docMethod(String typeName, MethodMember method, 312 docMethod(String typeName, MethodMember method,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 353
334 write('<strong>$name</strong>'); 354 write('<strong>$name</strong>');
335 355
336 // Named constructors. 356 // Named constructors.
337 if (namedConstructor != null && namedConstructor != '') { 357 if (namedConstructor != null && namedConstructor != '') {
338 write('.'); 358 write('.');
339 write(namedConstructor); 359 write(namedConstructor);
340 } 360 }
341 361
342 write('('); 362 write('(');
343 var paramList = []; 363 final paramList = [];
344 if (method.parameters == null) print(method.name); 364 if (method.parameters == null) print(method.name);
345 for (var p in method.parameters) { 365 for (final p in method.parameters) {
346 paramList.add('${optionalTypeRef(p.type)}${p.name}'); 366 paramList.add('${optionalTypeRef(p.type)}${p.name}');
347 } 367 }
348 write(Strings.join(paramList, ", ")); 368 write(Strings.join(paramList, ", "));
349 write(')'); 369 write(')');
350 370
351 write(''' <a class="anchor-link" href="#$typeName.${method.name}" 371 write(''' <a class="anchor-link" href="#$typeName.${method.name}"
352 title="Permalink to $typeName.$name">#</a>'''); 372 title="Permalink to $typeName.$name">#</a>''');
353 writeln('</h4>'); 373 writeln('</h4>');
354 374
355 docCode(method.span, showCode: true); 375 docCode(method.span, showCode: true);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 docCode(field.span, showCode: true); 411 docCode(field.span, showCode: true);
392 writeln('</div>'); 412 writeln('</div>');
393 } 413 }
394 414
395 /** 415 /**
396 * Writes a type annotation for [type]. Will hyperlink it to that type's 416 * Writes a type annotation for [type]. Will hyperlink it to that type's
397 * documentation if possible. 417 * documentation if possible.
398 */ 418 */
399 typeRef(Type type) { 419 typeRef(Type type) {
400 if (type.library != null) { 420 if (type.library != null) {
401 var library = sanitize(type.library.name); 421 final library = sanitize(type.library.name);
402 return '<a href="${library}.html#${type.name}">${type.name}</a>'; 422 return '<a href="${library}.html#${type.name}">${type.name}</a>';
403 } else { 423 } else {
404 return type.name; 424 return type.name;
405 } 425 }
406 } 426 }
407 427
408 /** 428 /**
409 * Creates a linked string for an optional type annotation. Returns an empty 429 * Creates a linked string for an optional type annotation. Returns an empty
410 * string if the type is Dynamic. 430 * string if the type is Dynamic.
411 */ 431 */
412 optionalTypeRef(Type type) { 432 optionalTypeRef(Type type) {
413 if (type.name == 'Dynamic') { 433 if (type.name == 'Dynamic') {
414 return ''; 434 return '';
415 } else { 435 } else {
416 return typeRef(type) + ' '; 436 return typeRef(type) + ' ';
417 } 437 }
418 } 438 }
419 439
420 /** 440 /**
421 * Documents the code contained within [span]. Will include the previous 441 * Documents the code contained within [span]. Will include the previous
422 * Dartdoc associated with that span if found, and will include the syntax 442 * Dartdoc associated with that span if found, and will include the syntax
423 * highlighted code itself if desired. 443 * highlighted code itself if desired.
424 */ 444 */
425 docCode(SourceSpan span, [bool showCode = false]) { 445 docCode(SourceSpan span, [bool showCode = false]) {
426 if (span == null) return; 446 if (span == null) return;
427 447
428 writeln('<div class="doc">'); 448 writeln('<div class="doc">');
429 var comment = findComment(span); 449 final comment = findComment(span);
430 if (comment != null) { 450 if (comment != null) {
431 writeln('<p>$comment</p>'); 451 writeln('<p>$comment</p>');
432 } 452 }
433 453
434 if (showCode) { 454 if (showCode) {
435 writeln('<pre class="source">'); 455 writeln('<pre class="source">');
436 write(formatCode(span)); 456 write(formatCode(span));
437 writeln('</pre>'); 457 writeln('</pre>');
438 } 458 }
439 459
440 writeln('</div>'); 460 writeln('</div>');
441 } 461 }
442 462
443 /** Finds the doc comment preceding the given source span, if there is one. */ 463 /** Finds the doc comment preceding the given source span, if there is one. */
444 findComment(SourceSpan span) => findCommentInFile(span.file, span.start); 464 findComment(SourceSpan span) => findCommentInFile(span.file, span.start);
445 465
446 /** Finds the doc comment preceding the given source span, if there is one. */ 466 /** Finds the doc comment preceding the given source span, if there is one. */
447 findCommentInFile(SourceFile file, int position) { 467 findCommentInFile(SourceFile file, int position) {
448 // Get the doc comments for this file. 468 // Get the doc comments for this file.
449 var fileComments = _comments.putIfAbsent(file.filename, 469 final fileComments = _comments.putIfAbsent(file.filename,
450 () => parseDocComments(file)); 470 () => parseDocComments(file));
451 471
452 return fileComments[position]; 472 return fileComments[position];
453 } 473 }
454 474
455 parseDocComments(SourceFile file) { 475 parseDocComments(SourceFile file) {
456 var comments = <int, String>{}; 476 final comments = <int, String>{};
457 477
458 var tokenizer = new Tokenizer(file, false); 478 final tokenizer = new Tokenizer(file, false);
459 var lastComment = null; 479 var lastComment = null;
460 480
461 while (true) { 481 while (true) {
462 var token = tokenizer.next(); 482 final token = tokenizer.next();
463 if (token.kind == TokenKind.END_OF_FILE) break; 483 if (token.kind == TokenKind.END_OF_FILE) break;
464 484
465 if (token.kind == TokenKind.COMMENT) { 485 if (token.kind == TokenKind.COMMENT) {
466 var text = token.text; 486 final text = token.text;
467 if (text.startsWith('/**')) { 487 if (text.startsWith('/**')) {
468 // Remember that we've encountered a doc comment. 488 // Remember that we've encountered a doc comment.
469 lastComment = stripComment(token.text); 489 lastComment = stripComment(token.text);
470 } 490 }
471 } else if (token.kind == TokenKind.WHITESPACE) { 491 } else if (token.kind == TokenKind.WHITESPACE) {
472 // Ignore whitespace tokens. 492 // Ignore whitespace tokens.
473 } else if (token.kind == TokenKind.HASH) { 493 } else if (token.kind == TokenKind.HASH) {
474 // Look for #library() to find the library comment. 494 // Look for #library() to find the library comment.
475 var next = tokenizer.next(); 495 final next = tokenizer.next();
476 if ((lastComment != null) && (next.kind == TokenKind.LIBRARY)) { 496 if ((lastComment != null) && (next.kind == TokenKind.LIBRARY)) {
477 comments[_libraryDoc] = lastComment; 497 comments[_libraryDoc] = lastComment;
478 lastComment = null; 498 lastComment = null;
479 } 499 }
480 } else { 500 } else {
481 if (lastComment != null) { 501 if (lastComment != null) {
482 // We haven't attached the last doc comment to something yet, so stick 502 // We haven't attached the last doc comment to something yet, so stick
483 // it to this token. 503 // it to this token.
484 comments[token.start] = lastComment; 504 comments[token.start] = lastComment;
485 lastComment = null; 505 lastComment = null;
486 } 506 }
487 } 507 }
488 } 508 }
489 509
490 return comments; 510 return comments;
491 } 511 }
492 512
493 /** 513 /**
494 * Takes a string of Dart code and turns it into sanitized HTML. 514 * Takes a string of Dart code and turns it into sanitized HTML.
495 */ 515 */
496 formatCode(SourceSpan span) { 516 formatCode(SourceSpan span) {
497 // Remove leading indentation to line up with first line. 517 // Remove leading indentation to line up with first line.
498 var column = getSpanColumn(span); 518 final column = getSpanColumn(span);
499 var lines = span.text.split('\n'); 519 final lines = span.text.split('\n');
500 // TODO(rnystrom): Dirty hack. 520 // TODO(rnystrom): Dirty hack.
501 for (int i = 1; i < lines.length; i++) { 521 for (final i = 1; i < lines.length; i++) {
502 lines[i] = unindent(lines[i], column); 522 lines[i] = unindent(lines[i], column);
503 } 523 }
504 524
505 var code = Strings.join(lines, '\n'); 525 final code = Strings.join(lines, '\n');
506 526
507 // Syntax highlight. 527 // Syntax highlight.
508 return classifySource(new SourceFile('', code)); 528 return classifySource(new SourceFile('', code));
509 } 529 }
510 530
511 // TODO(rnystrom): Move into SourceSpan? 531 // TODO(rnystrom): Move into SourceSpan?
512 int getSpanColumn(SourceSpan span) { 532 int getSpanColumn(SourceSpan span) {
513 var line = span.file.getLine(span.start); 533 final line = span.file.getLine(span.start);
514 return span.file.getColumn(line, span.start); 534 return span.file.getColumn(line, span.start);
515 } 535 }
516 536
517 /** Removes up to [indentation] leading whitespace characters from [text]. */ 537 /** Removes up to [indentation] leading whitespace characters from [text]. */
518 unindent(String text, int indentation) { 538 unindent(String text, int indentation) {
519 var start; 539 var start;
520 for (start = 0; start < Math.min(indentation, text.length); start++) { 540 for (start = 0; start < Math.min(indentation, text.length); start++) {
521 // Stop if we hit a non-whitespace character. 541 // Stop if we hit a non-whitespace character.
522 if (text[start] != ' ') break; 542 if (text[start] != ' ') break;
523 } 543 }
524 544
525 return text.substring(start); 545 return text.substring(start);
526 } 546 }
527 547
528 /** 548 /**
529 * Pulls the raw text out of a doc comment (i.e. removes the comment 549 * Pulls the raw text out of a doc comment (i.e. removes the comment
530 * characters. 550 * characters.
531 */ 551 */
532 // TODO(rnystrom): Should handle [name] and [:code:] in comments. Should also 552 // TODO(rnystrom): Should handle [name] and [:code:] in comments. Should also
533 // break empty lines into multiple paragraphs. Other formatting? 553 // break empty lines into multiple paragraphs. Other formatting?
534 // See dart/compiler/java/com/google/dart/compiler/backend/doc for ideas. 554 // See dart/compiler/java/com/google/dart/compiler/backend/doc for ideas.
535 // (/DartDocumentationVisitor.java#180) 555 // (/DartDocumentationVisitor.java#180)
536 stripComment(comment) { 556 stripComment(comment) {
537 StringBuffer buf = new StringBuffer(); 557 StringBuffer buf = new StringBuffer();
538 558
539 for (var line in comment.split('\n')) { 559 for (final line in comment.split('\n')) {
540 line = line.trim(); 560 line = line.trim();
541 if (line.startsWith('/**')) line = line.substring(3, line.length); 561 if (line.startsWith('/**')) line = line.substring(3, line.length);
542 if (line.endsWith('*/')) line = line.substring(0, line.length-2); 562 if (line.endsWith('*/')) line = line.substring(0, line.length-2);
543 line = line.trim(); 563 line = line.trim();
544 while (line.startsWith('*')) line = line.substring(1, line.length); 564 while (line.startsWith('*')) line = line.substring(1, line.length);
545 line = line.trim(); 565 line = line.trim();
546 buf.add(line); 566 buf.add(line);
547 buf.add(' '); 567 buf.add(' ');
548 } 568 }
549 569
550 return buf.toString(); 570 return buf.toString();
551 } 571 }
OLDNEW
« no previous file with comments | « utils/dartdoc/.gitignore ('k') | utils/dartdoc/docs/grid-22.png » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698