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

Side by Side Diff: tools/addlatexhash.dart

Issue 2827793002: Format all files under tools and utils directory. (Closed)
Patch Set: Format all files under tools and utils directory. Created 3 years, 8 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
« no previous file with comments | « no previous file | tools/dart2js/class_generator/class_generator.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env dart 1 #!/usr/bin/env dart
2 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 2 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
3 // for details. All rights reserved. Use of this source code is governed by a 3 // for details. All rights reserved. Use of this source code is governed by a
4 // BSD-style license that can be found in the LICENSE file. 4 // BSD-style license that can be found in the LICENSE file.
5 // 5 //
6 // ---------------------------------------------------------------------- 6 // ----------------------------------------------------------------------
7 // This is a very specialized tool which was created in order to support 7 // This is a very specialized tool which was created in order to support
8 // adding hash values used as location markers in the LaTeX source of the 8 // adding hash values used as location markers in the LaTeX source of the
9 // language specification. It is intended to take its input file as the 9 // language specification. It is intended to take its input file as the
10 // first argument, an output file name as the second argument, and a 10 // first argument, an output file name as the second argument, and a
11 // hash listing file name as the third argument. From docs/language a 11 // hash listing file name as the third argument. From docs/language a
12 // typical usage would be as follows: 12 // typical usage would be as follows:
13 // 13 //
14 // dart 14 // dart
15 // --package-root=<build dir>/packages \ 15 // --package-root=<build dir>/packages \
16 // ../../tools/addlatexhash.dart dartLangSpec.tex out.tex hash.txt 16 // ../../tools/addlatexhash.dart dartLangSpec.tex out.tex hash.txt
17 // 17 //
18 // This will produce a normalized variant out.tex of the language 18 // This will produce a normalized variant out.tex of the language
19 // specification with hash values filled in, and a listing hash.txt of 19 // specification with hash values filled in, and a listing hash.txt of
20 // all the hash values along with the label of their textual context 20 // all the hash values along with the label of their textual context
21 // (section, subsection, subsubsection, paragraph) . For more details, 21 // (section, subsection, subsubsection, paragraph) . For more details,
22 // please check the language specification source itself. 22 // please check the language specification source itself.
23 // 23 //
24 // NB: This utility assumes UN*X style line endings, \n, in the LaTeX 24 // NB: This utility assumes UN*X style line endings, \n, in the LaTeX
25 // source file receieved as input; it will not work with other styles. 25 // source file receieved as input; it will not work with other styles.
26 26
27 import 'dart:io'; 27 import 'dart:io';
28 import 'dart:convert'; 28 import 'dart:convert';
29 29
30 import 'package:crypto/crypto.dart'; 30 import 'package:crypto/crypto.dart';
31 import 'package:convert/convert.dart'; 31 import 'package:convert/convert.dart';
32 import 'package:utf/utf.dart'; 32 import 'package:utf/utf.dart';
33 33
34 // ---------------------------------------------------------------------- 34 // ----------------------------------------------------------------------
35 // Normalization of the text: removal or normalization of parts that 35 // Normalization of the text: removal or normalization of parts that
36 // do not affect the output from latex, such as white space. 36 // do not affect the output from latex, such as white space.
37 37
38 final commentRE = new RegExp(r"[^\\]%.*"); // NB: . does not match \n. 38 final commentRE = new RegExp(r"[^\\]%.*"); // NB: . does not match \n.
39 final whitespaceAllRE = new RegExp(r"^\s+$"); 39 final whitespaceAllRE = new RegExp(r"^\s+$");
40 final whitespaceRE = new RegExp(r"(?:(?=\s).){2,}"); // \s except end-of-line 40 final whitespaceRE = new RegExp(r"(?:(?=\s).){2,}"); // \s except end-of-line
41 41
42 /// Removes [match]ing part of [line], adjusting that part with the 42 /// Removes [match]ing part of [line], adjusting that part with the
43 /// given [startOffset] and [endOffset], bounded to be valid indices 43 /// given [startOffset] and [endOffset], bounded to be valid indices
44 /// into the string if needed, then inserts [glue] where text was 44 /// into the string if needed, then inserts [glue] where text was
45 /// removed. If there is no match then [line] is returned. 45 /// removed. If there is no match then [line] is returned.
46 cutMatch(line, match, {startOffset: 0, endOffset: 0, glue: ""}) { 46 cutMatch(line, match, {startOffset: 0, endOffset: 0, glue: ""}) {
47 if (match == null) return line; 47 if (match == null) return line;
48 var start = match.start + startOffset; 48 var start = match.start + startOffset;
49 var end = match.end + endOffset; 49 var end = match.end + endOffset;
50 var len = line.length; 50 var len = line.length;
51 if (start < 0) start = 0; 51 if (start < 0) start = 0;
52 if (end > len) end = len; 52 if (end > len) end = len;
53 return line.substring(0, start) + glue + line.substring(end); 53 return line.substring(0, start) + glue + line.substring(end);
54 } 54 }
55 55
56 cutRegexp(line, re, {startOffset: 0, endOffset: 0, glue: ""}) { 56 cutRegexp(line, re, {startOffset: 0, endOffset: 0, glue: ""}) {
57 return cutMatch(line, re.firstMatch(line), 57 return cutMatch(line, re.firstMatch(line),
58 startOffset: startOffset, 58 startOffset: startOffset, endOffset: endOffset, glue: glue);
59 endOffset: endOffset,
60 glue: glue);
61 } 59 }
62 60
63 /// Removes the rest of [line] starting from the beginning of the 61 /// Removes the rest of [line] starting from the beginning of the
64 /// given [match], and adjusting with the given [offset]. If there 62 /// given [match], and adjusting with the given [offset]. If there
65 /// is no match then [line] is returned. 63 /// is no match then [line] is returned.
66 cutFromMatch(line, match, {offset: 0, glue: ""}) { 64 cutFromMatch(line, match, {offset: 0, glue: ""}) {
67 if (match == null) return line; 65 if (match == null) return line;
68 return line.substring(0, match.start + offset) + glue; 66 return line.substring(0, match.start + offset) + glue;
69 } 67 }
70 68
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 var trimLine = line.trimLeft(); 105 var trimLine = line.trimLeft();
108 if (trimLine.isEmpty) return justEol(line); 106 if (trimLine.isEmpty) return justEol(line);
109 return trimLine.replaceAll(whitespaceRE, " "); 107 return trimLine.replaceAll(whitespaceRE, " ");
110 } 108 }
111 109
112 /// Reduces sequences of >1 white-space-only lines in [lines] to 1, 110 /// Reduces sequences of >1 white-space-only lines in [lines] to 1,
113 /// and sequences of >1 comment-only lines to 1. Treats comment-only 111 /// and sequences of >1 comment-only lines to 1. Treats comment-only
114 /// lines as white-space-only when they occur in white-space-only 112 /// lines as white-space-only when they occur in white-space-only
115 /// line blocks. 113 /// line blocks.
116 multilineNormalize(lines) { 114 multilineNormalize(lines) {
117 var afterBlankLines = false; // Does [line] succeed >0 empty lines? 115 var afterBlankLines = false; // Does [line] succeed >0 empty lines?
118 var afterCommentLines = false; // Does [line] succeed >0 commentOnly lines? 116 var afterCommentLines = false; // Does [line] succeed >0 commentOnly lines?
119 var newLines = new List(); 117 var newLines = new List();
120 for (var line in lines) { 118 for (var line in lines) {
121 if (afterBlankLines && afterCommentLines) { 119 if (afterBlankLines && afterCommentLines) {
122 // Previous line was both blank and a comment: not possible. 120 // Previous line was both blank and a comment: not possible.
123 throw "Bug, please report to eernst@"; 121 throw "Bug, please report to eernst@";
124 } else if (afterBlankLines && !afterCommentLines) { 122 } else if (afterBlankLines && !afterCommentLines) {
125 // At least one line before [line] is wsOnly. 123 // At least one line before [line] is wsOnly.
126 if (!isWsOnly(line)) { 124 if (!isWsOnly(line)) {
127 // Blank line block ended. 125 // Blank line block ended.
128 afterCommentLines = isCommentOnly(line); 126 afterCommentLines = isCommentOnly(line);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 /// Selects the elements in the normalization pipeline. 172 /// Selects the elements in the normalization pipeline.
175 normalize(line) => normalizeWhitespace(stripComment(line)); 173 normalize(line) => normalizeWhitespace(stripComment(line));
176 174
177 /// Selects the elements in the significant-spacing block 175 /// Selects the elements in the significant-spacing block
178 /// normalization pipeline. 176 /// normalization pipeline.
179 sispNormalize(line) => stripComment(line); 177 sispNormalize(line) => stripComment(line);
180 178
181 // Managing fragments with significant spacing. 179 // Managing fragments with significant spacing.
182 180
183 final dartCodeBeginRE = new RegExp(r"^\s*\\begin\s*\{dartCode\}"); 181 final dartCodeBeginRE = new RegExp(r"^\s*\\begin\s*\{dartCode\}");
184 final dartCodeEndRE = new RegExp (r"^\s*\\end\s*\{dartCode\}"); 182 final dartCodeEndRE = new RegExp(r"^\s*\\end\s*\{dartCode\}");
185 183
186 /// Recognizes beginning of dartCode block. 184 /// Recognizes beginning of dartCode block.
187 sispIsDartBegin(line) => line.contains(dartCodeBeginRE); 185 sispIsDartBegin(line) => line.contains(dartCodeBeginRE);
188 186
189 /// Recognizes end of dartCode block. 187 /// Recognizes end of dartCode block.
190 sispIsDartEnd(line) => line.contains(dartCodeEndRE); 188 sispIsDartEnd(line) => line.contains(dartCodeEndRE);
191 189
192 // ---------------------------------------------------------------------- 190 // ----------------------------------------------------------------------
193 // Analyzing the input to point out "interesting" lines 191 // Analyzing the input to point out "interesting" lines
194 192
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 263
266 /// Returns null except for \LMHash{} events, where it returns 264 /// Returns null except for \LMHash{} events, where it returns
267 /// the startLineNumber. This serves to specify a boundary because 265 /// the startLineNumber. This serves to specify a boundary because
268 /// the preceding \LMHash{} block should stop before the line of 266 /// the preceding \LMHash{} block should stop before the line of
269 /// this \LMHash{} command. Note that hash blocks may stop earlier, 267 /// this \LMHash{} command. Note that hash blocks may stop earlier,
270 /// because they cannot contain sectioning commands. 268 /// because they cannot contain sectioning commands.
271 getStartLineNumber() => null; 269 getStartLineNumber() => null;
272 } 270 }
273 271
274 class HashMarkerEvent extends HashEvent { 272 class HashMarkerEvent extends HashEvent {
275
276 // Line number of first line in block that gets hashed. 273 // Line number of first line in block that gets hashed.
277 var startLineNumber; 274 var startLineNumber;
278 275
279 // Highest possible number of first line after block that gets 276 // Highest possible number of first line after block that gets
280 // hashed (where the next \LMHash{} occurs). Note that this value 277 // hashed (where the next \LMHash{} occurs). Note that this value
281 // is not known initially (because that line has not yet been 278 // is not known initially (because that line has not yet been
282 // reached), so [endLineNumber] will be initialized in a separate 279 // reached), so [endLineNumber] will be initialized in a separate
283 // scan. Also note that the block may end earlier, because a block 280 // scan. Also note that the block may end earlier, because a block
284 // ends if it would otherwise include a sectioning command. 281 // ends if it would otherwise include a sectioning command.
285 var endLineNumber; 282 var endLineNumber;
286 283
287 HashMarkerEvent(this.startLineNumber); 284 HashMarkerEvent(this.startLineNumber);
288 285
289 setEndLineNumber(n) { endLineNumber = n; } 286 setEndLineNumber(n) {
287 endLineNumber = n;
288 }
289
290 getStartLineNumber() => startLineNumber; 290 getStartLineNumber() => startLineNumber;
291 } 291 }
292 292
293 class HashLabelEvent extends HashEvent { 293 class HashLabelEvent extends HashEvent {
294 var labelText; 294 var labelText;
295 HashLabelEvent(this.labelText); 295 HashLabelEvent(this.labelText);
296 } 296 }
297 297
298 class HashAnalyzer { 298 class HashAnalyzer {
299 // List of kinds of pending (= most recently seen) sectioning command. 299 // List of kinds of pending (= most recently seen) sectioning command.
(...skipping 24 matching lines...) Expand all
324 setPendingToParagraph() { 324 setPendingToParagraph() {
325 pendingSectioning = PENDING_IS_PARAGRAPH; 325 pendingSectioning = PENDING_IS_PARAGRAPH;
326 } 326 }
327 327
328 clearPending() { 328 clearPending() {
329 pendingSectioning = PENDING_IS_NONE; 329 pendingSectioning = PENDING_IS_NONE;
330 } 330 }
331 331
332 sectioningPrefix() { 332 sectioningPrefix() {
333 switch (pendingSectioning) { 333 switch (pendingSectioning) {
334 case PENDING_IS_SECTION: return "sec:"; 334 case PENDING_IS_SECTION:
335 case PENDING_IS_SUBSECTION: return "subsec:"; 335 return "sec:";
336 case PENDING_IS_SUBSUBSECTION: return "subsubsec:"; 336 case PENDING_IS_SUBSECTION:
337 case PENDING_IS_PARAGRAPH: return "par:"; 337 return "subsec:";
338 case PENDING_IS_SUBSUBSECTION:
339 return "subsubsec:";
340 case PENDING_IS_PARAGRAPH:
341 return "par:";
338 case PENDING_IS_NONE: 342 case PENDING_IS_NONE:
339 throw 343 throw "\\LMHash{..} should only be used after a sectioning command " +
340 "\\LMHash{..} should only be used after a sectioning command " +
341 "(\\section, \\subsection, \\subsubsection, \\paragraph)"; 344 "(\\section, \\subsection, \\subsubsection, \\paragraph)";
342 default: 345 default:
343 // set of PENDING_IS_.. was extended, but updates here omitted 346 // set of PENDING_IS_.. was extended, but updates here omitted
344 throw "Bug, please report to eernst@"; 347 throw "Bug, please report to eernst@";
345 } 348 }
346 } 349 }
347 350
348 analyze(line) { 351 analyze(line) {
349 var currentLineNumber = lineNumber++; 352 var currentLineNumber = lineNumber++;
350 if (isHashMarker(line)) { 353 if (isHashMarker(line)) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 // ---------------------------------------------------------------------- 389 // ----------------------------------------------------------------------
387 // Removal of non-normative elements of the text (rationale, commentary). 390 // Removal of non-normative elements of the text (rationale, commentary).
388 391
389 /// Returns [line] without the command [cmdName] (based on a match 392 /// Returns [line] without the command [cmdName] (based on a match
390 /// on "\\cmdName\s*{..}") starting at [startIndex]; note that it is 393 /// on "\\cmdName\s*{..}") starting at [startIndex]; note that it is
391 /// assumed but not checked that [line] contains "\\cmdType\s*{..", 394 /// assumed but not checked that [line] contains "\\cmdType\s*{..",
392 /// and note that the end of the {..} block is found via brace matching 395 /// and note that the end of the {..} block is found via brace matching
393 /// (i.e., nested {..} blocks are handled), but it may break if '{' is 396 /// (i.e., nested {..} blocks are handled), but it may break if '{' is
394 /// made an active character etc.etc. 397 /// made an active character etc.etc.
395 removeCommand(line, cmdName, startIndex) { 398 removeCommand(line, cmdName, startIndex) {
396 const BACKSLASH = 92; // char code for '\\'. 399 const BACKSLASH = 92; // char code for '\\'.
397 const BRACE_BEGIN = 123; // char code for '{'. 400 const BRACE_BEGIN = 123; // char code for '{'.
398 const BRACE_END = 125; // char code for '}'. 401 const BRACE_END = 125; // char code for '}'.
399 402
400 var blockStartIndex = startIndex + cmdName.length + 1; 403 var blockStartIndex = startIndex + cmdName.length + 1;
401 while (blockStartIndex < line.length && 404 while (blockStartIndex < line.length &&
402 line.codeUnitAt(blockStartIndex) != BRACE_BEGIN) { 405 line.codeUnitAt(blockStartIndex) != BRACE_BEGIN) {
403 blockStartIndex++; 406 blockStartIndex++;
404 } 407 }
405 blockStartIndex++; 408 blockStartIndex++;
406 if (blockStartIndex > line.length) { 409 if (blockStartIndex > line.length) {
407 throw "Bug, please report to eernst@"; 410 throw "Bug, please report to eernst@";
408 } 411 }
409 // [blockStartIndex] has index just after '{'. 412 // [blockStartIndex] has index just after '{'.
410 413
411 var afterEscape = false; // Is true iff [index] is just after '{'. 414 var afterEscape = false; // Is true iff [index] is just after '{'.
412 var braceLevel = 1; // Have seen so many '{'s minus so many '}'s. 415 var braceLevel = 1; // Have seen so many '{'s minus so many '}'s.
413 416
414 for (var index = blockStartIndex; index < line.length; index++) { 417 for (var index = blockStartIndex; index < line.length; index++) {
415 switch (line.codeUnitAt(index)) { 418 switch (line.codeUnitAt(index)) {
416 case BRACE_BEGIN: 419 case BRACE_BEGIN:
417 if (afterEscape) { 420 if (afterEscape) {
418 afterEscape = false; 421 afterEscape = false;
419 } else { 422 } else {
420 braceLevel++; 423 braceLevel++;
421 } 424 }
422 break; 425 break;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 // Recognition of line blocks, insertion of block hash into \LMHash{}. 474 // Recognition of line blocks, insertion of block hash into \LMHash{}.
472 475
473 final latexArgumentRE = new RegExp(r"\{.*\}"); 476 final latexArgumentRE = new RegExp(r"\{.*\}");
474 477
475 cleanupLine(line) => cutRegexp(line, commentRE, startOffset: 1).trimRight(); 478 cleanupLine(line) => cutRegexp(line, commentRE, startOffset: 1).trimRight();
476 479
477 /// Returns concatenation of all lines from [startIndex] in [lines] until 480 /// Returns concatenation of all lines from [startIndex] in [lines] until
478 /// a hash block terminator is encountered or [nextIndex] reached (if so, 481 /// a hash block terminator is encountered or [nextIndex] reached (if so,
479 /// the line lines[nextIndex] itself is not included); each line is cleaned 482 /// the line lines[nextIndex] itself is not included); each line is cleaned
480 /// up using [cleanupLine], and " " is inserted between the lines gathered. 483 /// up using [cleanupLine], and " " is inserted between the lines gathered.
481 gatherLines(lines, startIndex, nextIndex) => 484 gatherLines(lines, startIndex, nextIndex) => lines
482 lines.getRange(startIndex, nextIndex) 485 .getRange(startIndex, nextIndex)
483 .takeWhile(isntHashBlockTerminator) 486 .takeWhile(isntHashBlockTerminator)
484 .map(cleanupLine) 487 .map(cleanupLine)
485 .join(" "); 488 .join(" ");
486 489
487 /// Computes the hash value for the line block starting at [startIndex] 490 /// Computes the hash value for the line block starting at [startIndex]
488 /// in [lines], stopping just before [nextIndex]. SIDE EFFECT: 491 /// in [lines], stopping just before [nextIndex]. SIDE EFFECT:
489 /// Outputs the simplified text and its hash value to [listSink]. 492 /// Outputs the simplified text and its hash value to [listSink].
490 computeHashValue(lines, startIndex, nextIndex, listSink) { 493 computeHashValue(lines, startIndex, nextIndex, listSink) {
491 final gatheredLine = gatherLines(lines, startIndex, nextIndex); 494 final gatheredLine = gatherLines(lines, startIndex, nextIndex);
492 final simplifiedLine = simplifyLine(gatheredLine); 495 final simplifiedLine = simplifyLine(gatheredLine);
493 listSink.write(" % $simplifiedLine\n"); 496 listSink.write(" % $simplifiedLine\n");
494 var digest = sha1.convert(encodeUtf8(simplifiedLine)); 497 var digest = sha1.convert(encodeUtf8(simplifiedLine));
495 return digest.bytes; 498 return digest.bytes;
496 } 499 }
497 500
498 computeHashString(lines, startIndex, nextIndex, listSink) => 501 computeHashString(lines, startIndex, nextIndex, listSink) =>
499 hex.encode(computeHashValue(lines, 502 hex.encode(computeHashValue(lines, startIndex, nextIndex, listSink));
500 startIndex,
501 nextIndex,
502 listSink));
503 503
504 /// Computes and adds hashes to \LMHash{} lines in [lines] (which 504 /// Computes and adds hashes to \LMHash{} lines in [lines] (which
505 /// must be on the line numbers specified in [hashEvents]), and emits 505 /// must be on the line numbers specified in [hashEvents]), and emits
506 /// sectioning markers and hash values to [listSink], along with 506 /// sectioning markers and hash values to [listSink], along with
507 /// "comments" containing the simplified text (using the format 507 /// "comments" containing the simplified text (using the format
508 /// ' % <text>', where the text is one, long line, for easy grepping 508 /// ' % <text>', where the text is one, long line, for easy grepping
509 /// etc.). 509 /// etc.).
510 addHashMarks(lines, hashEvents, listSink) { 510 addHashMarks(lines, hashEvents, listSink) {
511 for (var hashEvent in hashEvents) { 511 for (var hashEvent in hashEvents) {
512 if (hashEvent is HashMarkerEvent) { 512 if (hashEvent is HashMarkerEvent) {
513 var start = hashEvent.startLineNumber; 513 var start = hashEvent.startLineNumber;
514 var end = hashEvent.endLineNumber; 514 var end = hashEvent.endLineNumber;
515 final hashValue = computeHashString(lines, start + 1, end, listSink); 515 final hashValue = computeHashString(lines, start + 1, end, listSink);
516 lines[start] = 516 lines[start] =
517 lines[start].replaceAll(latexArgumentRE, "{" + hashValue + "}"); 517 lines[start].replaceAll(latexArgumentRE, "{" + hashValue + "}");
518 listSink.write(" $hashValue\n"); 518 listSink.write(" $hashValue\n");
519 } else if (hashEvent is HashLabelEvent) { 519 } else if (hashEvent is HashLabelEvent) {
520 listSink.write("${hashEvent.labelText}\n"); 520 listSink.write("${hashEvent.labelText}\n");
521 } 521 }
522 } 522 }
523 } 523 }
524 524
525 /// Transforms LaTeX input to LaTeX output plus hash value list file. 525 /// Transforms LaTeX input to LaTeX output plus hash value list file.
526 main ([args]) { 526 main([args]) {
527 if (args.length != 3) { 527 if (args.length != 3) {
528 print("Usage: addlatexhash.dart <input-file> <output-file> <list-file>"); 528 print("Usage: addlatexhash.dart <input-file> <output-file> <list-file>");
529 throw "Received ${args.length} arguments, expected three"; 529 throw "Received ${args.length} arguments, expected three";
530 } 530 }
531 531
532 // Get LaTeX source. 532 // Get LaTeX source.
533 var inputFile = new File(args[0]); 533 var inputFile = new File(args[0]);
534 assert(inputFile.existsSync()); 534 assert(inputFile.existsSync());
535 var lines = inputFile.readAsLinesSync(); 535 var lines = inputFile.readAsLinesSync();
536 536
(...skipping 25 matching lines...) Expand all
562 normalizedLines = multilineNormalize(normalizedLines); 562 normalizedLines = multilineNormalize(normalizedLines);
563 563
564 // Insert hash values. 564 // Insert hash values.
565 var hashEvents = findHashEvents(normalizedLines); 565 var hashEvents = findHashEvents(normalizedLines);
566 addHashMarks(normalizedLines, hashEvents, listSink); 566 addHashMarks(normalizedLines, hashEvents, listSink);
567 567
568 // Produce/finalize output. 568 // Produce/finalize output.
569 outputFile.writeAsStringSync(normalizedLines.join()); 569 outputFile.writeAsStringSync(normalizedLines.join());
570 listSink.close(); 570 listSink.close();
571 } 571 }
OLDNEW
« no previous file with comments | « no previous file | tools/dart2js/class_generator/class_generator.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698