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

Side by Side Diff: pkg/analysis_server/tool/spec/codegen_tools.dart

Issue 473533003: Initial code to generate the Java types from the spec. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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) 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';
11 11
12 import 'package:html5lib/dom.dart' as dom; 12 import 'package:html5lib/dom.dart' as dom;
13 import 'package:path/path.dart'; 13 import 'package:path/path.dart';
14 14
15 import 'text_formatter.dart'; 15 import 'text_formatter.dart';
16 import 'html_tools.dart'; 16 import 'html_tools.dart';
17 17
18 /** 18 /**
19 * Join the given strings using camelCase. If [capitalize] is true, the first 19 * Join the given strings using camelCase. If [doCapitalize] is true, the first
20 * part will be capitalized as well. 20 * part will be capitalized as well.
21 */ 21 */
22 String camelJoin(List<String> parts, {bool capitalize: false}) { 22 String camelJoin(List<String> parts, {bool doCapitalize: false}) {
23 List<String> upcasedParts = <String>[]; 23 List<String> upcasedParts = <String>[];
24 for (int i = 0; i < parts.length; i++) { 24 for (int i = 0; i < parts.length; i++) {
25 if (i == 0 && !capitalize) { 25 if (i == 0 && !doCapitalize) {
26 upcasedParts.add(parts[i]); 26 upcasedParts.add(parts[i]);
27 } else { 27 } else {
28 upcasedParts.add(parts[i][0].toUpperCase() + parts[i].substring(1)); 28 upcasedParts.add(capitalize(parts[i]));
29 } 29 }
30 } 30 }
31 return upcasedParts.join(); 31 return upcasedParts.join();
32 } 32 }
33 33
34 /**
35 * Capitalize and return the passed String.
36 */
37 String capitalize(String string) {
38 return string[0].toUpperCase() + string.substring(1);
39 }
40
34 final RegExp trailingWhitespaceRegExp = new RegExp(r' +$', multiLine: true); 41 final RegExp trailingWhitespaceRegExp = new RegExp(r' +$', multiLine: true);
35 42
36 /** 43 /**
37 * Mixin class for generating code. 44 * Mixin class for generating code.
38 */ 45 */
39 class CodeGenerator { 46 class CodeGenerator {
40 _CodeGeneratorState _state; 47 _CodeGeneratorState _state;
41 48
42 /** 49 /**
43 * Execute [callback], collecting any code that is output using [write] 50 * Execute [callback], collecting any code that is output using [write]
(...skipping 25 matching lines...) Expand all
69 } 76 }
70 77
71 /** 78 /**
72 * Execute [callback], indenting any code it outputs by two spaces. 79 * Execute [callback], indenting any code it outputs by two spaces.
73 */ 80 */
74 void indent(void callback()) => indentSpecial(' ', ' ', callback); 81 void indent(void callback()) => indentSpecial(' ', ' ', callback);
75 82
76 /** 83 /**
77 * Execute [callback], using [additionalIndent] to indent any code it outputs. 84 * Execute [callback], using [additionalIndent] to indent any code it outputs.
78 */ 85 */
79 void indentBy(String additionalIndent, void callback()) => indentSpecial( 86 void indentBy(String additionalIndent, void callback()) => indentSpecial(addit ionalIndent, additionalIndent, callback);
80 additionalIndent, additionalIndent, callback);
81 87
82 /** 88 /**
83 * Execute [callback], using [additionalIndent] to indent any code it outputs. 89 * Execute [callback], using [additionalIndent] to indent any code it outputs.
84 * The first line of output is indented by [firstAdditionalIndent] instead of 90 * The first line of output is indented by [firstAdditionalIndent] instead of
85 * [additionalIndent]. 91 * [additionalIndent].
86 */ 92 */
87 void indentSpecial(String firstAdditionalIndent, String additionalIndent, void 93 void indentSpecial(String firstAdditionalIndent, String additionalIndent, void callback()) {
88 callback()) {
89 String oldNextIndent = _state.nextIndent; 94 String oldNextIndent = _state.nextIndent;
90 String oldIndent = _state.indent; 95 String oldIndent = _state.indent;
91 try { 96 try {
92 _state.nextIndent += firstAdditionalIndent; 97 _state.nextIndent += firstAdditionalIndent;
93 _state.indent += additionalIndent; 98 _state.indent += additionalIndent;
94 callback(); 99 callback();
95 } finally { 100 } finally {
96 _state.nextIndent = oldNextIndent; 101 _state.nextIndent = oldNextIndent;
97 _state.indent = oldIndent; 102 _state.indent = oldIndent;
98 } 103 }
(...skipping 13 matching lines...) Expand all
112 void docComment(List<dom.Node> docs, {int width: 79, bool javadocStyle: false} ) { 117 void docComment(List<dom.Node> docs, {int width: 79, bool javadocStyle: false} ) {
113 writeln('/**'); 118 writeln('/**');
114 indentBy(' * ', () { 119 indentBy(' * ', () {
115 write(nodesToText(docs, width - _state.indent.length, javadocStyle)); 120 write(nodesToText(docs, width - _state.indent.length, javadocStyle));
116 }); 121 });
117 writeln(' */'); 122 writeln(' */');
118 } 123 }
119 124
120 void outputHeader({bool javaStyle: false}) { 125 void outputHeader({bool javaStyle: false}) {
121 String header; 126 String header;
122 if(javaStyle) { 127 if (javaStyle) {
123 header = ''' 128 header = '''
124 /* 129 /*
125 * Copyright (c) 2014, the Dart project authors. 130 * Copyright (c) 2014, the Dart project authors.
126 * 131 *
127 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u se this file except 132 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u se this file except
128 * in compliance with the License. You may obtain a copy of the License at 133 * in compliance with the License. You may obtain a copy of the License at
129 * 134 *
130 * http://www.eclipse.org/legal/epl-v10.html 135 * http://www.eclipse.org/legal/epl-v10.html
131 * 136 *
132 * Unless required by applicable law or agreed to in writing, software distribut ed under the License 137 * Unless required by applicable law or agreed to in writing, software distribut ed under the License
133 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K IND, either express 138 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K IND, either express
134 * or implied. See the License for the specific language governing permissions a nd limitations under 139 * or implied. See the License for the specific language governing permissions a nd limitations under
135 * the License. 140 * the License.
136 * 141 *
137 * This file has been automatically generated. Please do not edit it manually. 142 * This file has been automatically generated. Please do not edit it manually.
138 * To regenerate the file, use the script "pkg/analysis_server/spec/generate_fil es". 143 * To regenerate the file, use the script "pkg/analysis_server/spec/generate_fil es".
139 */'''; 144 */''';
140 } 145 } else {
141 else {
142 header = ''' 146 header = '''
143 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 147 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
144 // for details. All rights reserved. Use of this source code is governed by a 148 // for details. All rights reserved. Use of this source code is governed by a
145 // BSD-style license that can be found in the LICENSE file. 149 // BSD-style license that can be found in the LICENSE file.
146 // 150 //
147 // This file has been automatically generated. Please do not edit it manually. 151 // This file has been automatically generated. Please do not edit it manually.
148 // To regenerate the file, use the script 152 // To regenerate the file, use the script
149 // "pkg/analysis_server/spec/generate_files". 153 // "pkg/analysis_server/spec/generate_files".
150 '''; 154 ''';
151 } 155 }
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 } else { 294 } else {
291 buffer.add(new dom.Text(lines.join('\n$indent'))); 295 buffer.add(new dom.Text(lines.join('\n$indent')));
292 indentNeeded = false; 296 indentNeeded = false;
293 } 297 }
294 } 298 }
295 } 299 }
296 300
297 /** 301 /**
298 * Type of functions used to compute the contents of generated files. 302 * Type of functions used to compute the contents of generated files.
299 */ 303 */
300 typedef String ContentsComputer(); 304 typedef String FileContentsComputer();
305
306 typedef Map<String, FileContentsComputer> DirectoryContentsComputer();
307
308 abstract class GeneratedContent {
309 bool check();
310 void generate();
311 }
301 312
302 /** 313 /**
303 * Class representing a single output file (either generated code or generated 314 * Class representing a single output file (either generated code or generated
304 * HTML). 315 * HTML).
305 */ 316 */
306 class GeneratedFile { 317 class GeneratedFile extends GeneratedContent {
307 /** 318 /**
308 * The output file to which generated output should be written, relative to 319 * The output file to which generated output should be written, relative to
309 * the "tool/spec" directory. This filename uses the posix path separator 320 * the "tool/spec" directory. This filename uses the posix path separator
310 * ('/') regardless of the OS. 321 * ('/') regardless of the OS.
311 */ 322 */
312 final String outputPath; 323 final String outputPath;
313 324
314 /** 325 /**
315 * Callback function which computes the file. 326 * Callback function which computes the file.
316 */ 327 */
317 final ContentsComputer computeContents; 328 final FileContentsComputer computeContents;
318 329
319 GeneratedFile(this.outputPath, this.computeContents); 330 GeneratedFile(this.outputPath, this.computeContents);
320 331
321 /** 332 /**
322 * Get a File object representing the output file. 333 * Get a File object representing the output file.
323 */ 334 */
324 File get outputFile => new File(joinAll(posix.split(outputPath))); 335 File get outputFile => new File(joinAll(posix.split(outputPath)));
325 336
326 /** 337 /**
327 * Check whether the file has the correct contents, and return true if it 338 * Check whether the file has the correct contents, and return true if it
328 * does. 339 * does.
329 */ 340 */
341 @override
330 bool check() { 342 bool check() {
331 String expectedContents = computeContents(); 343 String expectedContents = computeContents();
332 try { 344 try {
333 return expectedContents == outputFile.readAsStringSync(); 345 return expectedContents == outputFile.readAsStringSync();
334 } catch(e) { 346 } catch (e) {
335 // There was a problem reading the file (most likely because it didn't 347 // There was a problem reading the file (most likely because it didn't
336 // exist). Treat that the same as if the file doesn't have the expected 348 // exist). Treat that the same as if the file doesn't have the expected
337 // contents. 349 // contents.
338 return false; 350 return false;
339 } 351 }
340 } 352 }
341 353
342 /** 354 /**
343 * Replace the file with the correct contents. [spec] is the "tool/spec" 355 * Replace the file with the correct contents. [spec] is the "tool/spec"
344 * directory. If [spec] is unspecified, it is assumed to be the directory 356 * directory. If [spec] is unspecified, it is assumed to be the directory
345 * containing Platform.executable. 357 * containing Platform.executable.
346 */ 358 */
347 void generate() { 359 void generate() {
348 outputFile.writeAsStringSync(computeContents()); 360 outputFile.writeAsStringSync(computeContents());
349 } 361 }
350 } 362 }
363
364 class GeneratedDirectory extends GeneratedContent {
365
366 final String outputDirPath;
367 final DirectoryContentsComputer directoryContentsComputer;
368 GeneratedDirectory(this.outputDirPath, this.directoryContentsComputer);
369
370 /**
371 * Get a Directory object representing the output directory.
372 */
373 Directory get outputDir => new Directory(joinAll(posix.split(outputDirPath)));
374
375 @override
376 bool check() {
377 // TODO (jwren) the lists of files in the directories need to be compared to
378 // ensure no unexpected files have been added
379 Map<String, FileContentsComputer> map = directoryContentsComputer();
380 map.forEach((String file, FileContentsComputer fileContentsComputer) {
381 String expectedContents = fileContentsComputer();
382 File outputFile = new File(joinAll(posix.split(outputDirPath + file)));
383 try {
384 if (expectedContents != outputFile.readAsStringSync()) {
385 return false;
386 }
387 } catch (e) {
388 // There was a problem reading the file (most likely because it didn't
389 // exist). Treat that the same as if the file doesn't have the expected
390 // contents.
391 return false;
392 }
393 });
394 return true;
395 }
396
397 @override
398 void generate() {
399 // TODO (jwren) Delete contents in the directory first.
400 Map<String, FileContentsComputer> map = directoryContentsComputer();
401 map.forEach((String file, FileContentsComputer fileContentsComputer) {
402 File outputFile = new File(joinAll(posix.split(outputDirPath + file)));
403 outputFile.writeAsStringSync(fileContentsComputer());
404 });
405 }
406 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/tool/spec/codegen_java_types.dart ('k') | pkg/analysis_server/tool/spec/generate_all.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698