Index: lib/src/line_writer.dart |
diff --git a/lib/src/line_writer.dart b/lib/src/line_writer.dart |
index 2a69ae50b3b25c5d71ce441dc890b37706bbe891..87bfb4889a6e9fbf6f1898bc8b822f4d0b15b3a5 100644 |
--- a/lib/src/line_writer.dart |
+++ b/lib/src/line_writer.dart |
@@ -11,32 +11,6 @@ import 'line_splitter.dart'; |
import 'multisplit.dart'; |
import 'whitespace.dart'; |
-/// A comment in the source, with a bit of information about the surrounding |
-/// whitespace. |
-class SourceComment { |
- /// The text of the comment, including `//`, `/*`, and `*/`. |
- final String text; |
- |
- /// The number of newlines between the comment or token preceding this comment |
- /// and the beginning of this one. |
- /// |
- /// Will be zero if the comment is a trailing one. |
- final int linesBefore; |
- |
- /// Whether this comment is a line comment. |
- final bool isLineComment; |
- |
- /// Whether this comment starts at column one in the source. |
- /// |
- /// Comments that start at the start of the line will not be indented in the |
- /// output. This way, commented out chunks of code do not get erroneously |
- /// re-indented. |
- final bool isStartOfLine; |
- |
- SourceComment(this.text, this.linesBefore, |
- {this.isLineComment, this.isStartOfLine}); |
-} |
- |
/// Takes the incremental serialized output of [SourceVisitor]--the source text |
/// along with any comments and preserved whitespace--and produces a coherent |
/// series of [Chunk]s which can then be split into physical lines. |
@@ -47,7 +21,9 @@ class SourceComment { |
class LineWriter { |
final DartFormatter _formatter; |
- final StringBuffer _buffer; |
+ final SourceCode _source; |
+ |
+ final _buffer = new StringBuffer(); |
final _chunks = <Chunk>[]; |
@@ -161,6 +137,18 @@ class LineWriter { |
return _chunks.length; |
} |
+ /// The offset in [_buffer] where the selection starts in the formatted code. |
+ /// |
+ /// This will be `null` if there is no selection or the writer hasn't reached |
+ /// the beginning of the selection yet. |
+ int _selectionStart; |
+ |
+ /// The length in [_buffer] of the selection in the formatted code. |
+ /// |
+ /// This will be `null` if there is no selection or the writer hasn't reached |
+ /// the end of the selection yet. |
+ int _selectionLength; |
+ |
/// Whether there is pending whitespace that depends on the number of |
/// newlines in the source. |
/// |
@@ -174,7 +162,7 @@ class LineWriter { |
/// The number of characters of code that can fit in a single line. |
int get pageWidth => _formatter.pageWidth; |
- LineWriter(this._formatter, this._buffer) { |
+ LineWriter(this._formatter, this._source) { |
indent(_formatter.indent); |
_beginningIndent = _formatter.indent; |
} |
@@ -298,6 +286,14 @@ class LineWriter { |
_writeText(comment.text); |
+ if (comment.selectionStart != null) { |
+ startSelectionFromEnd(comment.text.length - comment.selectionStart); |
+ } |
+ |
+ if (comment.selectionEnd != null) { |
+ endSelectionFromEnd(comment.text.length - comment.selectionEnd); |
+ } |
+ |
// Make sure there is at least one newline after a line comment and allow |
// one or two after a block comment that has nothing after it. |
var linesAfter; |
@@ -452,9 +448,51 @@ class LineWriter { |
_nesting--; |
} |
- /// Finish writing the last line. |
- void end() { |
+ /// Marks the selection starting point as occurring [fromEnd] characters to |
+ /// the left of the end of what's currently been written. |
+ /// |
+ /// It counts backwards from the end because this is called *after* the chunk |
+ /// of text containing the selection has been output. |
+ void startSelectionFromEnd(int fromEnd) { |
+ assert(_chunks.isNotEmpty); |
+ _chunks.last.startSelectionFromEnd(fromEnd); |
+ } |
+ |
+ /// Marks the selection ending point as occurring [fromEnd] characters to the |
+ /// left of the end of what's currently been written. |
+ /// |
+ /// It counts backwards from the end because this is called *after* the chunk |
+ /// of text containing the selection has been output. |
+ void endSelectionFromEnd(int fromEnd) { |
+ assert(_chunks.isNotEmpty); |
+ _chunks.last.endSelectionFromEnd(fromEnd); |
+ } |
+ |
+ /// Finishes writing and returns a [SourceCode] containing the final output |
+ /// and updated selection, if any. |
+ SourceCode end() { |
if (_chunks.isNotEmpty) _completeLine(); |
+ |
+ // Be a good citizen, end with a newline. |
+ if (_source.isCompilationUnit) _buffer.write(_formatter.lineEnding); |
+ |
+ // If we haven't hit the beginning and/or end of the selection yet, they |
+ // must be at the very end of the code. |
+ if (_source.selectionStart != null) { |
+ if (_selectionStart == null) { |
+ _selectionStart = _buffer.length; |
+ } |
+ |
+ if (_selectionLength == null) { |
+ _selectionLength = _buffer.length - _selectionStart; |
+ } |
+ } |
+ |
+ return new SourceCode(_buffer.toString(), |
+ uri: _source.uri, |
+ isCompilationUnit: _source.isCompilationUnit, |
+ selectionStart: _selectionStart, |
+ selectionLength: _selectionLength); |
} |
/// Writes the current pending [Whitespace] to the output, if any. |
@@ -648,9 +686,12 @@ class LineWriter { |
_buffer.write(_formatter.lineEnding); |
} |
- var splitter = new LineSplitter(_formatter.lineEnding, |
- _formatter.pageWidth, _chunks, _spans, _beginningIndent); |
- splitter.apply(_buffer); |
+ var splitter = new LineSplitter(_formatter.lineEnding, _formatter.pageWidth, |
+ _chunks, _spans, _beginningIndent); |
+ var selection = splitter.apply(_buffer); |
+ |
+ if (selection[0] != null) _selectionStart = selection[0]; |
+ if (selection[1] != null) _selectionLength = selection[1] - _selectionStart; |
} |
/// Handles multisplits when a hard line occurs. |