| OLD | NEW |
| 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. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 /// [_trailingCollections] will be 0. | 22 /// [_trailingCollections] will be 0. |
| 23 final int _leadingCollections; | 23 final int _leadingCollections; |
| 24 | 24 |
| 25 /// The number of trailing collections. | 25 /// The number of trailing collections. |
| 26 /// | 26 /// |
| 27 /// This and [_leadingCollections] cannot both be positive. | 27 /// This and [_leadingCollections] cannot both be positive. |
| 28 final int _trailingCollections; | 28 final int _trailingCollections; |
| 29 | 29 |
| 30 /// 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. |
| 31 /// | 31 /// |
| 32 /// Temporarily disabled while writing collectio arguments so that they can be | 32 /// Temporarily disabled while writing collection arguments so that they can |
| 33 /// multi-line without forcing the whole argument list to split. | 33 /// be multi-line without forcing the whole argument list to split. |
| 34 bool _trackInnerRules = true; | 34 bool _trackInnerRules = true; |
| 35 | 35 |
| 36 /// Don't split when an inner collection rule splits. | 36 /// Don't split when an inner collection rule splits. |
| 37 bool get splitsOnInnerRules => _trackInnerRules; | 37 bool get splitsOnInnerRules => _trackInnerRules; |
| 38 | 38 |
| 39 ArgumentRule(this._collectionRule, this._leadingCollections, | 39 ArgumentRule(this._collectionRule, this._leadingCollections, |
| 40 this._trailingCollections); | 40 this._trailingCollections); |
| 41 | 41 |
| 42 void addConstrainedRules(Set<Rule> rules) { | 42 void addConstrainedRules(Set<Rule> rules) { |
| 43 super.addConstrainedRules(rules); | 43 super.addConstrainedRules(rules); |
| 44 if (_collectionRule != null) rules.add(_collectionRule); | 44 if (_collectionRule != null) rules.add(_collectionRule); |
| 45 } | 45 } |
| 46 | 46 |
| 47 void forgetUnusedRules() { | 47 void forgetUnusedRules() { |
| 48 super.forgetUnusedRules(); | 48 super.forgetUnusedRules(); |
| 49 if (_collectionRule != null && _collectionRule.index == null) { | 49 if (_collectionRule != null && _collectionRule.index == null) { |
| 50 _collectionRule = null; | 50 _collectionRule = null; |
| 51 } | 51 } |
| 52 } | 52 } |
| 53 | 53 |
| 54 /// Remembers [chunk] as containing the split that occurs right before an | 54 /// Remembers [chunk] as containing the split that occurs right before an |
| 55 /// argument in the list. | 55 /// argument in the list. |
| 56 void beforeArgument(Chunk chunk) { | 56 void beforeArgument(Chunk chunk) { |
| 57 _arguments.add(chunk); | 57 _arguments.add(chunk); |
| 58 } | 58 } |
| 59 | 59 |
| 60 /// Called before a collection argument is written. | |
| 61 /// | |
| 62 /// Disables tracking inner rules while a collection argument is written. | 60 /// Disables tracking inner rules while a collection argument is written. |
| 63 void beforeCollection() { | 61 void disableSplitOnInnerRules() { |
| 64 assert(_trackInnerRules == true); | 62 assert(_trackInnerRules == true); |
| 65 _trackInnerRules = false; | 63 _trackInnerRules = false; |
| 66 } | 64 } |
| 67 | 65 |
| 68 /// Called after a collection argument is complete. | |
| 69 /// | |
| 70 /// Re-enables tracking inner rules. | 66 /// Re-enables tracking inner rules. |
| 71 void afterCollection() { | 67 void enableSplitOnInnerRules() { |
| 72 assert(_trackInnerRules == false); | 68 assert(_trackInnerRules == false); |
| 73 _trackInnerRules = true; | 69 _trackInnerRules = true; |
| 74 } | 70 } |
| 75 } | 71 } |
| 76 | 72 |
| 77 /// Base class for a rule for handling positional argument lists. | 73 /// Rule for handling positional argument lists. |
| 78 abstract class PositionalRule extends ArgumentRule { | |
| 79 /// If there are named arguments following these positional ones, this will | |
| 80 /// be their rule. | |
| 81 Rule _namedArgsRule; | |
| 82 | |
| 83 /// Creates a new rule for a positional argument list. | |
| 84 /// | |
| 85 /// If [_collectionRule] is given, it is the rule used to split the collection | |
| 86 /// arguments in the list. | |
| 87 PositionalRule( | |
| 88 Rule collectionRule, int leadingCollections, int trailingCollections) | |
| 89 : super(collectionRule, leadingCollections, trailingCollections); | |
| 90 | |
| 91 void addConstrainedRules(Set<Rule> rules) { | |
| 92 super.addConstrainedRules(rules); | |
| 93 if (_namedArgsRule != null) rules.add(_namedArgsRule); | |
| 94 } | |
| 95 | |
| 96 void forgetUnusedRules() { | |
| 97 super.forgetUnusedRules(); | |
| 98 if (_namedArgsRule != null && _namedArgsRule.index == null) { | |
| 99 _namedArgsRule = null; | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 /// Remembers that [rule] is the [Rule] immediately following this positional | |
| 104 /// positional argument list. | |
| 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) { | |
| 110 _namedArgsRule = rule; | |
| 111 } | |
| 112 | |
| 113 /// Constrains the named argument list to at least move to the next line if | |
| 114 /// there are any splits in the positional arguments. Prevents things like: | |
| 115 /// | |
| 116 /// function( | |
| 117 /// argument, | |
| 118 /// argument, named: argument); | |
| 119 int constrain(int value, Rule other) { | |
| 120 var constrained = super.constrain(value, other); | |
| 121 if (constrained != null) return constrained; | |
| 122 | |
| 123 // Handle the relationship between the positional and named args. | |
| 124 if (other == _namedArgsRule) { | |
| 125 // If the positional args are one-per-line, the named args are too. | |
| 126 if (value == fullySplitValue) return _namedArgsRule.fullySplitValue; | |
| 127 | |
| 128 // Otherwise, if there is any split in the positional arguments, don't | |
| 129 // allow the named arguments on the same line as them. | |
| 130 if (value != 0) return -1; | |
| 131 } | |
| 132 | |
| 133 return null; | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 /// Split rule for a call with a single positional argument (which may or may | |
| 138 /// not be a collection argument.) | |
| 139 class SinglePositionalRule extends PositionalRule { | |
| 140 int get numValues => 2; | |
| 141 | |
| 142 /// If there is only a single non-collection argument, allow it to split | |
| 143 /// internally without forcing a split before the argument. | |
| 144 final bool splitsOnInnerRules; | |
| 145 | |
| 146 /// Creates a new rule for a positional argument list. | |
| 147 /// | |
| 148 /// If [collectionRule] is given, it is the rule used to split the | |
| 149 /// collections in the list. If [splitsOnInnerRules] is `true`, then we will | |
| 150 /// split before the argument if the argument itself contains a split. | |
| 151 SinglePositionalRule(Rule collectionRule, {bool splitsOnInnerRules}) | |
| 152 : super(collectionRule, 0, 0), | |
| 153 splitsOnInnerRules = | |
| 154 splitsOnInnerRules != null ? splitsOnInnerRules : false; | |
| 155 | |
| 156 int constrain(int value, Rule other) { | |
| 157 var constrained = super.constrain(value, other); | |
| 158 if (constrained != null) return constrained; | |
| 159 | |
| 160 if (other != _collectionRule) return null; | |
| 161 | |
| 162 // If we aren't splitting any args, we can split the collection. | |
| 163 if (value == Rule.unsplit) return null; | |
| 164 | |
| 165 // We are splitting before a collection, so don't let it split internally. | |
| 166 return Rule.unsplit; | |
| 167 } | |
| 168 | |
| 169 String toString() => "1Pos${super.toString()}"; | |
| 170 } | |
| 171 | |
| 172 /// Split rule for a call with more than one positional argument. | |
| 173 /// | 74 /// |
| 174 /// The number of values is based on the number of arguments and whether or not | 75 /// The number of values is based on the number of arguments and whether or not |
| 175 /// there are bodies. The first two values are always: | 76 /// there are bodies. The first two values are always: |
| 176 /// | 77 /// |
| 177 /// * 0: Do not split at all. | 78 /// * 0: Do not split at all. |
| 178 /// * 1: Split only before the first argument. | 79 /// * 1: Split only before the first argument. |
| 179 /// | 80 /// |
| 180 /// Then there is a value for each argument, to split before that argument. | 81 /// Then there is a value for each argument, to split before that argument. |
| 181 /// These values work back to front. So, for a two-argument list, value 2 splits | 82 /// These values work back to front. So, for a two-argument list, value 2 splits |
| 182 /// after the second argument and value 3 splits after the first. | 83 /// after the second argument and value 3 splits after the first. |
| 183 /// | 84 /// |
| 184 /// Then there is a value that splits before every argument. | 85 /// Then there is a value that splits before every argument. |
| 185 /// | 86 /// |
| 186 /// Finally, if there are collection arguments, there is another value that | 87 /// Finally, if there are collection arguments, there is another value that |
| 187 /// splits before all of the non-collection arguments, but does not split | 88 /// splits before all of the non-collection arguments, but does not split |
| 188 /// before the collections, so that they can split internally. | 89 /// before the collections, so that they can split internally. |
| 189 class MultiplePositionalRule extends PositionalRule { | 90 class PositionalRule extends ArgumentRule { |
| 91 /// If there are named arguments following these positional ones, this will |
| 92 /// be their rule. |
| 93 Rule _namedArgsRule; |
| 94 |
| 95 /// Creates a new rule for a positional argument list. |
| 96 /// |
| 97 /// If [_collectionRule] is given, it is the rule used to split the collection |
| 98 /// arguments in the list. |
| 99 PositionalRule( |
| 100 Rule collectionRule, int leadingCollections, int trailingCollections) |
| 101 : super(collectionRule, leadingCollections, trailingCollections); |
| 102 |
| 190 int get numValues { | 103 int get numValues { |
| 191 // Can split before any one argument, none, or all. | 104 // Can split before any one argument or none. |
| 192 var result = 2 + _arguments.length; | 105 var result = _arguments.length + 1; |
| 106 |
| 107 // If there are multiple arguments, can split before all of them. |
| 108 if (_arguments.length > 1) result++; |
| 193 | 109 |
| 194 // When there are collection arguments, there are two ways we can split on | 110 // When there are collection arguments, there are two ways we can split on |
| 195 // "all" arguments: | 111 // "all" arguments: |
| 196 // | 112 // |
| 197 // - Split on just the non-collection arguments, and force the collection | 113 // - Split on just the non-collection arguments, and force the collection |
| 198 // arguments to split internally. | 114 // arguments to split internally. |
| 199 // - Split on all of them including the collection arguments, and do not | 115 // - Split on all of them including the collection arguments, and do not |
| 200 // allow the collection arguments to split internally. | 116 // allow the collection arguments to split internally. |
| 201 if (_leadingCollections > 0 || _trailingCollections > 0) result++; | 117 if (_leadingCollections > 0 || _trailingCollections > 0) result++; |
| 202 | 118 |
| 203 return result; | 119 return result; |
| 204 } | 120 } |
| 205 | 121 |
| 206 MultiplePositionalRule( | 122 void addConstrainedRules(Set<Rule> rules) { |
| 207 Rule collectionRule, int leadingCollections, int trailingCollections) | 123 super.addConstrainedRules(rules); |
| 208 : super(collectionRule, leadingCollections, trailingCollections); | 124 if (_namedArgsRule != null) rules.add(_namedArgsRule); |
| 125 } |
| 209 | 126 |
| 210 String toString() => "*Pos${super.toString()}"; | 127 void forgetUnusedRules() { |
| 128 super.forgetUnusedRules(); |
| 129 if (_namedArgsRule != null && _namedArgsRule.index == null) { |
| 130 _namedArgsRule = null; |
| 131 } |
| 132 } |
| 211 | 133 |
| 212 bool isSplitAtValue(int value, Chunk chunk) { | 134 bool isSplitAtValue(int value, Chunk chunk) { |
| 213 // Split only before the first argument. Keep the entire argument list | 135 // Split only before the first argument. Keep the entire argument list |
| 214 // together on the next line. | 136 // together on the next line. |
| 215 if (value == 1) return chunk == _arguments.first; | 137 if (value == 1) return chunk == _arguments.first; |
| 216 | 138 |
| 217 // Split before a single argument. Try later arguments before earlier ones | 139 // Split before a single argument. Try later arguments before earlier ones |
| 218 // to try to keep as much on the first line as possible. | 140 // to try to keep as much on the first line as possible. |
| 219 if (value <= _arguments.length) { | 141 if (value <= _arguments.length) { |
| 220 var argument = _arguments.length - value + 1; | 142 var argument = _arguments.length - value + 1; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 233 if (chunk == _arguments[i]) return false; | 155 if (chunk == _arguments[i]) return false; |
| 234 } | 156 } |
| 235 | 157 |
| 236 return true; | 158 return true; |
| 237 } | 159 } |
| 238 | 160 |
| 239 // Split before all of the arguments, even the collections. | 161 // Split before all of the arguments, even the collections. |
| 240 return true; | 162 return true; |
| 241 } | 163 } |
| 242 | 164 |
| 165 /// Remembers that [rule] is the [Rule] immediately following this positional |
| 166 /// positional argument list. |
| 167 /// |
| 168 /// This is normally a [NamedRule] but [PositionalRule] is also used for the |
| 169 /// property accesses at the beginning of a call chain, in which case this |
| 170 /// is just a [SimpleRule]. |
| 171 void setNamedArgsRule(Rule rule) { |
| 172 _namedArgsRule = rule; |
| 173 } |
| 174 |
| 175 /// Constrains the named argument list to at least move to the next line if |
| 176 /// there are any splits in the positional arguments. Prevents things like: |
| 177 /// |
| 178 /// function( |
| 179 /// argument, |
| 180 /// argument, named: argument); |
| 243 int constrain(int value, Rule other) { | 181 int constrain(int value, Rule other) { |
| 244 var constrained = super.constrain(value, other); | 182 var constrained = super.constrain(value, other); |
| 245 if (constrained != null) return constrained; | 183 if (constrained != null) return constrained; |
| 246 | 184 |
| 185 // Handle the relationship between the positional and named args. |
| 186 if (other == _namedArgsRule) { |
| 187 // If the positional args are one-per-line, the named args are too. |
| 188 if (value == fullySplitValue) return _namedArgsRule.fullySplitValue; |
| 189 |
| 190 // Otherwise, if there is any split in the positional arguments, don't |
| 191 // allow the named arguments on the same line as them. |
| 192 if (value != 0) return -1; |
| 193 } |
| 194 |
| 247 // Decide how to constrain the collection rule. | 195 // Decide how to constrain the collection rule. |
| 248 if (other != _collectionRule) return null; | 196 if (other != _collectionRule) return null; |
| 249 | 197 |
| 250 // If all of the collections are in the named arguments, [_collectionRule] | 198 // If all of the collections are in the named arguments, [_collectionRule] |
| 251 // will not be null, but we don't have to handle it. | 199 // will not be null, but we don't have to handle it. |
| 252 if (_leadingCollections == 0 && _trailingCollections == 0) return null; | 200 if (_leadingCollections == 0 && _trailingCollections == 0) return null; |
| 253 | 201 |
| 254 // If we aren't splitting any args, we can split the collection. | 202 // If we aren't splitting any args, we can split the collection. |
| 255 if (value == Rule.unsplit) return null; | 203 if (value == Rule.unsplit) return null; |
| 256 | 204 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 279 } | 227 } |
| 280 | 228 |
| 281 // Only split before the non-collection arguments. This case only comes into | 229 // Only split before the non-collection arguments. This case only comes into |
| 282 // play when we do want to split the collection, so force that here. | 230 // play when we do want to split the collection, so force that here. |
| 283 if (value == _arguments.length + 1) return 1; | 231 if (value == _arguments.length + 1) return 1; |
| 284 | 232 |
| 285 // Split before all of the arguments, even the collections. We'll allow | 233 // Split before all of the arguments, even the collections. We'll allow |
| 286 // them to split but indent their bodies if they do. | 234 // them to split but indent their bodies if they do. |
| 287 return null; | 235 return null; |
| 288 } | 236 } |
| 237 |
| 238 String toString() => "Pos${super.toString()}"; |
| 289 } | 239 } |
| 290 | 240 |
| 291 /// Splitting rule for a list of named arguments or parameters. Its values mean: | 241 /// Splitting rule for a list of named arguments or parameters. Its values mean: |
| 292 /// | 242 /// |
| 293 /// * Do not split at all. | 243 /// * Do not split at all. |
| 294 /// * Split only before first argument. | 244 /// * Split only before first argument. |
| 295 /// * Split before all arguments. | 245 /// * Split before all arguments. |
| 296 class NamedRule extends ArgumentRule { | 246 class NamedRule extends ArgumentRule { |
| 297 int get numValues => 3; | 247 int get numValues => 3; |
| 298 | 248 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 326 // split. | 276 // split. |
| 327 if (value == 1) return Rule.unsplit; | 277 if (value == 1) return Rule.unsplit; |
| 328 | 278 |
| 329 // Split before all of the arguments, even the collections. We'll allow | 279 // Split before all of the arguments, even the collections. We'll allow |
| 330 // them to split but indent their bodies if they do. | 280 // them to split but indent their bodies if they do. |
| 331 return null; | 281 return null; |
| 332 } | 282 } |
| 333 | 283 |
| 334 String toString() => "Named${super.toString()}"; | 284 String toString() => "Named${super.toString()}"; |
| 335 } | 285 } |
| OLD | NEW |