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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_server/spec/codegen_tools.dart
diff --git a/pkg/analysis_server/spec/codegen_tools.dart b/pkg/analysis_server/spec/codegen_tools.dart
new file mode 100644
index 0000000000000000000000000000000000000000..97756edbf64024b767a52ab487f7d9d3b413bb32
--- /dev/null
+++ b/pkg/analysis_server/spec/codegen_tools.dart
@@ -0,0 +1,272 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Tools for code generation.
+ */
+library CodegenTools;
+
+import 'package:html5lib/dom.dart' as dom;
+
+import 'text_formatter.dart';
+import 'html_tools.dart';
+
+/**
+ * Join the given strings using camelCase. If [capitalize] is true, the first
+ * part will be capitalized as well.
+ */
+String camelJoin(List<String> parts, {bool capitalize: false}) {
+ List<String> upcasedParts = <String>[];
+ for (int i = 0; i < parts.length; i++) {
+ if (i == 0 && !capitalize) {
+ upcasedParts.add(parts[i]);
+ } else {
+ upcasedParts.add(parts[i][0].toUpperCase() + parts[i].substring(1));
+ }
+ }
+ return upcasedParts.join();
+}
+
+final RegExp trailingWhitespaceRegExp = new RegExp(r' +$', multiLine: true);
+
+/**
+ * Mixin class for generating code.
+ */
+class CodeGenerator {
+ _CodeGeneratorState _state;
+
+ /**
+ * Execute [callback], collecting any code that is output using [write]
+ * or [writeln], and return the result as a string.
+ */
+ String collectCode(void callback()) {
+ _CodeGeneratorState oldState = _state;
+ try {
+ _state = new _CodeGeneratorState();
+ callback();
+ return _state.buffer.toString().replaceAll(trailingWhitespaceRegExp, '');
+ } finally {
+ _state = oldState;
+ }
+ }
+
+ /**
+ * Output text without ending the current line.
+ */
+ void write(Object obj) {
+ _state.write(obj.toString());
+ }
+
+ /**
+ * Output text, ending the current line.
+ */
+ void writeln([Object obj = '']) {
+ _state.write('$obj\n');
+ }
+
+ /**
+ * Execute [callback], indenting any code it outputs by two spaces.
+ */
+ void indent(void callback()) => indentSpecial(' ', ' ', callback);
+
+ /**
+ * Execute [callback], using [additionalIndent] to indent any code it outputs.
+ */
+ void indentBy(String additionalIndent, void callback()) => indentSpecial(
+ additionalIndent, additionalIndent, callback);
+
+ /**
+ * Execute [callback], using [additionalIndent] to indent any code it outputs.
+ * The first line of output is indented by [firstAdditionalIndent] instead of
+ * [additionalIndent].
+ */
+ void indentSpecial(String firstAdditionalIndent, String additionalIndent, void
+ callback()) {
+ String oldNextIndent = _state.nextIndent;
+ String oldIndent = _state.indent;
+ try {
+ _state.nextIndent += firstAdditionalIndent;
+ _state.indent += additionalIndent;
+ callback();
+ } finally {
+ _state.nextIndent = oldNextIndent;
+ _state.indent = oldIndent;
+ }
+ }
+
+ /**
+ * Measure the width of the current indentation level.
+ */
+ int get indentWidth => _state.nextIndent.length;
+
+ /**
+ * Generate a doc comment based on the HTML in [docs].
+ *
+ * If [javadocStyle] is true, then the output is compatable with Javadoc,
+ * which understands certain HTML constructs.
+ */
+ void docComment(List<dom.Node> docs, bool javadocStyle) {
+ writeln('/**');
+ indentBy(' * ', () {
+ write(nodesToText(docs, 79 - _state.indent.length, javadocStyle));
+ });
+ writeln(' */');
+ }
+
+ void outputHeader() {
+ String header =
+ '''
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file');
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// This file has been automatically generated. Please do not edit it manually.
+// To regenerate the file, use the script
+// "pkg/analysis_server/spec/generate_files".
+''';
+ writeln(header.trim());
+ writeln();
+ }
+}
+
+/**
+ * State used by [CodeGenerator].
+ */
+class _CodeGeneratorState {
+ StringBuffer buffer = new StringBuffer();
+ String nextIndent = '';
+ String indent = '';
+ bool indentNeeded = true;
+
+ void write(String text) {
+ List<String> lines = text.split('\n');
+ for (int i = 0; i < lines.length; i++) {
+ if (i == lines.length - 1 && lines[i].isEmpty) {
+ break;
+ }
+ if (indentNeeded) {
+ buffer.write(nextIndent);
+ nextIndent = indent;
+ }
+ indentNeeded = false;
+ buffer.write(lines[i]);
+ if (i != lines.length - 1) {
+ buffer.writeln();
+ indentNeeded = true;
+ }
+ }
+ }
+}
+
+/**
+ * Mixin class for generating HTML representations of code that are suitable
+ * for enclosing inside a <pre> element.
+ */
+abstract class HtmlCodeGenerator {
+ _HtmlCodeGeneratorState _state;
+
+ /**
+ * Execute [callback], collecting any code that is output using [write],
+ * [writeln], [add], or [addAll], and return the result as a list of DOM
+ * nodes.
+ */
+ List<dom.Node> collectHtml(void callback()) {
+ _HtmlCodeGeneratorState oldState = _state;
+ try {
+ _state = new _HtmlCodeGeneratorState();
+ if (callback != null) {
+ callback();
+ }
+ return _state.buffer;
+ } finally {
+ _state = oldState;
+ }
+ }
+
+ /**
+ * Add the given [node] to the HTML output.
+ */
+ void add(dom.Node node) {
+ _state.add(node);
+ }
+
+ /**
+ * Add the given [nodes] to the HTML output.
+ */
+ void addAll(Iterable<dom.Node> nodes) {
+ for (dom.Node node in nodes) {
+ _state.add(node);
+ }
+ }
+
+ /**
+ * Output text without ending the current line.
+ */
+ void write(Object obj) {
+ _state.write(obj.toString());
+ }
+
+ /**
+ * Output text, ending the current line.
+ */
+ void writeln([Object obj = '']) {
+ _state.write('$obj\n');
+ }
+
+ /**
+ * Execute [callback], indenting any code it outputs by two spaces.
+ */
+ void indent(void callback()) {
+ String oldIndent = _state.indent;
+ try {
+ _state.indent += ' ';
+ callback();
+ } finally {
+ _state.indent = oldIndent;
+ }
+ }
+
+ /**
+ * Execute [callback], wrapping its output in an element with the given
+ * [name] and [attributes].
+ */
+ void element(String name, Map<String, String> attributes, [void callback()]) {
+ add(makeElement(name, attributes, collectHtml(callback)));
+ }
+}
+
+/**
+ * State used by [HtmlCodeGenerator].
+ */
+class _HtmlCodeGeneratorState {
+ List<dom.Node> buffer = <dom.Node>[];
+ String indent = '';
+ bool indentNeeded = true;
+
+ void add(dom.Node node) {
+ if (node is dom.Text) {
+ write(node.text);
+ } else {
+ buffer.add(node);
+ }
+ }
+
+ void write(String text) {
+ if (text.isEmpty) {
+ return;
+ }
+ if (indentNeeded) {
+ buffer.add(new dom.Text(indent));
+ }
+ List<String> lines = text.split('\n');
+ if (lines.last.isEmpty) {
+ lines.removeLast();
+ buffer.add(new dom.Text(lines.join('\n$indent') + '\n'));
+ indentNeeded = true;
+ } else {
+ buffer.add(new dom.Text(lines.join('\n$indent')));
+ indentNeeded = false;
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698