OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library dart_style.src.rule.rule; | |
6 | |
7 import '../chunk.dart'; | |
8 import '../fast_hash.dart'; | |
9 | |
10 /// A constraint that determines the different ways a related set of chunks may | |
11 /// be split. | |
12 abstract class Rule extends FastHash { | |
13 /// The number of different states this rule can be in. | |
14 /// | |
15 /// Each state determines which set of chunks using this rule are split and | |
16 /// which aren't. Values range from zero to one minus this. Value zero | |
17 /// always means "no chunks are split" and increasing values by convention | |
18 /// mean increasingly undesirable splits. | |
19 int get numValues; | |
20 | |
21 /// The rule value that forces this rule into its maximally split state. | |
22 /// | |
23 /// By convention, this is the highest of the range of allowed values. | |
24 int get fullySplitValue => numValues - 1; | |
25 | |
26 int get cost => Cost.normal; | |
27 | |
28 /// During line splitting [LineSplitter] sets this to the index of this | |
29 /// rule in its list of rules. | |
30 int index; | |
31 | |
32 /// The other [Rule]s that "surround" this one (and care about that fact). | |
33 /// | |
34 /// In many cases, if a split occurs inside an expression, surrounding rules | |
35 /// also want to split too. For example, a split in the middle of an argument | |
36 /// forces the entire argument list to also split. | |
37 /// | |
38 /// This tracks those relationships. If this rule splits, (sets its value to | |
39 /// [fullySplitValue]) then all of the outer rules will also be set to their | |
40 /// fully split value. | |
41 /// | |
42 /// This contains all direct as well as transitive relationships. If A | |
43 /// contains B which contains C, C's outerRules contains both B and A. | |
44 Iterable<Rule> get outerRules => _outerRules; | |
45 final Set<Rule> _outerRules = new Set<Rule>(); | |
46 | |
47 /// Adds [inner] as an inner rule of this rule if it cares about inner rules. | |
48 /// | |
49 /// When an inner rule splits, it forces any surrounding outer rules to also | |
50 /// split. | |
51 void contain(Rule inner) { | |
52 if (!splitsOnInnerRules) return; | |
53 inner._outerRules.add(this); | |
54 } | |
55 | |
56 /// Whether this rule cares about rules that it contains. | |
57 /// | |
58 /// If `true` then inner rules will constrain this one and force it to split | |
59 /// when they split. Otherwise, it can split independently of any contained | |
60 /// rules. | |
61 bool get splitsOnInnerRules => true; | |
62 | |
63 bool isSplit(int value, Chunk chunk); | |
64 | |
65 /// Given that this rule has [value], determine if [other]'s value should be | |
66 /// constrained. | |
67 /// | |
68 /// Allows relationships between rules like "if I split, then this should | |
69 /// split too". Returns a non-negative value to force [other] to take that | |
70 /// value. Returns -1 to allow [other] to take any non-zero value. Returns | |
71 /// null to not constrain other. | |
72 int constrain(int value, Rule other) { | |
73 // By default, any implied rule will be fully split if this one is fully | |
74 // split. | |
75 if (value == 0) return null; | |
76 if (_outerRules.contains(other)) return other.fullySplitValue; | |
77 | |
78 return null; | |
79 } | |
80 | |
81 String toString() => "$id"; | |
82 } | |
83 | |
84 /// A rule that always splits a chunk. | |
85 class HardSplitRule extends Rule { | |
86 int get numValues => 1; | |
87 | |
88 /// It's always going to be applied, so there's no point in penalizing it. | |
89 /// | |
90 /// Also, this avoids doubled counting in literal blocks where there is both | |
91 /// a split in the outer chunk containing the block and the inner hard split | |
92 /// between the elements or statements. | |
93 int get cost => 0; | |
94 | |
95 /// It's always split anyway. | |
96 bool get splitsOnInnerRules => false; | |
97 | |
98 bool isSplit(int value, Chunk chunk) => true; | |
99 | |
100 String toString() => "Hard"; | |
101 } | |
102 | |
103 /// A basic rule that has two states: unsplit or split. | |
104 class SimpleRule extends Rule { | |
105 /// Two values: 0 is unsplit, 1 is split. | |
106 int get numValues => 2; | |
107 | |
108 final int cost; | |
109 | |
110 final bool splitsOnInnerRules; | |
111 | |
112 SimpleRule({int cost, bool splitsOnInnerRules}) | |
113 : cost = cost != null ? cost : Cost.normal, | |
114 splitsOnInnerRules = | |
115 splitsOnInnerRules != null ? splitsOnInnerRules : true; | |
116 | |
117 bool isSplit(int value, Chunk chunk) => value == 1; | |
118 | |
119 String toString() => "Simple${super.toString()}"; | |
120 } | |
OLD | NEW |