| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 * Tools for code generation. | 6 * Tools for code generation. |
| 7 */ | 7 */ |
| 8 library codegen.tools; | 8 library codegen.tools; |
| 9 | 9 |
| 10 import 'dart:io'; | 10 import 'dart:io'; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 | 70 |
| 71 /** | 71 /** |
| 72 * Execute [callback], collecting any code that is output using [write] | 72 * Execute [callback], collecting any code that is output using [write] |
| 73 * or [writeln], and return the result as a string. | 73 * or [writeln], and return the result as a string. |
| 74 */ | 74 */ |
| 75 String collectCode(void callback(), {bool removeTrailingNewLine: false}) { | 75 String collectCode(void callback(), {bool removeTrailingNewLine: false}) { |
| 76 _CodeGeneratorState oldState = _state; | 76 _CodeGeneratorState oldState = _state; |
| 77 try { | 77 try { |
| 78 _state = new _CodeGeneratorState(); | 78 _state = new _CodeGeneratorState(); |
| 79 callback(); | 79 callback(); |
| 80 var text = _state.buffer.toString().replaceAll(trailingSpacesInLineRegExp,
''); | 80 var text = |
| 81 _state.buffer.toString().replaceAll(trailingSpacesInLineRegExp, ''); |
| 81 if (!removeTrailingNewLine) { | 82 if (!removeTrailingNewLine) { |
| 82 return text; | 83 return text; |
| 83 } else { | 84 } else { |
| 84 return text.replaceAll(trailingWhitespaceRegExp, ''); | 85 return text.replaceAll(trailingWhitespaceRegExp, ''); |
| 85 } | 86 } |
| 86 } finally { | 87 } finally { |
| 87 _state = oldState; | 88 _state = oldState; |
| 88 } | 89 } |
| 89 } | 90 } |
| 90 | 91 |
| 91 /** | 92 /** |
| 92 * Generate a doc comment based on the HTML in [docs]. | 93 * Generate a doc comment based on the HTML in [docs]. |
| 93 * | 94 * |
| 94 * When generating java code, the output is compatible with Javadoc, which | 95 * When generating java code, the output is compatible with Javadoc, which |
| 95 * understands certain HTML constructs. | 96 * understands certain HTML constructs. |
| 96 */ | 97 */ |
| 97 void docComment(List<dom.Node> docs, {bool removeTrailingNewLine: false}) { | 98 void docComment(List<dom.Node> docs, {bool removeTrailingNewLine: false}) { |
| 98 if (containsOnlyWhitespace(docs)) return; | 99 if (containsOnlyWhitespace(docs)) return; |
| 99 writeln(codeGeneratorSettings.docCommentStartMarker); | 100 writeln(codeGeneratorSettings.docCommentStartMarker); |
| 100 int width = codeGeneratorSettings.commentLineLength; | 101 int width = codeGeneratorSettings.commentLineLength; |
| 101 bool javadocStyle = codeGeneratorSettings.languageName == 'java'; | 102 bool javadocStyle = codeGeneratorSettings.languageName == 'java'; |
| 102 indentBy(codeGeneratorSettings.docCommentLineLeader, () { | 103 indentBy(codeGeneratorSettings.docCommentLineLeader, () { |
| 103 write(nodesToText(docs, width - _state.indent.length, javadocStyle, | 104 write(nodesToText(docs, width - _state.indent.length, javadocStyle, |
| 104 removeTrailingNewLine: removeTrailingNewLine)); | 105 removeTrailingNewLine: removeTrailingNewLine)); |
| 105 }); | 106 }); |
| 106 writeln(codeGeneratorSettings.docCommentEndMarker); | 107 writeln(codeGeneratorSettings.docCommentEndMarker); |
| 107 } | 108 } |
| 108 | 109 |
| 109 /** | 110 /** |
| 110 * Execute [callback], indenting any code it outputs. | 111 * Execute [callback], indenting any code it outputs. |
| 111 */ | 112 */ |
| 112 void indent(void callback()) { | 113 void indent(void callback()) { |
| 113 indentSpecial(codeGeneratorSettings.indent, codeGeneratorSettings.indent, | 114 indentSpecial( |
| 114 callback); | 115 codeGeneratorSettings.indent, codeGeneratorSettings.indent, callback); |
| 115 } | 116 } |
| 116 | 117 |
| 117 /** | 118 /** |
| 118 * Execute [callback], using [additionalIndent] to indent any code it outputs. | 119 * Execute [callback], using [additionalIndent] to indent any code it outputs. |
| 119 */ | 120 */ |
| 120 void indentBy(String additionalIndent, void callback()) => | 121 void indentBy(String additionalIndent, void callback()) => |
| 121 indentSpecial(additionalIndent, additionalIndent, callback); | 122 indentSpecial(additionalIndent, additionalIndent, callback); |
| 122 | 123 |
| 123 /** | 124 /** |
| 124 * Execute [callback], using [additionalIndent] to indent any code it outputs. | 125 * Execute [callback], using [additionalIndent] to indent any code it outputs. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 /** | 244 /** |
| 244 * Line length for doc comment lines. | 245 * Line length for doc comment lines. |
| 245 */ | 246 */ |
| 246 int commentLineLength; | 247 int commentLineLength; |
| 247 | 248 |
| 248 /** | 249 /** |
| 249 * String used for indenting code. | 250 * String used for indenting code. |
| 250 */ | 251 */ |
| 251 String indent; | 252 String indent; |
| 252 | 253 |
| 253 CodeGeneratorSettings({this.languageName: 'java', | 254 CodeGeneratorSettings( |
| 254 this.lineCommentLineLeader: '// ', this.docCommentStartMarker: '/**', | 255 {this.languageName: 'java', |
| 255 this.docCommentLineLeader: ' * ', this.docCommentEndMarker: ' */', | 256 this.lineCommentLineLeader: '// ', |
| 256 this.commentLineLength: 99, this.indent: ' '}); | 257 this.docCommentStartMarker: '/**', |
| 258 this.docCommentLineLeader: ' * ', |
| 259 this.docCommentEndMarker: ' */', |
| 260 this.commentLineLength: 99, |
| 261 this.indent: ' '}); |
| 257 } | 262 } |
| 258 | 263 |
| 259 abstract class GeneratedContent { | 264 abstract class GeneratedContent { |
| 260 FileSystemEntity get outputFile; | 265 FileSystemEntity get outputFile; |
| 261 bool check(); | 266 bool check(); |
| 262 void generate(); | 267 void generate(); |
| 263 } | 268 } |
| 264 | 269 |
| 265 /** | 270 /** |
| 266 * Class representing a single output directory (either generated code or | 271 * Class representing a single output directory (either generated code or |
| 267 * generated HTML). No other content should exist in the directory. | 272 * generated HTML). No other content should exist in the directory. |
| 268 */ | 273 */ |
| 269 class GeneratedDirectory extends GeneratedContent { | 274 class GeneratedDirectory extends GeneratedContent { |
| 270 | |
| 271 /** | 275 /** |
| 272 * The path to the directory that will have the generated content. | 276 * The path to the directory that will have the generated content. |
| 273 */ | 277 */ |
| 274 final String outputDirPath; | 278 final String outputDirPath; |
| 275 | 279 |
| 276 /** | 280 /** |
| 277 * Callback function that computes the directory contents. | 281 * Callback function that computes the directory contents. |
| 278 */ | 282 */ |
| 279 final DirectoryContentsComputer directoryContentsComputer; | 283 final DirectoryContentsComputer directoryContentsComputer; |
| 280 | 284 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 301 new File(joinAll(posix.split(posix.join(outputDirPath, file)))); | 305 new File(joinAll(posix.split(posix.join(outputDirPath, file)))); |
| 302 String actualContents = outputFile.readAsStringSync(); | 306 String actualContents = outputFile.readAsStringSync(); |
| 303 // Normalize Windows line endings to Unix line endings so that the | 307 // Normalize Windows line endings to Unix line endings so that the |
| 304 // comparison doesn't fail on Windows. | 308 // comparison doesn't fail on Windows. |
| 305 actualContents = actualContents.replaceAll('\r\n', '\n'); | 309 actualContents = actualContents.replaceAll('\r\n', '\n'); |
| 306 if (expectedContents != actualContents) { | 310 if (expectedContents != actualContents) { |
| 307 return false; | 311 return false; |
| 308 } | 312 } |
| 309 } | 313 } |
| 310 int nonHiddenFileCount = 0; | 314 int nonHiddenFileCount = 0; |
| 311 outputFile.listSync(recursive: false, followLinks: false).forEach( | 315 outputFile |
| 312 (FileSystemEntity fileSystemEntity) { | 316 .listSync(recursive: false, followLinks: false) |
| 317 .forEach((FileSystemEntity fileSystemEntity) { |
| 313 if (fileSystemEntity is File && | 318 if (fileSystemEntity is File && |
| 314 !basename(fileSystemEntity.path).startsWith('.')) { | 319 !basename(fileSystemEntity.path).startsWith('.')) { |
| 315 nonHiddenFileCount++; | 320 nonHiddenFileCount++; |
| 316 } | 321 } |
| 317 }); | 322 }); |
| 318 if (nonHiddenFileCount != map.length) { | 323 if (nonHiddenFileCount != map.length) { |
| 319 // The number of files generated doesn't match the number we expected to | 324 // The number of files generated doesn't match the number we expected to |
| 320 // generate. | 325 // generate. |
| 321 return false; | 326 return false; |
| 322 } | 327 } |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 if (lines.last.isEmpty) { | 548 if (lines.last.isEmpty) { |
| 544 lines.removeLast(); | 549 lines.removeLast(); |
| 545 buffer.add(new dom.Text(lines.join('\n$indent') + '\n')); | 550 buffer.add(new dom.Text(lines.join('\n$indent') + '\n')); |
| 546 indentNeeded = true; | 551 indentNeeded = true; |
| 547 } else { | 552 } else { |
| 548 buffer.add(new dom.Text(lines.join('\n$indent'))); | 553 buffer.add(new dom.Text(lines.join('\n$indent'))); |
| 549 indentNeeded = false; | 554 indentNeeded = false; |
| 550 } | 555 } |
| 551 } | 556 } |
| 552 } | 557 } |
| OLD | NEW |