| Index: lib/src/line_writer.dart
|
| diff --git a/lib/src/line_writer.dart b/lib/src/line_writer.dart
|
| index 25a140a803c84cb114b1ef470e9afa6cdfe0a33e..0477e2f9966fd9baedd14840c0f3a0fd67bdc4aa 100644
|
| --- a/lib/src/line_writer.dart
|
| +++ b/lib/src/line_writer.dart
|
| @@ -472,7 +472,7 @@ class LineWriter {
|
| /// Finishes writing and returns a [SourceCode] containing the final output
|
| /// and updated selection, if any.
|
| SourceCode end() {
|
| - if (_chunks.isNotEmpty) _completeLine();
|
| + if (_chunks.isNotEmpty) _completeLine(_chunks.length);
|
|
|
| // Be a good citizen, end with a newline.
|
| if (_source.isCompilationUnit) _buffer.write(_formatter.lineEnding);
|
| @@ -636,49 +636,49 @@ class LineWriter {
|
| // Since we're about to write some text on the next line, we know the
|
| // previous one is fully done being tweaked and merged, so now we can see
|
| // if it can be split independently.
|
| - _checkForCompleteLine();
|
| + _checkForCompleteLine(_chunks.length);
|
|
|
| _chunks.add(new Chunk(text));
|
| }
|
| }
|
|
|
| - /// Checks to see if we are currently at a point where the existing chunks
|
| - /// can be processed as a single line and processes them if so.
|
| + /// Checks to see if we the first [length] chunks can be processed as a
|
| + /// single line and processes them if so.
|
| ///
|
| /// We want to send small lists of chunks to [LineSplitter] for performance.
|
| /// We can do that when we know one set of chunks will absolutely not affect
|
| /// anything following it. The rule for that is pretty simple: a hard newline
|
| /// that is not nested inside an expression.
|
| - void _checkForCompleteLine() {
|
| - if (_chunks.isEmpty) return;
|
| + bool _checkForCompleteLine(int length) {
|
| + if (length == 0) return false;
|
| +
|
| + // Hang on to the split info so we can reset the writer to start with it.
|
| + var split = _chunks[length - 1];
|
|
|
| // Can only split on a hard line that is not nested in the middle of an
|
| // expression.
|
| - if (!_chunks.last.isHardSplit || _chunks.last.nesting >= 0) return;
|
| + if (!split.isHardSplit || split.nesting >= 0) return false;
|
|
|
| - // Hang on to the split info so we can reset the writer to start with it.
|
| - var split = _chunks.last;
|
| -
|
| - // Don't write any empty line, just discard it.
|
| - if (_chunks.isNotEmpty) {
|
| - _completeLine();
|
| - _chunks.clear();
|
| - }
|
| + _completeLine(length);
|
|
|
| - _spans.clear();
|
| + // Discard the formatted chunks and any spans contained in them.
|
| + _chunks.removeRange(0, length);
|
| + _spans.removeWhere((span) => span.shift(length));
|
|
|
| // Get ready for the next line.
|
| _bufferedNewlines = split.isDouble ? 2 : 1;
|
| _beginningIndent = split.indent;
|
| +
|
| + return true;
|
| }
|
|
|
| - /// Hands off the current list of chunks to [LineSplitter] as a single logical
|
| - /// line.
|
| - void _completeLine() {
|
| + /// Hands off the first [length] chunks to the [LineSplitter] as a single
|
| + /// logical line to be split.
|
| + void _completeLine(int length) {
|
| assert(_chunks.isNotEmpty);
|
|
|
| if (debugFormatter) {
|
| - dumpChunks(_chunks);
|
| + dumpChunks(_chunks.take(length).toList());
|
| print(_spans.join("\n"));
|
| }
|
|
|
| @@ -687,8 +687,18 @@ class LineWriter {
|
| _buffer.write(_formatter.lineEnding);
|
| }
|
|
|
| + // If we aren't completing the entire set of chunks, get the subset that we
|
| + // are completing.
|
| + var chunks = _chunks;
|
| + var spans = _spans;
|
| +
|
| + if (length < _chunks.length) {
|
| + chunks = chunks.take(length).toList();
|
| + spans = spans.where((span) => span.start <= length).toList();
|
| + }
|
| +
|
| var splitter = new LineSplitter(_formatter.lineEnding, _formatter.pageWidth,
|
| - _chunks, _spans, _beginningIndent);
|
| + chunks, spans, _beginningIndent);
|
| var selection = splitter.apply(_buffer);
|
|
|
| if (selection[0] != null) _selectionStart = selection[0];
|
| @@ -725,11 +735,17 @@ class LineWriter {
|
| if (splitParams.isEmpty) return;
|
|
|
| // Take any existing splits for the multisplits and hard split them.
|
| - for (var chunk in _chunks) {
|
| + for (var i = 0; i < _chunks.length; i++) {
|
| + var chunk = _chunks[i];
|
| if (chunk.param == null) continue;
|
|
|
| if (splitParams.contains(chunk.param)) {
|
| chunk.harden();
|
| +
|
| + // Now that this chunk is a hard split, we may be able to format up to
|
| + // it as its own line. If so, the chunks will get removed, so reset
|
| + // the loop counter.
|
| + if (_checkForCompleteLine(i + 1)) i = -1;
|
| } else {
|
| // If the chunk isn't hardened, but implies something that is, we can
|
| // discard the implication since it is always satisfied now.
|
|
|