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

Side by Side Diff: lib/src/line_writer.dart

Issue 987253002: Separately format lines when a multisplit is split. (Closed) Base URL: https://github.com/dart-lang/dart_style.git@master
Patch Set: Rebase. Created 5 years, 9 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
« no previous file with comments | « lib/src/chunk.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart_style.src.source_writer; 5 library dart_style.src.source_writer;
6 6
7 import 'dart_formatter.dart'; 7 import 'dart_formatter.dart';
8 import 'chunk.dart'; 8 import 'chunk.dart';
9 import 'debug.dart'; 9 import 'debug.dart';
10 import 'line_splitter.dart'; 10 import 'line_splitter.dart';
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 /// It counts backwards from the end because this is called *after* the chunk 465 /// It counts backwards from the end because this is called *after* the chunk
466 /// of text containing the selection has been output. 466 /// of text containing the selection has been output.
467 void endSelectionFromEnd(int fromEnd) { 467 void endSelectionFromEnd(int fromEnd) {
468 assert(_chunks.isNotEmpty); 468 assert(_chunks.isNotEmpty);
469 _chunks.last.endSelectionFromEnd(fromEnd); 469 _chunks.last.endSelectionFromEnd(fromEnd);
470 } 470 }
471 471
472 /// Finishes writing and returns a [SourceCode] containing the final output 472 /// Finishes writing and returns a [SourceCode] containing the final output
473 /// and updated selection, if any. 473 /// and updated selection, if any.
474 SourceCode end() { 474 SourceCode end() {
475 if (_chunks.isNotEmpty) _completeLine(); 475 if (_chunks.isNotEmpty) _completeLine(_chunks.length);
476 476
477 // Be a good citizen, end with a newline. 477 // Be a good citizen, end with a newline.
478 if (_source.isCompilationUnit) _buffer.write(_formatter.lineEnding); 478 if (_source.isCompilationUnit) _buffer.write(_formatter.lineEnding);
479 479
480 // If we haven't hit the beginning and/or end of the selection yet, they 480 // If we haven't hit the beginning and/or end of the selection yet, they
481 // must be at the very end of the code. 481 // must be at the very end of the code.
482 if (_source.selectionStart != null) { 482 if (_source.selectionStart != null) {
483 if (_selectionStart == null) { 483 if (_selectionStart == null) {
484 _selectionStart = _buffer.length; 484 _selectionStart = _buffer.length;
485 } 485 }
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 /// chunk is complete. 629 /// chunk is complete.
630 void _writeText(String text) { 630 void _writeText(String text) {
631 if (_chunks.isEmpty) { 631 if (_chunks.isEmpty) {
632 _chunks.add(new Chunk(text)); 632 _chunks.add(new Chunk(text));
633 } else if (_chunks.last.canAddText) { 633 } else if (_chunks.last.canAddText) {
634 _chunks.last.appendText(text); 634 _chunks.last.appendText(text);
635 } else { 635 } else {
636 // Since we're about to write some text on the next line, we know the 636 // Since we're about to write some text on the next line, we know the
637 // previous one is fully done being tweaked and merged, so now we can see 637 // previous one is fully done being tweaked and merged, so now we can see
638 // if it can be split independently. 638 // if it can be split independently.
639 _checkForCompleteLine(); 639 _checkForCompleteLine(_chunks.length);
640 640
641 _chunks.add(new Chunk(text)); 641 _chunks.add(new Chunk(text));
642 } 642 }
643 } 643 }
644 644
645 /// Checks to see if we are currently at a point where the existing chunks 645 /// Checks to see if we the first [length] chunks can be processed as a
646 /// can be processed as a single line and processes them if so. 646 /// single line and processes them if so.
647 /// 647 ///
648 /// We want to send small lists of chunks to [LineSplitter] for performance. 648 /// We want to send small lists of chunks to [LineSplitter] for performance.
649 /// We can do that when we know one set of chunks will absolutely not affect 649 /// We can do that when we know one set of chunks will absolutely not affect
650 /// anything following it. The rule for that is pretty simple: a hard newline 650 /// anything following it. The rule for that is pretty simple: a hard newline
651 /// that is not nested inside an expression. 651 /// that is not nested inside an expression.
652 void _checkForCompleteLine() { 652 bool _checkForCompleteLine(int length) {
653 if (_chunks.isEmpty) return; 653 if (length == 0) return false;
654
655 // Hang on to the split info so we can reset the writer to start with it.
656 var split = _chunks[length - 1];
654 657
655 // Can only split on a hard line that is not nested in the middle of an 658 // Can only split on a hard line that is not nested in the middle of an
656 // expression. 659 // expression.
657 if (!_chunks.last.isHardSplit || _chunks.last.nesting >= 0) return; 660 if (!split.isHardSplit || split.nesting >= 0) return false;
658 661
659 // Hang on to the split info so we can reset the writer to start with it. 662 _completeLine(length);
660 var split = _chunks.last;
661 663
662 // Don't write any empty line, just discard it. 664 // Discard the formatted chunks and any spans contained in them.
663 if (_chunks.isNotEmpty) { 665 _chunks.removeRange(0, length);
664 _completeLine(); 666 _spans.removeWhere((span) => span.shift(length));
665 _chunks.clear();
666 }
667
668 _spans.clear();
669 667
670 // Get ready for the next line. 668 // Get ready for the next line.
671 _bufferedNewlines = split.isDouble ? 2 : 1; 669 _bufferedNewlines = split.isDouble ? 2 : 1;
672 _beginningIndent = split.indent; 670 _beginningIndent = split.indent;
671
672 return true;
673 } 673 }
674 674
675 /// Hands off the current list of chunks to [LineSplitter] as a single logical 675 /// Hands off the first [length] chunks to the [LineSplitter] as a single
676 /// line. 676 /// logical line to be split.
677 void _completeLine() { 677 void _completeLine(int length) {
678 assert(_chunks.isNotEmpty); 678 assert(_chunks.isNotEmpty);
679 679
680 if (debugFormatter) { 680 if (debugFormatter) {
681 dumpChunks(_chunks); 681 dumpChunks(_chunks.take(length).toList());
682 print(_spans.join("\n")); 682 print(_spans.join("\n"));
683 } 683 }
684 684
685 // Write the newlines required by the previous line. 685 // Write the newlines required by the previous line.
686 for (var i = 0; i < _bufferedNewlines; i++) { 686 for (var i = 0; i < _bufferedNewlines; i++) {
687 _buffer.write(_formatter.lineEnding); 687 _buffer.write(_formatter.lineEnding);
688 } 688 }
689 689
690 // If we aren't completing the entire set of chunks, get the subset that we
691 // are completing.
692 var chunks = _chunks;
693 var spans = _spans;
694
695 if (length < _chunks.length) {
696 chunks = chunks.take(length).toList();
697 spans = spans.where((span) => span.start <= length).toList();
698 }
699
690 var splitter = new LineSplitter(_formatter.lineEnding, _formatter.pageWidth, 700 var splitter = new LineSplitter(_formatter.lineEnding, _formatter.pageWidth,
691 _chunks, _spans, _beginningIndent); 701 chunks, spans, _beginningIndent);
692 var selection = splitter.apply(_buffer); 702 var selection = splitter.apply(_buffer);
693 703
694 if (selection[0] != null) _selectionStart = selection[0]; 704 if (selection[0] != null) _selectionStart = selection[0];
695 if (selection[1] != null) _selectionLength = selection[1] - _selectionStart; 705 if (selection[1] != null) _selectionLength = selection[1] - _selectionStart;
696 } 706 }
697 707
698 /// Handles multisplits when a hard line occurs. 708 /// Handles multisplits when a hard line occurs.
699 /// 709 ///
700 /// Any active separable multisplits will get split in two at this point. 710 /// Any active separable multisplits will get split in two at this point.
701 /// Other multisplits are forced into the "hard" state. All of their previous 711 /// Other multisplits are forced into the "hard" state. All of their previous
(...skipping 16 matching lines...) Expand all
718 for (var multisplit in _multisplits) { 728 for (var multisplit in _multisplits) {
719 // If this multisplit isn't separable or already split, we need to harden 729 // If this multisplit isn't separable or already split, we need to harden
720 // all of its previous splits now. 730 // all of its previous splits now.
721 var param = multisplit.harden(); 731 var param = multisplit.harden();
722 if (param != null) traverseParams(param); 732 if (param != null) traverseParams(param);
723 } 733 }
724 734
725 if (splitParams.isEmpty) return; 735 if (splitParams.isEmpty) return;
726 736
727 // Take any existing splits for the multisplits and hard split them. 737 // Take any existing splits for the multisplits and hard split them.
728 for (var chunk in _chunks) { 738 for (var i = 0; i < _chunks.length; i++) {
739 var chunk = _chunks[i];
729 if (chunk.param == null) continue; 740 if (chunk.param == null) continue;
730 741
731 if (splitParams.contains(chunk.param)) { 742 if (splitParams.contains(chunk.param)) {
732 chunk.harden(); 743 chunk.harden();
744
745 // Now that this chunk is a hard split, we may be able to format up to
746 // it as its own line. If so, the chunks will get removed, so reset
747 // the loop counter.
748 if (_checkForCompleteLine(i + 1)) i = -1;
733 } else { 749 } else {
734 // If the chunk isn't hardened, but implies something that is, we can 750 // If the chunk isn't hardened, but implies something that is, we can
735 // discard the implication since it is always satisfied now. 751 // discard the implication since it is always satisfied now.
736 chunk.param.implies.removeWhere(splitParams.contains); 752 chunk.param.implies.removeWhere(splitParams.contains);
737 } 753 }
738 } 754 }
739 } 755 }
740 } 756 }
OLDNEW
« no previous file with comments | « lib/src/chunk.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698