| 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. | 
| 11 abstract class ArgumentRule extends Rule { | 11 abstract class ArgumentRule extends Rule { | 
| 12   /// The rule used to split block arguments in the argument list, if any. | 12   /// The rule used to split collections in the argument list, if any. | 
| 13   final Rule _blockRule; | 13   final Rule _collectionRule; | 
| 14 | 14 | 
| 15   /// If true, then inner rules that are written will force this rule to split. | 15   /// If true, then inner rules that are written will force this rule to split. | 
| 16   /// | 16   /// | 
| 17   /// Temporarily disabled while writing block arguments so that they can be | 17   /// Temporarily disabled while writing collectio arguments so that they can be | 
| 18   /// multi-line without forcing the whole argument list to split. | 18   /// multi-line without forcing the whole argument list to split. | 
| 19   bool _trackInnerRules = true; | 19   bool _trackInnerRules = true; | 
| 20 | 20 | 
| 21   /// Don't split when an inner block rule splits. | 21   /// Don't split when an inner collection rule splits. | 
| 22   bool get splitsOnInnerRules => _trackInnerRules; | 22   bool get splitsOnInnerRules => _trackInnerRules; | 
| 23 | 23 | 
| 24   /// Creates a new rule for a positional argument list. | 24   /// Creates a new rule for a positional argument list. | 
| 25   /// | 25   /// | 
| 26   /// If [_blockRule] is given, it is the rule used to split the block | 26   /// If [_collectionRule] is given, it is the rule used to split the | 
| 27   /// arguments in the list. | 27   /// collections in the list. | 
| 28   ArgumentRule(this._blockRule); | 28   ArgumentRule(this._collectionRule); | 
| 29 | 29 | 
| 30   /// Called before a block argument is written. | 30   /// Called before a collection argument is written. | 
| 31   /// | 31   /// | 
| 32   /// Disables tracking inner rules while a block argument is being written. | 32   /// Disables tracking inner rules while a collection argument is written. | 
| 33   void beforeBlockArgument() { | 33   void beforeCollection() { | 
| 34     assert(_trackInnerRules == true); | 34     assert(_trackInnerRules == true); | 
| 35     _trackInnerRules = false; | 35     _trackInnerRules = false; | 
| 36   } | 36   } | 
| 37 | 37 | 
| 38   /// Called after a block argument is complete. | 38   /// Called after a collection argument is complete. | 
| 39   /// | 39   /// | 
| 40   /// Re-enables tracking inner rules after a block argument is complete. | 40   /// Re-enables tracking inner rules. | 
| 41   void afterBlockArgument() { | 41   void afterCollection() { | 
| 42     assert(_trackInnerRules == false); | 42     assert(_trackInnerRules == false); | 
| 43     _trackInnerRules = true; | 43     _trackInnerRules = true; | 
| 44   } | 44   } | 
| 45 } | 45 } | 
| 46 | 46 | 
| 47 /// Base class for a rule for handling positional argument lists. | 47 /// Base class for a rule for handling positional argument lists. | 
| 48 abstract class PositionalRule extends ArgumentRule { | 48 abstract class PositionalRule extends ArgumentRule { | 
| 49   /// The chunks prior to each positional argument. | 49   /// The chunks prior to each positional argument. | 
| 50   final List<Chunk> _arguments = []; | 50   final List<Chunk> _arguments = []; | 
| 51 | 51 | 
| 52   /// If there are named arguments following these positional ones, this will | 52   /// If there are named arguments following these positional ones, this will | 
| 53   /// be their rule. | 53   /// be their rule. | 
| 54   Rule _namedArgsRule; | 54   Rule _namedArgsRule; | 
| 55 | 55 | 
| 56   /// Creates a new rule for a positional argument list. | 56   /// Creates a new rule for a positional argument list. | 
| 57   /// | 57   /// | 
| 58   /// If [blockRule] is given, it is the rule used to split the block arguments | 58   /// If [collectionRule] is given, it is the rule used to split the collection | 
| 59   /// in the list. | 59   /// arguments in the list. | 
| 60   PositionalRule(Rule blockRule) : super(blockRule); | 60   PositionalRule(Rule collectionRule) : super(collectionRule); | 
| 61 | 61 | 
| 62   /// Remembers [chunk] as containing the split that occurs right before an | 62   /// Remembers [chunk] as containing the split that occurs right before an | 
| 63   /// argument in the list. | 63   /// argument in the list. | 
| 64   void beforeArgument(Chunk chunk) { | 64   void beforeArgument(Chunk chunk) { | 
| 65     _arguments.add(chunk); | 65     _arguments.add(chunk); | 
| 66   } | 66   } | 
| 67 | 67 | 
| 68   /// Remembers that [rule] is the [NamedArgsRule] immediately following this | 68   /// Remembers that [rule] is the [NamedArgsRule] immediately following this | 
| 69   /// positional argument list. | 69   /// positional argument list. | 
| 70   void setNamedArgsRule(NamedRule rule) { | 70   void setNamedArgsRule(NamedRule rule) { | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 89       // Otherwise, if there is any split in the positional arguments, don't | 89       // Otherwise, if there is any split in the positional arguments, don't | 
| 90       // allow the named arguments on the same line as them. | 90       // allow the named arguments on the same line as them. | 
| 91       if (value != 0) return -1; | 91       if (value != 0) return -1; | 
| 92     } | 92     } | 
| 93 | 93 | 
| 94     return null; | 94     return null; | 
| 95   } | 95   } | 
| 96 } | 96 } | 
| 97 | 97 | 
| 98 /// Split rule for a call with a single positional argument (which may or may | 98 /// Split rule for a call with a single positional argument (which may or may | 
| 99 /// not be a block argument.) | 99 /// not be a collection argument.) | 
| 100 class SinglePositionalRule extends PositionalRule { | 100 class SinglePositionalRule extends PositionalRule { | 
| 101   int get numValues => 2; | 101   int get numValues => 2; | 
| 102 | 102 | 
| 103   /// If there is only a single argument, allow it to split internally without | 103   /// If there is only a single non-collection argument, allow it to split | 
| 104   /// forcing a split before the argument. | 104   /// internally without forcing a split before the argument. | 
| 105   bool get splitsOnInnerRules => false; | 105   final bool splitsOnInnerRules; | 
|  | 106 | 
|  | 107   bool hack = false; | 
| 106 | 108 | 
| 107   /// Creates a new rule for a positional argument list. | 109   /// Creates a new rule for a positional argument list. | 
| 108   /// | 110   /// | 
| 109   /// If [blockRule] is given, it is the rule used to split the block arguments | 111   /// If [collectionRule] is given, it is the rule used to split the | 
| 110   /// in the list. If [isSingleArgument] is `true`, then the argument list will | 112   /// collections in the list. If [splitsOnInnerRules] is `true`, then we will | 
| 111   /// only contain a single argument. | 113   /// split before the argument if the argument itself contains a split. | 
| 112   SinglePositionalRule(Rule blockRule) : super(blockRule); | 114   SinglePositionalRule(Rule collectionRule, {bool splitsOnInnerRules}) | 
|  | 115       : super(collectionRule), | 
|  | 116         splitsOnInnerRules = splitsOnInnerRules | 
|  | 117             != null | 
|  | 118             ? splitsOnInnerRules : false; | 
| 113 | 119 | 
| 114   bool isSplit(int value, Chunk chunk) => value == 1; | 120   bool isSplit(int value, Chunk chunk) => value == 1; | 
| 115 | 121 | 
| 116   int constrain(int value, Rule other) { | 122   int constrain(int value, Rule other) { | 
| 117     var constrained = super.constrain(value, other); | 123     var constrained = super.constrain(value, other); | 
| 118     if (constrained != null) return constrained; | 124     if (constrained != null) return constrained; | 
| 119 | 125 | 
| 120     if (other != _blockRule) return null; | 126     if (other != _collectionRule) return null; | 
| 121 | 127 | 
| 122     // If we aren't splitting any args, we can split the block. | 128     // If we aren't splitting any args, we can split the collection. | 
| 123     if (value == 0) return null; | 129     if (value == 0) return null; | 
| 124 | 130 | 
| 125     // We are splitting before a block, so don't let it split internally. | 131     // We are splitting before a collection, so don't let it split internally. | 
| 126     return 0; | 132     return 0; | 
| 127   } | 133   } | 
| 128 | 134 | 
| 129   String toString() => "1Pos${super.toString()}"; | 135   String toString() => "1Pos${super.toString()}"; | 
| 130 } | 136 } | 
| 131 | 137 | 
| 132 /// Split rule for a call with more than one positional argument. | 138 /// Split rule for a call with more than one positional argument. | 
| 133 /// | 139 /// | 
| 134 /// The number of values is based on the number of arguments and whether or not | 140 /// The number of values is based on the number of arguments and whether or not | 
| 135 /// there are bodies. The first two values are always: | 141 /// there are bodies. The first two values are always: | 
| 136 /// | 142 /// | 
| 137 /// * 0: Do not split at all. | 143 /// * 0: Do not split at all. | 
| 138 /// * 1: Split only before the first argument. | 144 /// * 1: Split only before the first argument. | 
| 139 /// | 145 /// | 
| 140 /// Then there is a value for each argument, to split before that argument. | 146 /// Then there is a value for each argument, to split before that argument. | 
| 141 /// These values work back to front. So, for a two-argument list, value 2 splits | 147 /// These values work back to front. So, for a two-argument list, value 2 splits | 
| 142 /// after the second argument and value 3 splits after the first. | 148 /// after the second argument and value 3 splits after the first. | 
| 143 /// | 149 /// | 
| 144 /// Then there is a value that splits before every argument. | 150 /// Then there is a value that splits before every argument. | 
| 145 /// | 151 /// | 
| 146 /// Finally, if there are block arguments, there is another value that splits | 152 /// Finally, if there are collection arguments, there is another value that | 
| 147 /// before all of the non-block arguments, but does not split before the block | 153 /// splits before all of the non-collection arguments, but does not split | 
| 148 /// ones, so that they can split internally. | 154 /// before the collections, so that they can split internally. | 
| 149 class MultiplePositionalRule extends PositionalRule { | 155 class MultiplePositionalRule extends PositionalRule { | 
| 150   /// The number of leading block arguments. | 156   /// The number of leading collection arguments. | 
| 151   /// | 157   /// | 
| 152   /// This and [_trailingBlocks] cannot both be positive. If every argument is | 158   /// This and [_trailingCollections] cannot both be positive. If every | 
| 153   /// a block, this will be [_arguments.length] and [_trailingBlocks] will be 0. | 159   /// argument is a collection, this will be [_arguments.length] and | 
| 154   final int _leadingBlocks; | 160   /// [_trailingCollections] will be 0. | 
|  | 161   final int _leadingCollections; | 
| 155 | 162 | 
| 156   /// The number of trailing block arguments. | 163   /// The number of trailing collections. | 
| 157   /// | 164   /// | 
| 158   /// This and [_leadingBlocks] cannot both be positive. | 165   /// This and [_leadingCollections] cannot both be positive. | 
| 159   final int _trailingBlocks; | 166   final int _trailingCollections; | 
| 160 | 167 | 
| 161   int get numValues { | 168   int get numValues { | 
| 162     // Can split before any one argument, none, or all. | 169     // Can split before any one argument, none, or all. | 
| 163     var result = 2 + _arguments.length; | 170     var result = 2 + _arguments.length; | 
| 164 | 171 | 
| 165     // When there are block arguments, there are two ways we can split on "all" | 172     // When there are collection arguments, there are two ways we can split on | 
| 166     // arguments: | 173     // "all" arguments: | 
| 167     // | 174     // | 
| 168     // - Split on just the non-block arguments, and force the block arguments | 175     // - Split on just the non-collection arguments, and force the collection | 
| 169     //   to split internally. | 176     //   arguments to split internally. | 
| 170     // - Split on all of them including the block arguments, and do not allow | 177     // - Split on all of them including the collection arguments, and do not | 
| 171     //   the block arguments to split internally. | 178     //   allow the collection arguments to split internally. | 
| 172     if (_leadingBlocks > 0 || _trailingBlocks > 0) result++; | 179     if (_leadingCollections > 0 || _trailingCollections > 0) result++; | 
| 173 | 180 | 
| 174     return result; | 181     return result; | 
| 175   } | 182   } | 
| 176 | 183 | 
| 177   MultiplePositionalRule( | 184   MultiplePositionalRule( | 
| 178       Rule blockRule, this._leadingBlocks, this._trailingBlocks) | 185       Rule collectionRule, this._leadingCollections, this._trailingCollections) | 
| 179       : super(blockRule); | 186       : super(collectionRule); | 
| 180 | 187 | 
| 181   String toString() => "*Pos${super.toString()}"; | 188   String toString() => "*Pos${super.toString()}"; | 
| 182 | 189 | 
| 183   bool isSplit(int value, Chunk chunk) { | 190   bool isSplit(int value, Chunk chunk) { | 
| 184     // Don't split at all. | 191     // Don't split at all. | 
| 185     if (value == 0) return false; | 192     if (value == 0) return false; | 
| 186 | 193 | 
| 187     // Split only before the first argument. Keep the entire argument list | 194     // Split only before the first argument. Keep the entire argument list | 
| 188     // together on the next line. | 195     // together on the next line. | 
| 189     if (value == 1) return chunk == _arguments.first; | 196     if (value == 1) return chunk == _arguments.first; | 
| 190 | 197 | 
| 191     // Split before a single argument. Try later arguments before earlier ones | 198     // Split before a single argument. Try later arguments before earlier ones | 
| 192     // to try to keep as much on the first line as possible. | 199     // to try to keep as much on the first line as possible. | 
| 193     if (value <= _arguments.length) { | 200     if (value <= _arguments.length) { | 
| 194       var argument = _arguments.length - value + 1; | 201       var argument = _arguments.length - value + 1; | 
| 195       return chunk == _arguments[argument]; | 202       return chunk == _arguments[argument]; | 
| 196     } | 203     } | 
| 197 | 204 | 
| 198     // Only split before the non-block arguments. Note that we consider this | 205     // Only split before the non-collection arguments. | 
| 199     // case to correctly prefer this over the latter case because function |  | 
| 200     // block arguments always split internally. Preferring this case ensures we |  | 
| 201     // avoid: |  | 
| 202     // |  | 
| 203     //     function( // <-- :( |  | 
| 204     //         () { |  | 
| 205     //        ... |  | 
| 206     //     }), |  | 
| 207     //         argument, |  | 
| 208     //         ... |  | 
| 209     //         argument; |  | 
| 210     if (value == _arguments.length + 1) { | 206     if (value == _arguments.length + 1) { | 
| 211       for (var i = 0; i < _leadingBlocks; i++) { | 207       for (var i = 0; i < _leadingCollections; i++) { | 
| 212         if (chunk == _arguments[i]) return false; | 208         if (chunk == _arguments[i]) return false; | 
| 213       } | 209       } | 
| 214 | 210 | 
| 215       for (var i = _arguments.length - _trailingBlocks; | 211       for (var i = _arguments.length - _trailingCollections; | 
| 216           i < _arguments.length; | 212           i < _arguments.length; | 
| 217           i++) { | 213           i++) { | 
| 218         if (chunk == _arguments[i]) return false; | 214         if (chunk == _arguments[i]) return false; | 
| 219       } | 215       } | 
| 220 | 216 | 
| 221       return true; | 217       return true; | 
| 222     } | 218     } | 
| 223 | 219 | 
| 224     // Split before all of the arguments, even the block ones. | 220     // Split before all of the arguments, even the collections. | 
| 225     return true; | 221     return true; | 
| 226   } | 222   } | 
| 227 | 223 | 
| 228   int constrain(int value, Rule other) { | 224   int constrain(int value, Rule other) { | 
| 229     var constrained = super.constrain(value, other); | 225     var constrained = super.constrain(value, other); | 
| 230     if (constrained != null) return constrained; | 226     if (constrained != null) return constrained; | 
| 231 | 227 | 
| 232     if (other != _blockRule) return null; | 228     if (other != _collectionRule) return null; | 
| 233 | 229 | 
| 234     // If we aren't splitting any args, we can split the block. | 230     // If we aren't splitting any args, we can split the collection. | 
| 235     if (value == 0) return null; | 231     if (value == 0) return null; | 
| 236 | 232 | 
| 237     // Split only before the first argument. | 233     // Split only before the first argument. | 
| 238     if (value == 1) { | 234     if (value == 1) { | 
| 239       if (_leadingBlocks > 0) { | 235       if (_leadingCollections > 0) { | 
| 240         // We are splitting before a block, so don't let it split internally. | 236         // We are splitting before a collection, so don't let it split | 
|  | 237         // internally. | 
| 241         return 0; | 238         return 0; | 
| 242       } else { | 239       } else { | 
| 243         // The split is outside of the blocks so they can split or not. | 240         // The split is outside of the collections so they can split or not. | 
| 244         return null; | 241         return null; | 
| 245       } | 242       } | 
| 246     } | 243     } | 
| 247 | 244 | 
| 248     // Split before a single argument. If it's in the middle of the block | 245     // Split before a single argument. If it's in the middle of the collection | 
| 249     // arguments, don't allow them to split. | 246     // arguments, don't allow them to split. | 
| 250     if (value <= _arguments.length) { | 247     if (value <= _arguments.length) { | 
| 251       var argument = _arguments.length - value + 1; | 248       var argument = _arguments.length - value + 1; | 
| 252       if (argument < _leadingBlocks) return 0; | 249       if (argument < _leadingCollections) return 0; | 
| 253       if (argument >= _arguments.length - _trailingBlocks) return 0; | 250       if (argument >= _arguments.length - _trailingCollections) return 0; | 
| 254 | 251 | 
| 255       return null; | 252       return null; | 
| 256     } | 253     } | 
| 257 | 254 | 
| 258     // Only split before the non-block arguments. This case only comes into | 255     // Only split before the non-collection arguments. This case only comes into | 
| 259     // play when we do want to split the blocks, so force that here. | 256     // play when we do want to split the collection, so force that here. | 
| 260     if (value == _arguments.length + 1) return 1; | 257     if (value == _arguments.length + 1) return 1; | 
| 261 | 258 | 
| 262     // Split before all of the arguments, even the block ones, so don't let | 259     // Split before all of the arguments, even the collection, so don't let | 
| 263     // them split. | 260     // them split. | 
| 264     return 0; | 261     return 0; | 
| 265   } | 262   } | 
| 266 } | 263 } | 
| 267 | 264 | 
| 268 /// Splitting rule for a list of named arguments or parameters. Its values mean: | 265 /// Splitting rule for a list of named arguments or parameters. Its values mean: | 
| 269 /// | 266 /// | 
| 270 /// * 0: Do not split at all. | 267 /// * 0: Do not split at all. | 
| 271 /// * 1: Split only before first argument. | 268 /// * 1: Split only before first argument. | 
| 272 /// * 2: Split before all arguments, including the first. | 269 /// * 2: Split before all arguments, including the first. | 
| 273 class NamedRule extends ArgumentRule { | 270 class NamedRule extends ArgumentRule { | 
| 274   /// The chunk prior to the first named argument. | 271   /// The chunk prior to the first named argument. | 
| 275   Chunk _first; | 272   Chunk _first; | 
| 276 | 273 | 
| 277   int get numValues => 3; | 274   int get numValues => 3; | 
| 278 | 275 | 
| 279   NamedRule(Rule blockRule) : super(blockRule); | 276   NamedRule(Rule collectionRule) : super(collectionRule); | 
| 280 | 277 | 
| 281   void beforeArguments(Chunk chunk) { | 278   void beforeArguments(Chunk chunk) { | 
| 282     assert(_first == null); | 279     assert(_first == null); | 
| 283     _first = chunk; | 280     _first = chunk; | 
| 284   } | 281   } | 
| 285 | 282 | 
| 286   bool isSplit(int value, Chunk chunk) { | 283   bool isSplit(int value, Chunk chunk) { | 
| 287     switch (value) { | 284     switch (value) { | 
| 288       case 0: | 285       case 0: | 
| 289         return false; | 286         return false; | 
| 290       case 1: | 287       case 1: | 
| 291         return chunk == _first; | 288         return chunk == _first; | 
| 292       case 2: | 289       case 2: | 
| 293         return true; | 290         return true; | 
| 294     } | 291     } | 
| 295 | 292 | 
| 296     throw "unreachable"; | 293     throw "unreachable"; | 
| 297   } | 294   } | 
| 298 | 295 | 
| 299   int constrain(int value, Rule other) { | 296   int constrain(int value, Rule other) { | 
| 300     var constrained = super.constrain(value, other); | 297     var constrained = super.constrain(value, other); | 
| 301     if (constrained != null) return constrained; | 298     if (constrained != null) return constrained; | 
| 302 | 299 | 
| 303     if (other != _blockRule) return null; | 300     if (other != _collectionRule) return null; | 
| 304 | 301 | 
| 305     // If we aren't splitting any args, we can split the block. | 302     // If we aren't splitting any args, we can split the collection. | 
| 306     if (value == 0) return null; | 303     if (value == 0) return null; | 
| 307 | 304 | 
| 308     // Split before all of the arguments, even the block ones, so don't let | 305     // Split before all of the arguments, even the collections, so don't let | 
| 309     // them split. | 306     // them split. | 
| 310     return 0; | 307     return 0; | 
| 311   } | 308   } | 
| 312 | 309 | 
| 313   String toString() => "Named${super.toString()}"; | 310   String toString() => "Named${super.toString()}"; | 
| 314 } | 311 } | 
| OLD | NEW | 
|---|