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

Side by Side Diff: lib/src/rule/argument.dart

Issue 1493553002: Smarter splitting around named collection arguments. (Closed) Base URL: https://github.com/dart-lang/dart_style.git@master
Patch Set: Created 5 years 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/line_splitting/solve_state.dart ('k') | lib/src/source_visitor.dart » ('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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.rule.argument; 5 library dart_style.src.rule.argument;
6 6
7 import '../chunk.dart'; 7 import '../chunk.dart';
8 import 'rule.dart'; 8 import 'rule.dart';
9 9
10 /// Base class for a rule that handles argument or parameter lists. 10 /// Base class for a rule that handles argument or parameter lists.
11 abstract class ArgumentRule extends Rule { 11 abstract class ArgumentRule extends Rule {
12 /// The chunks prior to each positional argument.
13 final List<Chunk> _arguments = [];
14
15 /// The rule used to split collections in the argument list, if any.
16 Rule _collectionRule;
17
18 /// The number of leading collection arguments.
19 ///
20 /// This and [_trailingCollections] cannot both be positive. If every
21 /// argument is a collection, this will be [_arguments.length] and
22 /// [_trailingCollections] will be 0.
23 final int _leadingCollections;
24
25 /// The number of trailing collections.
26 ///
27 /// This and [_leadingCollections] cannot both be positive.
28 final int _trailingCollections;
29
12 /// If true, then inner rules that are written will force this rule to split. 30 /// If true, then inner rules that are written will force this rule to split.
13 /// 31 ///
14 /// Temporarily disabled while writing collectio arguments so that they can be 32 /// Temporarily disabled while writing collectio arguments so that they can be
15 /// multi-line without forcing the whole argument list to split. 33 /// multi-line without forcing the whole argument list to split.
16 bool _trackInnerRules = true; 34 bool _trackInnerRules = true;
17 35
18 /// Don't split when an inner collection rule splits. 36 /// Don't split when an inner collection rule splits.
19 bool get splitsOnInnerRules => _trackInnerRules; 37 bool get splitsOnInnerRules => _trackInnerRules;
20 38
39 ArgumentRule(this._collectionRule, this._leadingCollections,
40 this._trailingCollections);
41
42 void addConstrainedRules(Set<Rule> rules) {
43 super.addConstrainedRules(rules);
44 if (_collectionRule != null) rules.add(_collectionRule);
45 }
46
47 void forgetUnusedRules() {
48 super.forgetUnusedRules();
49 if (_collectionRule != null && _collectionRule.index == null) {
50 _collectionRule = null;
51 }
52 }
53
54 /// Remembers [chunk] as containing the split that occurs right before an
55 /// argument in the list.
56 void beforeArgument(Chunk chunk) {
57 _arguments.add(chunk);
58 }
59
21 /// Called before a collection argument is written. 60 /// Called before a collection argument is written.
22 /// 61 ///
23 /// Disables tracking inner rules while a collection argument is written. 62 /// Disables tracking inner rules while a collection argument is written.
24 void beforeCollection() { 63 void beforeCollection() {
25 assert(_trackInnerRules == true); 64 assert(_trackInnerRules == true);
26 _trackInnerRules = false; 65 _trackInnerRules = false;
27 } 66 }
28 67
29 /// Called after a collection argument is complete. 68 /// Called after a collection argument is complete.
30 /// 69 ///
31 /// Re-enables tracking inner rules. 70 /// Re-enables tracking inner rules.
32 void afterCollection() { 71 void afterCollection() {
33 assert(_trackInnerRules == false); 72 assert(_trackInnerRules == false);
34 _trackInnerRules = true; 73 _trackInnerRules = true;
35 } 74 }
36 } 75 }
37 76
38 /// Base class for a rule for handling positional argument lists. 77 /// Base class for a rule for handling positional argument lists.
39 abstract class PositionalRule extends ArgumentRule { 78 abstract class PositionalRule extends ArgumentRule {
40 /// The chunks prior to each positional argument.
41 final List<Chunk> _arguments = [];
42
43 /// The rule used to split collections in the argument list, if any.
44 Rule _collectionRule;
45
46 /// If there are named arguments following these positional ones, this will 79 /// If there are named arguments following these positional ones, this will
47 /// be their rule. 80 /// be their rule.
48 Rule _namedArgsRule; 81 Rule _namedArgsRule;
49 82
50 /// Creates a new rule for a positional argument list. 83 /// Creates a new rule for a positional argument list.
51 /// 84 ///
52 /// If [_collectionRule] is given, it is the rule used to split the collection 85 /// If [_collectionRule] is given, it is the rule used to split the collection
53 /// arguments in the list. 86 /// arguments in the list.
54 PositionalRule(this._collectionRule); 87 PositionalRule(
88 Rule collectionRule, int leadingCollections, int trailingCollections)
89 : super(collectionRule, leadingCollections, trailingCollections);
55 90
56 void addConstrainedRules(Set<Rule> rules) { 91 void addConstrainedRules(Set<Rule> rules) {
57 if (_collectionRule != null) rules.add(_collectionRule); 92 super.addConstrainedRules(rules);
58 if (_namedArgsRule != null) rules.add(_namedArgsRule); 93 if (_namedArgsRule != null) rules.add(_namedArgsRule);
59 } 94 }
60 95
61 void forgetUnusedRules() { 96 void forgetUnusedRules() {
62 super.forgetUnusedRules(); 97 super.forgetUnusedRules();
63 if (_namedArgsRule != null && _namedArgsRule.index == null) { 98 if (_namedArgsRule != null && _namedArgsRule.index == null) {
64 _namedArgsRule = null; 99 _namedArgsRule = null;
65 } 100 }
66
67 if (_collectionRule != null && _collectionRule.index == null) {
68 _collectionRule = null;
69 }
70 } 101 }
71 102
72 /// Remembers [chunk] as containing the split that occurs right before an 103 /// Remembers that [rule] is the [Rule] immediately following this positional
73 /// argument in the list.
74 void beforeArgument(Chunk chunk) {
75 _arguments.add(chunk);
76 }
77
78 /// Remembers that [rule] is the [NamedArgsRule] immediately following this
79 /// positional argument list. 104 /// positional argument list.
80 void setNamedArgsRule(NamedRule rule) { 105 ///
106 /// This is normally a [NamedRule] but [PositionalRule] is also used for the
107 /// property accesses at the beginning of a call chain, in which case this
108 /// is just a [SimpleRule].
109 void setNamedArgsRule(Rule rule) {
81 _namedArgsRule = rule; 110 _namedArgsRule = rule;
82 } 111 }
83 112
84 /// Constrains the named argument list to at least move to the next line if 113 /// Constrains the named argument list to at least move to the next line if
85 /// there are any splits in the positional arguments. Prevents things like: 114 /// there are any splits in the positional arguments. Prevents things like:
86 /// 115 ///
87 /// function( 116 /// function(
88 /// argument, 117 /// argument,
89 /// argument, named: argument); 118 /// argument, named: argument);
90 int constrain(int value, Rule other) { 119 int constrain(int value, Rule other) {
(...skipping 22 matching lines...) Expand all
113 /// If there is only a single non-collection argument, allow it to split 142 /// If there is only a single non-collection argument, allow it to split
114 /// internally without forcing a split before the argument. 143 /// internally without forcing a split before the argument.
115 final bool splitsOnInnerRules; 144 final bool splitsOnInnerRules;
116 145
117 /// Creates a new rule for a positional argument list. 146 /// Creates a new rule for a positional argument list.
118 /// 147 ///
119 /// If [collectionRule] is given, it is the rule used to split the 148 /// If [collectionRule] is given, it is the rule used to split the
120 /// collections in the list. If [splitsOnInnerRules] is `true`, then we will 149 /// collections in the list. If [splitsOnInnerRules] is `true`, then we will
121 /// split before the argument if the argument itself contains a split. 150 /// split before the argument if the argument itself contains a split.
122 SinglePositionalRule(Rule collectionRule, {bool splitsOnInnerRules}) 151 SinglePositionalRule(Rule collectionRule, {bool splitsOnInnerRules})
123 : super(collectionRule), 152 : super(collectionRule, 0, 0),
124 splitsOnInnerRules = 153 splitsOnInnerRules =
125 splitsOnInnerRules != null ? splitsOnInnerRules : false; 154 splitsOnInnerRules != null ? splitsOnInnerRules : false;
126 155
127 int constrain(int value, Rule other) { 156 int constrain(int value, Rule other) {
128 var constrained = super.constrain(value, other); 157 var constrained = super.constrain(value, other);
129 if (constrained != null) return constrained; 158 if (constrained != null) return constrained;
130 159
131 if (other != _collectionRule) return null; 160 if (other != _collectionRule) return null;
132 161
133 // If we aren't splitting any args, we can split the collection. 162 // If we aren't splitting any args, we can split the collection.
(...skipping 17 matching lines...) Expand all
151 /// Then there is a value for each argument, to split before that argument. 180 /// Then there is a value for each argument, to split before that argument.
152 /// These values work back to front. So, for a two-argument list, value 2 splits 181 /// These values work back to front. So, for a two-argument list, value 2 splits
153 /// after the second argument and value 3 splits after the first. 182 /// after the second argument and value 3 splits after the first.
154 /// 183 ///
155 /// Then there is a value that splits before every argument. 184 /// Then there is a value that splits before every argument.
156 /// 185 ///
157 /// Finally, if there are collection arguments, there is another value that 186 /// Finally, if there are collection arguments, there is another value that
158 /// splits before all of the non-collection arguments, but does not split 187 /// splits before all of the non-collection arguments, but does not split
159 /// before the collections, so that they can split internally. 188 /// before the collections, so that they can split internally.
160 class MultiplePositionalRule extends PositionalRule { 189 class MultiplePositionalRule extends PositionalRule {
161 /// The number of leading collection arguments.
162 ///
163 /// This and [_trailingCollections] cannot both be positive. If every
164 /// argument is a collection, this will be [_arguments.length] and
165 /// [_trailingCollections] will be 0.
166 final int _leadingCollections;
167
168 /// The number of trailing collections.
169 ///
170 /// This and [_leadingCollections] cannot both be positive.
171 final int _trailingCollections;
172
173 int get numValues { 190 int get numValues {
174 // Can split before any one argument, none, or all. 191 // Can split before any one argument, none, or all.
175 var result = 2 + _arguments.length; 192 var result = 2 + _arguments.length;
176 193
177 // When there are collection arguments, there are two ways we can split on 194 // When there are collection arguments, there are two ways we can split on
178 // "all" arguments: 195 // "all" arguments:
179 // 196 //
180 // - Split on just the non-collection arguments, and force the collection 197 // - Split on just the non-collection arguments, and force the collection
181 // arguments to split internally. 198 // arguments to split internally.
182 // - Split on all of them including the collection arguments, and do not 199 // - Split on all of them including the collection arguments, and do not
183 // allow the collection arguments to split internally. 200 // allow the collection arguments to split internally.
184 if (_leadingCollections > 0 || _trailingCollections > 0) result++; 201 if (_leadingCollections > 0 || _trailingCollections > 0) result++;
185 202
186 return result; 203 return result;
187 } 204 }
188 205
189 MultiplePositionalRule( 206 MultiplePositionalRule(
190 Rule collectionRule, this._leadingCollections, this._trailingCollections) 207 Rule collectionRule, int leadingCollections, int trailingCollections)
191 : super(collectionRule); 208 : super(collectionRule, leadingCollections, trailingCollections);
192 209
193 String toString() => "*Pos${super.toString()}"; 210 String toString() => "*Pos${super.toString()}";
194 211
195 bool isSplitAtValue(int value, Chunk chunk) { 212 bool isSplitAtValue(int value, Chunk chunk) {
196 // Split only before the first argument. Keep the entire argument list 213 // Split only before the first argument. Keep the entire argument list
197 // together on the next line. 214 // together on the next line.
198 if (value == 1) return chunk == _arguments.first; 215 if (value == 1) return chunk == _arguments.first;
199 216
200 // Split before a single argument. Try later arguments before earlier ones 217 // Split before a single argument. Try later arguments before earlier ones
201 // to try to keep as much on the first line as possible. 218 // to try to keep as much on the first line as possible.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 if (value == _arguments.length + 1) return 1; 283 if (value == _arguments.length + 1) return 1;
267 284
268 // Split before all of the arguments, even the collections. We'll allow 285 // Split before all of the arguments, even the collections. We'll allow
269 // them to split but indent their bodies if they do. 286 // them to split but indent their bodies if they do.
270 return null; 287 return null;
271 } 288 }
272 } 289 }
273 290
274 /// Splitting rule for a list of named arguments or parameters. Its values mean: 291 /// Splitting rule for a list of named arguments or parameters. Its values mean:
275 /// 292 ///
276 /// * 0: Do not split at all. 293 /// * Do not split at all.
277 /// * 1: Split only before first argument. 294 /// * Split only before first argument.
278 /// * 2: Split before all arguments, including the first. 295 /// * Split before all arguments.
279 class NamedRule extends ArgumentRule { 296 class NamedRule extends ArgumentRule {
280 /// The chunk prior to the first named argument.
281 Chunk _first;
282
283 /// Whether any of the named arguments are collection literals.
284 final bool _containsCollections;
285
286 int get numValues => 3; 297 int get numValues => 3;
287 298
288 NamedRule({bool containsCollections}) 299 NamedRule(
289 : _containsCollections = containsCollections ?? false; 300 Rule collectionRule, int leadingCollections, int trailingCollections)
301 : super(collectionRule, leadingCollections, trailingCollections);
290 302
291 void beforeArguments(Chunk chunk) { 303 bool isSplitAtValue(int value, Chunk chunk) {
292 assert(_first == null); 304 // Move all arguments to the second line as a unit.
293 _first = chunk; 305 if (value == 1) return chunk == _arguments.first;
306
307 // Otherwise, split before all arguments.
308 return true;
294 } 309 }
295 310
296 bool isSplitAtValue(int value, Chunk chunk) { 311 int constrain(int value, Rule other) {
297 // Only split before the first argument. 312 var constrained = super.constrain(value, other);
298 if (value == 1) return chunk == _first; 313 if (constrained != null) return constrained;
299 314
300 // Split before every argument. 315 // Decide how to constrain the collection rule.
301 return true; 316 if (other != _collectionRule) return null;
317
318 // If all of the collections are in the named arguments, [_collectionRule]
319 // will not be null, but we don't have to handle it.
320 if (_leadingCollections == 0 && _trailingCollections == 0) return null;
321
322 // If we aren't splitting any args, we can split the collection.
323 if (value == Rule.unsplit) return null;
324
325 // Split only before the first argument. Don't allow the collections to
326 // split.
327 if (value == 1) return Rule.unsplit;
328
329 // Split before all of the arguments, even the collections. We'll allow
330 // them to split but indent their bodies if they do.
331 return null;
302 } 332 }
303 333
304 String toString() => "Named${super.toString()}"; 334 String toString() => "Named${super.toString()}";
305 } 335 }
OLDNEW
« no previous file with comments | « lib/src/line_splitting/solve_state.dart ('k') | lib/src/source_visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698