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

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

Issue 996033002: Automatically harden splits containing too much nesting. Fix #108. (Closed) Base URL: https://github.com/dart-lang/dart_style.git@master
Patch Set: Update changelog. 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 | « CHANGELOG.md ('k') | test/regression/108.unit » ('j') | 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.line_splitter; 5 library dart_style.src.line_splitter;
6 6
7 import 'dart:math' as math; 7 import 'dart:math' as math;
8 8
9 import 'chunk.dart'; 9 import 'chunk.dart';
10 import 'debug.dart'; 10 import 'debug.dart';
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 /// return a single string that may contain one or more newline characters. 96 /// return a single string that may contain one or more newline characters.
97 /// 97 ///
98 /// Returns a two-element list. The first element will be an [int] indicating 98 /// Returns a two-element list. The first element will be an [int] indicating
99 /// where in [buffer] the selection start point should appear if it was 99 /// where in [buffer] the selection start point should appear if it was
100 /// contained in the formatted list of chunks. Otherwise it will be `null`. 100 /// contained in the formatted list of chunks. Otherwise it will be `null`.
101 /// Likewise, the second element will be non-`null` if the selection endpoint 101 /// Likewise, the second element will be non-`null` if the selection endpoint
102 /// is within the list of chunks. 102 /// is within the list of chunks.
103 List<int> apply(StringBuffer buffer) { 103 List<int> apply(StringBuffer buffer) {
104 if (debugFormatter) dumpLine(_chunks, _indent); 104 if (debugFormatter) dumpLine(_chunks, _indent);
105 105
106 _flattenNestingLevels(); 106 var nestingDepth = _flattenNestingLevels();
107
108 // Hack. The formatter doesn't handle formatting very deeply nested code
109 // well. It can make performance spiral into a pit of sadness. Fortunately,
110 // we only tend to see expressions pathologically deeply nested in
111 // generated code that isn't read by humans much anyway. To avoid burning
112 // too much time on these, harden any splits containing more than a certain
113 // level of nesting.
114 //
115 // The number here was chosen empirically based on formatting the repo. It
116 // was picked to get the best performance while affecting the minimum amount
117 // of results.
118 // TODO(rnystrom): Do something smarter.
pquitslund 2015/03/11 00:09:50 Best comment I've read all year.
Bob Nystrom 2015/03/11 00:14:17 :D
119 if (nestingDepth > 9) {
120 for (var chunk in _chunks) {
121 if (chunk.param != null && nestingDepth - chunk.nesting > 9) {
122 chunk.harden();
123 }
124 }
125 }
107 126
108 var splits = _findBestSplits(new LinePrefix()); 127 var splits = _findBestSplits(new LinePrefix());
128
109 var selection = [null, null]; 129 var selection = [null, null];
110 130
111 // Write each chunk and the split after it. 131 // Write each chunk and the split after it.
112 buffer.write(" " * (_indent * spacesPerIndent)); 132 buffer.write(" " * (_indent * spacesPerIndent));
113 for (var i = 0; i < _chunks.length; i++) { 133 for (var i = 0; i < _chunks.length; i++) {
114 var chunk = _chunks[i]; 134 var chunk = _chunks[i];
115 135
116 // If this chunk contains one of the selection markers, tell the writer 136 // If this chunk contains one of the selection markers, tell the writer
117 // where it ended up in the final output. 137 // where it ended up in the final output.
118 if (chunk.selectionStart != null) { 138 if (chunk.selectionStart != null) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 /// It's fairly common for a nesting level to not actually appear at the 174 /// It's fairly common for a nesting level to not actually appear at the
155 /// boundary of a chunk. The source visitor may enter more than one level of 175 /// boundary of a chunk. The source visitor may enter more than one level of
156 /// nesting at a point where a split cannot happen. In that case, there's no 176 /// nesting at a point where a split cannot happen. In that case, there's no
157 /// point in trying to assign an indentation level to that nesting level. It 177 /// point in trying to assign an indentation level to that nesting level. It
158 /// will never be used because no line will begin at that level of 178 /// will never be used because no line will begin at that level of
159 /// indentation. 179 /// indentation.
160 /// 180 ///
161 /// Worse, if the splitter *does* consider these levels, it can dramatically 181 /// Worse, if the splitter *does* consider these levels, it can dramatically
162 /// increase solving time. To avoid that, this renumbers all of the nesting 182 /// increase solving time. To avoid that, this renumbers all of the nesting
163 /// levels in the chunks to not have any of these unused gaps. 183 /// levels in the chunks to not have any of these unused gaps.
164 void _flattenNestingLevels() { 184 ///
185 /// Returns the number of distinct nesting levels remaining after flattening.
186 /// This may be zero if the chunks have no nesting (i.e. just statement-level
187 /// indentation).
188 int _flattenNestingLevels() {
165 var nestingLevels = _chunks 189 var nestingLevels = _chunks
166 .map((chunk) => chunk.nesting) 190 .map((chunk) => chunk.nesting)
167 .where((nesting) => nesting != -1) 191 .where((nesting) => nesting != -1)
168 .toSet() 192 .toSet()
169 .toList(); 193 .toList();
170 nestingLevels.sort(); 194 nestingLevels.sort();
171 195
172 var nestingMap = {-1: -1}; 196 var nestingMap = {-1: -1};
173 for (var i = 0; i < nestingLevels.length; i++) { 197 for (var i = 0; i < nestingLevels.length; i++) {
174 nestingMap[nestingLevels[i]] = i; 198 nestingMap[nestingLevels[i]] = i;
175 } 199 }
176 200
177 for (var chunk in _chunks) { 201 for (var chunk in _chunks) {
178 chunk.nesting = nestingMap[chunk.nesting]; 202 chunk.nesting = nestingMap[chunk.nesting];
179 } 203 }
204
205 return nestingLevels.length;
180 } 206 }
181 207
182 /// Finds the best set of splits to apply to the remainder of the line 208 /// Finds the best set of splits to apply to the remainder of the line
183 /// following [prefix]. 209 /// following [prefix].
184 SplitSet _findBestSplits(LinePrefix prefix) { 210 SplitSet _findBestSplits(LinePrefix prefix) {
185 // Use the memoized result if we have it. 211 // Use the memoized result if we have it.
186 if (_bestSplits.containsKey(prefix)) return _bestSplits[prefix]; 212 if (_bestSplits.containsKey(prefix)) return _bestSplits[prefix];
187 213
188 var indent = prefix.getNextLineIndent(_chunks, _indent); 214 var indent = prefix.getNextLineIndent(_chunks, _indent);
189 215
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 var result = []; 534 var result = [];
509 for (var i = 0; i < _splitNesting.length; i++) { 535 for (var i = 0; i < _splitNesting.length; i++) {
510 if (_splitNesting[i] != null) { 536 if (_splitNesting[i] != null) {
511 result.add("$i:${_splitNesting[i]}"); 537 result.add("$i:${_splitNesting[i]}");
512 } 538 }
513 } 539 }
514 540
515 return result.join(" "); 541 return result.join(" ");
516 } 542 }
517 } 543 }
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | test/regression/108.unit » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698