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

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

Issue 443873006: Add analysis server API specification and related tools. (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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * Tools for code generation.
7 */
8 library CodegenTools;
9
10 import 'package:html5lib/dom.dart' as dom;
11
12 import 'text_formatter.dart';
13 import 'html_tools.dart';
14
15 /**
16 * Join the given strings using camelCase. If [capitalize] is true, the first
17 * part will be capitalized as well.
18 */
19 String camelJoin(List<String> parts, {bool capitalize: false}) {
20 List<String> upcasedParts = <String>[];
21 for (int i = 0; i < parts.length; i++) {
22 if (i == 0 && !capitalize) {
23 upcasedParts.add(parts[i]);
24 } else {
25 upcasedParts.add(parts[i][0].toUpperCase() + parts[i].substring(1));
26 }
27 }
28 return upcasedParts.join();
29 }
30
31 final RegExp trailingWhitespaceRegExp = new RegExp(r' +$', multiLine: true);
32
33 /**
34 * Mixin class for generating code.
35 */
36 class CodeGenerator {
37 _CodeGeneratorState _state;
38
39 /**
40 * Execute [callback], collecting any code that is output using [write]
41 * or [writeln], and return the result as a string.
42 */
43 String collectCode(void callback()) {
44 _CodeGeneratorState oldState = _state;
45 try {
46 _state = new _CodeGeneratorState();
47 callback();
48 return _state.buffer.toString().replaceAll(trailingWhitespaceRegExp, '');
49 } finally {
50 _state = oldState;
51 }
52 }
53
54 /**
55 * Output text without ending the current line.
56 */
57 void write(Object obj) {
58 _state.write(obj.toString());
59 }
60
61 /**
62 * Output text, ending the current line.
63 */
64 void writeln([Object obj = '']) {
65 _state.write('$obj\n');
66 }
67
68 /**
69 * Execute [callback], indenting any code it outputs by two spaces.
70 */
71 void indent(void callback()) => indentSpecial(' ', ' ', callback);
72
73 /**
74 * Execute [callback], using [additionalIndent] to indent any code it outputs.
75 */
76 void indentBy(String additionalIndent, void callback()) => indentSpecial(
77 additionalIndent, additionalIndent, callback);
78
79 /**
80 * Execute [callback], using [additionalIndent] to indent any code it outputs.
81 * The first line of output is indented by [firstAdditionalIndent] instead of
82 * [additionalIndent].
83 */
84 void indentSpecial(String firstAdditionalIndent, String additionalIndent, void
85 callback()) {
86 String oldNextIndent = _state.nextIndent;
87 String oldIndent = _state.indent;
88 try {
89 _state.nextIndent += firstAdditionalIndent;
90 _state.indent += additionalIndent;
91 callback();
92 } finally {
93 _state.nextIndent = oldNextIndent;
94 _state.indent = oldIndent;
95 }
96 }
97
98 /**
99 * Measure the width of the current indentation level.
100 */
101 int get indentWidth => _state.nextIndent.length;
102
103 /**
104 * Generate a doc comment based on the HTML in [docs].
105 *
106 * If [javadocStyle] is true, then the output is compatable with Javadoc,
107 * which understands certain HTML constructs.
108 */
109 void docComment(List<dom.Node> docs, bool javadocStyle) {
110 writeln('/**');
111 indentBy(' * ', () {
112 write(nodesToText(docs, 79 - _state.indent.length, javadocStyle));
113 });
114 writeln(' */');
115 }
116
117 void outputHeader() {
118 String header =
119 '''
120 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file');
121 // for details. All rights reserved. Use of this source code is governed by a
122 // BSD-style license that can be found in the LICENSE file.
123 //
124 // This file has been automatically generated. Please do not edit it manually.
125 // To regenerate the file, use the script
126 // "pkg/analysis_server/spec/generate_files".
127 ''';
128 writeln(header.trim());
129 writeln();
130 }
131 }
132
133 /**
134 * State used by [CodeGenerator].
135 */
136 class _CodeGeneratorState {
137 StringBuffer buffer = new StringBuffer();
138 String nextIndent = '';
139 String indent = '';
140 bool indentNeeded = true;
141
142 void write(String text) {
143 List<String> lines = text.split('\n');
144 for (int i = 0; i < lines.length; i++) {
145 if (i == lines.length - 1 && lines[i].isEmpty) {
146 break;
147 }
148 if (indentNeeded) {
149 buffer.write(nextIndent);
150 nextIndent = indent;
151 }
152 indentNeeded = false;
153 buffer.write(lines[i]);
154 if (i != lines.length - 1) {
155 buffer.writeln();
156 indentNeeded = true;
157 }
158 }
159 }
160 }
161
162 /**
163 * Mixin class for generating HTML representations of code that are suitable
164 * for enclosing inside a <pre> element.
165 */
166 abstract class HtmlCodeGenerator {
167 _HtmlCodeGeneratorState _state;
168
169 /**
170 * Execute [callback], collecting any code that is output using [write],
171 * [writeln], [add], or [addAll], and return the result as a list of DOM
172 * nodes.
173 */
174 List<dom.Node> collectHtml(void callback()) {
175 _HtmlCodeGeneratorState oldState = _state;
176 try {
177 _state = new _HtmlCodeGeneratorState();
178 if (callback != null) {
179 callback();
180 }
181 return _state.buffer;
182 } finally {
183 _state = oldState;
184 }
185 }
186
187 /**
188 * Add the given [node] to the HTML output.
189 */
190 void add(dom.Node node) {
191 _state.add(node);
192 }
193
194 /**
195 * Add the given [nodes] to the HTML output.
196 */
197 void addAll(Iterable<dom.Node> nodes) {
198 for (dom.Node node in nodes) {
199 _state.add(node);
200 }
201 }
202
203 /**
204 * Output text without ending the current line.
205 */
206 void write(Object obj) {
207 _state.write(obj.toString());
208 }
209
210 /**
211 * Output text, ending the current line.
212 */
213 void writeln([Object obj = '']) {
214 _state.write('$obj\n');
215 }
216
217 /**
218 * Execute [callback], indenting any code it outputs by two spaces.
219 */
220 void indent(void callback()) {
221 String oldIndent = _state.indent;
222 try {
223 _state.indent += ' ';
224 callback();
225 } finally {
226 _state.indent = oldIndent;
227 }
228 }
229
230 /**
231 * Execute [callback], wrapping its output in an element with the given
232 * [name] and [attributes].
233 */
234 void element(String name, Map<String, String> attributes, [void callback()]) {
235 add(makeElement(name, attributes, collectHtml(callback)));
236 }
237 }
238
239 /**
240 * State used by [HtmlCodeGenerator].
241 */
242 class _HtmlCodeGeneratorState {
243 List<dom.Node> buffer = <dom.Node>[];
244 String indent = '';
245 bool indentNeeded = true;
246
247 void add(dom.Node node) {
248 if (node is dom.Text) {
249 write(node.text);
250 } else {
251 buffer.add(node);
252 }
253 }
254
255 void write(String text) {
256 if (text.isEmpty) {
257 return;
258 }
259 if (indentNeeded) {
260 buffer.add(new dom.Text(indent));
261 }
262 List<String> lines = text.split('\n');
263 if (lines.last.isEmpty) {
264 lines.removeLast();
265 buffer.add(new dom.Text(lines.join('\n$indent') + '\n'));
266 indentNeeded = true;
267 } else {
268 buffer.add(new dom.Text(lines.join('\n$indent')));
269 indentNeeded = false;
270 }
271 }
272 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698