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

Side by Side Diff: packages/dart_style/lib/src/rule/rule.dart

Issue 1521693002: Roll Observatory deps (charted -> ^0.3.0) (Closed) Base URL: https://chromium.googlesource.com/external/github.com/dart-lang/observatory_pub_packages.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
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.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
11 /// be split. 11 /// be split.
12 abstract class Rule extends FastHash { 12 class Rule extends FastHash {
13 /// Rule value that splits no chunks.
14 ///
15 /// Every rule is required to treat this value as fully unsplit.
16 static const unsplit = 0;
17
18 /// Rule constraint value that means "any value as long as something splits".
19 ///
20 /// It disallows [unsplit] but allows any other value.
21 static const mustSplit = -1;
22
13 /// The number of different states this rule can be in. 23 /// The number of different states this rule can be in.
14 /// 24 ///
15 /// Each state determines which set of chunks using this rule are split and 25 /// 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 26 /// 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 27 /// always means "no chunks are split" and increasing values by convention
18 /// mean increasingly undesirable splits. 28 /// mean increasingly undesirable splits.
19 int get numValues; 29 ///
30 /// By default, a rule has two values: fully unsplit and fully split.
31 int get numValues => 2;
20 32
21 /// 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.
22 /// 34 ///
23 /// 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.
24 int get fullySplitValue => numValues - 1; 36 int get fullySplitValue => numValues - 1;
25 37
26 int get cost => Cost.normal; 38 final int cost;
27 39
28 /// During line splitting [LineSplitter] sets this to the index of this 40 /// During line splitting [LineSplitter] sets this to the index of this
29 /// rule in its list of rules. 41 /// rule in its list of rules.
30 int index; 42 int index;
31 43
44 /// If `true`, the rule has been "hardened" meaning it's been placed into a
45 /// permanent "must fully split" state.
46 bool get isHardened => _isHardened;
47 bool _isHardened = false;
48
32 /// The other [Rule]s that "surround" this one (and care about that fact). 49 /// The other [Rule]s that "surround" this one (and care about that fact).
33 /// 50 ///
34 /// In many cases, if a split occurs inside an expression, surrounding rules 51 /// 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 52 /// also want to split too. For example, a split in the middle of an argument
36 /// forces the entire argument list to also split. 53 /// forces the entire argument list to also split.
37 /// 54 ///
38 /// This tracks those relationships. If this rule splits, (sets its value to 55 /// 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 56 /// [fullySplitValue]) then all of the outer rules will also be set to their
40 /// fully split value. 57 /// fully split value.
41 /// 58 ///
42 /// This contains all direct as well as transitive relationships. If A 59 /// 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. 60 /// 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>(); 61 final Set<Rule> _outerRules = new Set<Rule>();
46 62
47 /// Adds [inner] as an inner rule of this rule if it cares about inner rules. 63 /// Adds [inner] as an inner rule of this rule if it cares about inner rules.
48 /// 64 ///
49 /// When an inner rule splits, it forces any surrounding outer rules to also 65 /// When an inner rule splits, it forces any surrounding outer rules to also
50 /// split. 66 /// split.
51 void contain(Rule inner) { 67 void contain(Rule inner) {
52 if (!splitsOnInnerRules) return; 68 if (!splitsOnInnerRules) return;
53 inner._outerRules.add(this); 69 inner._outerRules.add(this);
54 } 70 }
55 71
56 /// Whether this rule cares about rules that it contains. 72 /// Whether this rule cares about rules that it contains.
57 /// 73 ///
58 /// If `true` then inner rules will constrain this one and force it to split 74 /// 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 75 /// when they split. Otherwise, it can split independently of any contained
60 /// rules. 76 /// rules.
61 bool get splitsOnInnerRules => true; 77 bool get splitsOnInnerRules => true;
62 78
63 bool isSplit(int value, Chunk chunk); 79 Rule([int cost]) : cost = cost ?? Cost.normal;
80
81 /// Creates a new rule that is already fully split.
82 Rule.hard() : cost = 0 {
83 // Set the cost to zero since it will always be applied, so there's no
84 // point in penalizing it.
85 //
86 // 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
88 // between the elements or statements.
89 harden();
90 }
91
92 /// Fixes this rule into a "fully split" state.
93 void harden() {
94 _isHardened = true;
95 }
96
97 /// Returns `true` if [chunk] should split when this rule has [value].
98 bool isSplit(int value, Chunk chunk) {
99 if (_isHardened) return true;
100
101 if (value == Rule.unsplit) return false;
102
103 // Let the subclass decide.
104 return isSplitAtValue(value, chunk);
105 }
106
107 /// Subclasses can override this to determine which values split which chunks.
108 ///
109 /// By default, this assumes every chunk splits.
110 bool isSplitAtValue(value, chunk) => true;
64 111
65 /// Given that this rule has [value], determine if [other]'s value should be 112 /// Given that this rule has [value], determine if [other]'s value should be
66 /// constrained. 113 /// constrained.
67 /// 114 ///
68 /// Allows relationships between rules like "if I split, then this should 115 /// 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 116 /// 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 117 /// value. Returns -1 to allow [other] to take any non-zero value. Returns
71 /// null to not constrain other. 118 /// null to not constrain other.
72 int constrain(int value, Rule other) { 119 int constrain(int value, Rule other) {
73 // By default, any implied rule will be fully split if this one is fully 120 // By default, any containing rule will be fully split if this one is split.
74 // split. 121 if (value == Rule.unsplit) return null;
75 if (value == 0) return null;
76 if (_outerRules.contains(other)) return other.fullySplitValue; 122 if (_outerRules.contains(other)) return other.fullySplitValue;
77 123
78 return null; 124 return null;
79 } 125 }
80 126
127 /// A protected method for subclasses to add the rules that they constrain
128 /// to [rules].
129 ///
130 /// Called by [Rule] the first time [constrainedRules] is accessed.
131 void addConstrainedRules(Set<Rule> rules) {}
132
133 /// Discards constraints on any rule that doesn't have an index.
134 ///
135 /// 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
137 /// 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
139 /// empty list of metadata annotations.
140 ///
141 /// This removes all of those.
142 void forgetUnusedRules() {
143 _outerRules.retainWhere((rule) => rule.index != null);
144
145 // Clear the cached ones too.
146 _constrainedRules = null;
147 _allConstrainedRules = null;
148 }
149
150 /// The other [Rule]s that this rule places immediate constraints on.
151 Set<Rule> get constrainedRules {
152 // 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
154 // up.
155 if (_constrainedRules == null) {
156 _constrainedRules = _outerRules.toSet();
157 addConstrainedRules(_constrainedRules);
158 }
159
160 return _constrainedRules;
161 }
162
163 Set<Rule> _constrainedRules;
164
165 /// The transitive closure of all of the rules this rule places constraints
166 /// on, directly or indirectly, including itself.
167 Set<Rule> get allConstrainedRules {
168 if (_allConstrainedRules == null) {
169 visit(Rule rule) {
170 if (_allConstrainedRules.contains(rule)) return;
171
172 _allConstrainedRules.add(rule);
173 rule.constrainedRules.forEach(visit);
174 }
175
176 _allConstrainedRules = new Set();
177 visit(this);
178 }
179
180 return _allConstrainedRules;
181 }
182
183 Set<Rule> _allConstrainedRules;
184
81 String toString() => "$id"; 185 String toString() => "$id";
82 } 186 }
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 }
OLDNEW
« no previous file with comments | « packages/dart_style/lib/src/rule/metadata.dart ('k') | packages/dart_style/lib/src/rule/type_argument.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698