| Index: lib/src/dart_formatter.dart
|
| diff --git a/lib/src/dart_formatter.dart b/lib/src/dart_formatter.dart
|
| index 480f40de1099242c249bc5c6705d3be79d2f5ffa..5b59faa366d5ca85b9b1c0bbadd86fdb858b3a2c 100644
|
| --- a/lib/src/dart_formatter.dart
|
| +++ b/lib/src/dart_formatter.dart
|
| @@ -12,6 +12,58 @@ import 'package:analyzer/src/generated/source.dart';
|
| import 'error_listener.dart';
|
| import 'source_visitor.dart';
|
|
|
| +/// Describes a chunk of source code that is to be formatted or has been
|
| +/// formatted.
|
| +class SourceCode {
|
| + /// The [uri] where the source code is from.
|
| + ///
|
| + /// Used in error messages if the code cannot be parsed.
|
| + final String uri;
|
| +
|
| + /// The Dart source code text.
|
| + final String text;
|
| +
|
| + /// Whether the source is a compilation unit or a bare statement.
|
| + final bool isCompilationUnit;
|
| +
|
| + /// The offset in [text] where the selection begins, or `null` if there is
|
| + /// no selection.
|
| + final int selectionStart;
|
| +
|
| + /// The number of selected characters or `null` if there is no selection.
|
| + final int selectionLength;
|
| +
|
| + SourceCode(this.text,
|
| + {this.uri, this.isCompilationUnit: true, this.selectionStart,
|
| + this.selectionLength}) {
|
| + // Must either provide both selection bounds or neither.
|
| + if ((selectionStart == null) != (selectionLength == null)) {
|
| + throw new ArgumentError(
|
| + "Is selectionStart is provided, selectionLength must be too.");
|
| + }
|
| +
|
| + if (selectionStart != null) {
|
| + if (selectionStart < 0) {
|
| + throw new ArgumentError("selectionStart must be non-negative.");
|
| + }
|
| +
|
| + if (selectionStart > text.length) {
|
| + throw new ArgumentError("selectionStart must be within text.");
|
| + }
|
| + }
|
| +
|
| + if (selectionLength != null) {
|
| + if (selectionLength < 0) {
|
| + throw new ArgumentError("selectionLength must be non-negative.");
|
| + }
|
| +
|
| + if (selectionStart + selectionLength > text.length) {
|
| + throw new ArgumentError("selectionLength must end within text.");
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| /// Dart source code formatter.
|
| class DartFormatter {
|
| /// The string that newlines should use.
|
| @@ -38,7 +90,7 @@ class DartFormatter {
|
| DartFormatter({this.lineEnding, int pageWidth, this.indent: 0})
|
| : this.pageWidth = (pageWidth == null) ? 80 : pageWidth;
|
|
|
| - /// Format the given [source] string containing an entire Dart compilation
|
| + /// Formats the given [source] string containing an entire Dart compilation
|
| /// unit.
|
| ///
|
| /// If [uri] is given, it is a [String] or [Uri] used to identify the file
|
| @@ -54,20 +106,25 @@ class DartFormatter {
|
| throw new ArgumentError("uri must be `null`, a Uri, or a String.");
|
| }
|
|
|
| - return _format(source, uri: uri, isCompilationUnit: true);
|
| + return formatSource(
|
| + new SourceCode(source, uri: uri, isCompilationUnit: true)).text;
|
| }
|
|
|
| - /// Format the given [source] string containing a single Dart statement.
|
| + /// Formats the given [source] string containing a single Dart statement.
|
| String formatStatement(String source) {
|
| - return _format(source, isCompilationUnit: false);
|
| + return formatSource(new SourceCode(source, isCompilationUnit: false)).text;
|
| }
|
|
|
| - String _format(String source, {String uri, bool isCompilationUnit}) {
|
| + /// Formats the given [source].
|
| + ///
|
| + /// Returns a new [SourceCode] containing the formatted code and the resulting
|
| + /// selection, if any.
|
| + SourceCode formatSource(SourceCode source) {
|
| var errorListener = new ErrorListener();
|
|
|
| // Tokenize the source.
|
| - var reader = new CharSequenceReader(source);
|
| - var stringSource = new StringSource(source, uri);
|
| + var reader = new CharSequenceReader(source.text);
|
| + var stringSource = new StringSource(source.text, source.uri);
|
| var scanner = new Scanner(stringSource, reader, errorListener);
|
| var startToken = scanner.tokenize();
|
| var lineInfo = new LineInfo(scanner.lineStarts);
|
| @@ -78,7 +135,7 @@ class DartFormatter {
|
| // If the first newline is "\r\n", use that. Otherwise, use "\n".
|
| if (scanner.lineStarts.length > 1 &&
|
| scanner.lineStarts[1] >= 2 &&
|
| - source[scanner.lineStarts[1] - 2] == '\r') {
|
| + source.text[scanner.lineStarts[1] - 2] == '\r') {
|
| lineEnding = "\r\n";
|
| } else {
|
| lineEnding = "\n";
|
| @@ -92,7 +149,7 @@ class DartFormatter {
|
| parser.parseAsync = true;
|
|
|
| var node;
|
| - if (isCompilationUnit) {
|
| + if (source.isCompilationUnit) {
|
| node = parser.parseCompilationUnit(startToken);
|
| } else {
|
| node = parser.parseStatement(startToken);
|
| @@ -101,14 +158,7 @@ class DartFormatter {
|
| errorListener.throwIfErrors();
|
|
|
| // Format it.
|
| - var buffer = new StringBuffer();
|
| - var visitor = new SourceVisitor(this, lineInfo, source, buffer);
|
| -
|
| - visitor.run(node);
|
| -
|
| - // Be a good citizen, end with a newline.
|
| - if (isCompilationUnit) buffer.write(lineEnding);
|
| -
|
| - return buffer.toString();
|
| + var visitor = new SourceVisitor(this, lineInfo, source);
|
| + return visitor.run(node);
|
| }
|
| }
|
|
|