| 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.rule; | 5 library dart_style.src.rule.rule; |
| 6 | 6 |
| 7 import '../chunk.dart'; | 7 import '../chunk.dart'; |
| 8 import '../fast_hash.dart'; | 8 import '../fast_hash.dart'; |
| 9 | 9 |
| 10 /// A constraint that determines the different ways a related set of chunks may | 10 /// A constraint that determines the different ways a related set of chunks may |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 /// mean increasingly undesirable splits. | 28 /// mean increasingly undesirable splits. |
| 29 /// | 29 /// |
| 30 /// By default, a rule has two values: fully unsplit and fully split. | 30 /// By default, a rule has two values: fully unsplit and fully split. |
| 31 int get numValues => 2; | 31 int get numValues => 2; |
| 32 | 32 |
| 33 /// The rule value that forces this rule into its maximally split state. | 33 /// The rule value that forces this rule into its maximally split state. |
| 34 /// | 34 /// |
| 35 /// By convention, this is the highest of the range of allowed values. | 35 /// By convention, this is the highest of the range of allowed values. |
| 36 int get fullySplitValue => numValues - 1; | 36 int get fullySplitValue => numValues - 1; |
| 37 | 37 |
| 38 final int cost; | 38 int get cost => _cost; |
| 39 final int _cost; |
| 39 | 40 |
| 40 /// During line splitting [LineSplitter] sets this to the index of this | 41 /// During line splitting [LineSplitter] sets this to the index of this |
| 41 /// rule in its list of rules. | 42 /// rule in its list of rules. |
| 42 int index; | 43 int index; |
| 43 | 44 |
| 44 /// If `true`, the rule has been "hardened" meaning it's been placed into a | 45 /// If `true`, the rule has been "hardened" meaning it's been placed into a |
| 45 /// permanent "must fully split" state. | 46 /// permanent "must fully split" state. |
| 46 bool get isHardened => _isHardened; | 47 bool get isHardened => _isHardened; |
| 47 bool _isHardened = false; | 48 bool _isHardened = false; |
| 48 | 49 |
| 49 /// The other [Rule]s that "surround" this one (and care about that fact). | 50 /// The other [Rule]s that are implied this one. |
| 50 /// | 51 /// |
| 51 /// In many cases, if a split occurs inside an expression, surrounding rules | 52 /// In many cases, if a split occurs inside an expression, surrounding rules |
| 52 /// also want to split too. For example, a split in the middle of an argument | 53 /// also want to split too. For example, a split in the middle of an argument |
| 53 /// forces the entire argument list to also split. | 54 /// forces the entire argument list to also split. |
| 54 /// | 55 /// |
| 55 /// This tracks those relationships. If this rule splits, (sets its value to | 56 /// This tracks those relationships. If this rule splits, (sets its value to |
| 56 /// [fullySplitValue]) then all of the outer rules will also be set to their | 57 /// [fullySplitValue]) then all of the surrounding implied rules are also set |
| 57 /// fully split value. | 58 /// to their fully split value. |
| 58 /// | 59 /// |
| 59 /// This contains all direct as well as transitive relationships. If A | 60 /// This contains all direct as well as transitive relationships. If A |
| 60 /// contains B which contains C, C's outerRules contains both B and A. | 61 /// contains B which contains C, C's outerRules contains both B and A. |
| 61 final Set<Rule> _outerRules = new Set<Rule>(); | 62 final Set<Rule> _implied = new Set<Rule>(); |
| 62 | 63 |
| 63 /// Adds [inner] as an inner rule of this rule if it cares about inner rules. | 64 /// Marks [other] as implied by this one. |
| 64 /// | 65 /// |
| 65 /// When an inner rule splits, it forces any surrounding outer rules to also | 66 /// That means that if this rule splits, then [other] is force to split too. |
| 66 /// split. | 67 void imply(Rule other) { |
| 67 void contain(Rule inner) { | 68 _implied.add(other); |
| 68 if (!splitsOnInnerRules) return; | |
| 69 inner._outerRules.add(this); | |
| 70 } | 69 } |
| 71 | 70 |
| 72 /// Whether this rule cares about rules that it contains. | 71 /// Whether this rule cares about rules that it contains. |
| 73 /// | 72 /// |
| 74 /// If `true` then inner rules will constrain this one and force it to split | 73 /// If `true` then inner rules will constrain this one and force it to split |
| 75 /// when they split. Otherwise, it can split independently of any contained | 74 /// when they split. Otherwise, it can split independently of any contained |
| 76 /// rules. | 75 /// rules. |
| 77 bool get splitsOnInnerRules => true; | 76 bool get splitsOnInnerRules => true; |
| 78 | 77 |
| 79 Rule([int cost]) : cost = cost ?? Cost.normal; | 78 Rule([int cost]) : _cost = cost ?? Cost.normal; |
| 80 | 79 |
| 81 /// Creates a new rule that is already fully split. | 80 /// Creates a new rule that is already fully split. |
| 82 Rule.hard() : cost = 0 { | 81 Rule.hard() : _cost = 0 { |
| 83 // Set the cost to zero since it will always be applied, so there's no | 82 // Set the cost to zero since it will always be applied, so there's no |
| 84 // point in penalizing it. | 83 // point in penalizing it. |
| 85 // | 84 // |
| 86 // Also, this avoids doubled counting in literal blocks where there is both | 85 // Also, this avoids doubled counting in literal blocks where there is both |
| 87 // a split in the outer chunk containing the block and the inner hard split | 86 // a split in the outer chunk containing the block and the inner hard split |
| 88 // between the elements or statements. | 87 // between the elements or statements. |
| 89 harden(); | 88 harden(); |
| 90 } | 89 } |
| 91 | 90 |
| 92 /// Fixes this rule into a "fully split" state. | 91 /// Fixes this rule into a "fully split" state. |
| 93 void harden() { | 92 void harden() { |
| 94 _isHardened = true; | 93 _isHardened = true; |
| 95 } | 94 } |
| 96 | 95 |
| 97 /// Returns `true` if [chunk] should split when this rule has [value]. | 96 /// Returns `true` if [chunk] should split when this rule has [value]. |
| 98 bool isSplit(int value, Chunk chunk) { | 97 bool isSplit(int value, Chunk chunk) { |
| 99 if (_isHardened) return true; | 98 if (_isHardened) return true; |
| 100 | 99 |
| 101 if (value == Rule.unsplit) return false; | 100 if (value == Rule.unsplit) return false; |
| 102 | 101 |
| 103 // Let the subclass decide. | 102 // Let the subclass decide. |
| 104 return isSplitAtValue(value, chunk); | 103 return isSplitAtValue(value, chunk); |
| 105 } | 104 } |
| 106 | 105 |
| 107 /// Subclasses can override this to determine which values split which chunks. | 106 /// Subclasses can override this to determine which values split which chunks. |
| 108 /// | 107 /// |
| 109 /// By default, this assumes every chunk splits. | 108 /// By default, this assumes every chunk splits. |
| 110 bool isSplitAtValue(value, chunk) => true; | 109 bool isSplitAtValue(int value, Chunk chunk) => true; |
| 111 | 110 |
| 112 /// Given that this rule has [value], determine if [other]'s value should be | 111 /// Given that this rule has [value], determine if [other]'s value should be |
| 113 /// constrained. | 112 /// constrained. |
| 114 /// | 113 /// |
| 115 /// Allows relationships between rules like "if I split, then this should | 114 /// Allows relationships between rules like "if I split, then this should |
| 116 /// split too". Returns a non-negative value to force [other] to take that | 115 /// split too". Returns a non-negative value to force [other] to take that |
| 117 /// value. Returns -1 to allow [other] to take any non-zero value. Returns | 116 /// value. Returns -1 to allow [other] to take any non-zero value. Returns |
| 118 /// null to not constrain other. | 117 /// null to not constrain other. |
| 119 int constrain(int value, Rule other) { | 118 int constrain(int value, Rule other) { |
| 120 // By default, any containing rule will be fully split if this one is split. | 119 // By default, any containing rule will be fully split if this one is split. |
| 121 if (value == Rule.unsplit) return null; | 120 if (value == Rule.unsplit) return null; |
| 122 if (_outerRules.contains(other)) return other.fullySplitValue; | 121 if (_implied.contains(other)) return other.fullySplitValue; |
| 123 | 122 |
| 124 return null; | 123 return null; |
| 125 } | 124 } |
| 126 | 125 |
| 127 /// A protected method for subclasses to add the rules that they constrain | 126 /// A protected method for subclasses to add the rules that they constrain |
| 128 /// to [rules]. | 127 /// to [rules]. |
| 129 /// | 128 /// |
| 130 /// Called by [Rule] the first time [constrainedRules] is accessed. | 129 /// Called by [Rule] the first time [constrainedRules] is accessed. |
| 131 void addConstrainedRules(Set<Rule> rules) {} | 130 void addConstrainedRules(Set<Rule> rules) {} |
| 132 | 131 |
| 133 /// Discards constraints on any rule that doesn't have an index. | 132 /// Discards constraints on any rule that doesn't have an index. |
| 134 /// | 133 /// |
| 135 /// This is called by [LineSplitter] after it has indexed all of the in-use | 134 /// This is called by [LineSplitter] after it has indexed all of the in-use |
| 136 /// rules. A rule may end up with a constraint on a rule that's no longer | 135 /// rules. A rule may end up with a constraint on a rule that's no longer |
| 137 /// used by any chunk. This can happen if the rule gets hardened, or if it | 136 /// used by any chunk. This can happen if the rule gets hardened, or if it |
| 138 /// simply never got used by a chunk. For example, a rule for splitting an | 137 /// simply never got used by a chunk. For example, a rule for splitting an |
| 139 /// empty list of metadata annotations. | 138 /// empty list of metadata annotations. |
| 140 /// | 139 /// |
| 141 /// This removes all of those. | 140 /// This removes all of those. |
| 142 void forgetUnusedRules() { | 141 void forgetUnusedRules() { |
| 143 _outerRules.retainWhere((rule) => rule.index != null); | 142 _implied.retainWhere((rule) => rule.index != null); |
| 144 | 143 |
| 145 // Clear the cached ones too. | 144 // Clear the cached ones too. |
| 146 _constrainedRules = null; | 145 _constrainedRules = null; |
| 147 _allConstrainedRules = null; | 146 _allConstrainedRules = null; |
| 148 } | 147 } |
| 149 | 148 |
| 150 /// The other [Rule]s that this rule places immediate constraints on. | 149 /// The other [Rule]s that this rule places immediate constraints on. |
| 151 Set<Rule> get constrainedRules { | 150 Set<Rule> get constrainedRules { |
| 152 // Lazy initialize this on first use. Note: Assumes this is only called | 151 // Lazy initialize this on first use. Note: Assumes this is only called |
| 153 // after the chunks have been written and any constraints have been wired | 152 // after the chunks have been written and any constraints have been wired |
| 154 // up. | 153 // up. |
| 155 if (_constrainedRules == null) { | 154 if (_constrainedRules == null) { |
| 156 _constrainedRules = _outerRules.toSet(); | 155 _constrainedRules = _implied.toSet(); |
| 157 addConstrainedRules(_constrainedRules); | 156 addConstrainedRules(_constrainedRules); |
| 158 } | 157 } |
| 159 | 158 |
| 160 return _constrainedRules; | 159 return _constrainedRules; |
| 161 } | 160 } |
| 162 | 161 |
| 163 Set<Rule> _constrainedRules; | 162 Set<Rule> _constrainedRules; |
| 164 | 163 |
| 165 /// The transitive closure of all of the rules this rule places constraints | 164 /// The transitive closure of all of the rules this rule places constraints |
| 166 /// on, directly or indirectly, including itself. | 165 /// on, directly or indirectly, including itself. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 177 visit(this); | 176 visit(this); |
| 178 } | 177 } |
| 179 | 178 |
| 180 return _allConstrainedRules; | 179 return _allConstrainedRules; |
| 181 } | 180 } |
| 182 | 181 |
| 183 Set<Rule> _allConstrainedRules; | 182 Set<Rule> _allConstrainedRules; |
| 184 | 183 |
| 185 String toString() => "$id"; | 184 String toString() => "$id"; |
| 186 } | 185 } |
| OLD | NEW |