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

Side by Side Diff: lib/src/line_prefix.dart

Issue 1255643002: New, simpler and faster line splitter. (Closed) Base URL: https://github.com/dart-lang/dart_style.git@master
Patch Set: Optimize nesting. Reformat. Created 5 years, 5 months 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
« no previous file with comments | « lib/src/debug.dart ('k') | lib/src/line_splitter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, 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.line_prefix;
6
7 import 'chunk.dart';
8 import 'nesting.dart';
9 import 'rule/rule.dart';
10
11 /// A prefix of a series of chunks and the context needed to uniquely describe
12 /// any shared state between the preceding and following chunks.
13 ///
14 /// This is used by [LineSplitter] to memoize suffixes whose best splits have
15 /// previously been calculated. For each unique [LinePrefix], there is a single
16 /// set of best splits for the remainder of the line following it.
17 ///
18 /// [LinePrefix] is a value type. It overloads [hashCode] and [==] and it's
19 /// critical that those be correct and efficient. These objects are used as
20 /// keys in the [LineSplitter]'s memoization table.
21 class LinePrefix {
22 /// The number of chunks in the prefix.
23 ///
24 /// The suffix is the remaining chunks starting at index [length].
25 final int length;
26
27 /// The [Rule]s that apply to chunks in the prefix and have thus already had
28 /// their values selected.
29 ///
30 /// Does not include rules that do not also appear in the suffix since they
31 /// don't affect the suffix.
32 final Map<Rule, int> ruleValues;
33
34 /// The number of characters of "statement-based" indentation of the line
35 /// after the prefix.
36 ///
37 /// This handles things like control flow, switch cases, and constructor
38 /// initialization lists that tweak the per-line indentation.
39 ///
40 /// For nested blocks, this also includes the indentation to push the entire
41 /// block over.
42 final int _indent;
43
44 final NestingSplitter _nesting;
45
46 /// The absolute starting column of the line after this chunk.
47 ///
48 /// This takes into account whether the line should be flush left or not.
49 int get column => _flushLeft ? 0 : _indent + _nesting.indent;
50 final bool _flushLeft;
51
52 /// Creates a new zero-length prefix with initial [indent] whose suffix is
53 /// the entire line.
54 LinePrefix(int indent, {bool flushLeft})
55 : this._(0, {}, indent, new NestingSplitter(), flushLeft: flushLeft);
56
57 LinePrefix._(this.length, this.ruleValues, this._indent, this._nesting,
58 {bool flushLeft: false})
59 : _flushLeft = flushLeft;
60
61 bool operator ==(other) {
62 if (other is! LinePrefix) return false;
63
64 if (length != other.length) return false;
65 if (_indent != other._indent) return false;
66 if (_flushLeft != other._flushLeft) return false;
67 if (_nesting != other._nesting) return false;
68
69 // Compare rule values.
70 if (ruleValues.length != other.ruleValues.length) return false;
71
72 for (var key in ruleValues.keys) {
73 if (other.ruleValues[key] != ruleValues[key]) return false;
74 }
75
76 return true;
77 }
78
79 int get hashCode => length.hashCode ^ _indent ^ _nesting.hashCode;
80
81 /// Create a new LinePrefix one chunk longer than this one using [ruleValues],
82 /// and assuming that we do not split before that chunk.
83 LinePrefix extend(Map<Rule, int> ruleValues) =>
84 new LinePrefix._(length + 1, ruleValues, _indent, _nesting,
85 flushLeft: _flushLeft);
86
87 /// Create a series of new LinePrefixes one chunk longer than this one using
88 /// [ruleValues], and assuming that the new [chunk] splits at an expression
89 /// boundary so there may be multiple possible different nesting stacks.
90 ///
91 /// If this prefix is for a nested block, [blockIndentation] may be nonzero
92 /// to push the output to the right.
93 Iterable<LinePrefix> split(
94 Chunk chunk, int blockIndentation, Map<Rule, int> ruleValues) {
95 var indent = chunk.indent + blockIndentation;
96 var flushLeft = chunk.flushLeft;
97
98 // If the chunk has a block, then its flushLeft property is for the first
99 // line of the block, not the line after the block. The line after the block
100 // is never flush left since it will always be for a `}` or `]`.
101 if (chunk.blockChunks.isNotEmpty) flushLeft = false;
102
103 return _nesting.update(chunk.nesting).map((nesting) => new LinePrefix._(
104 length + 1, ruleValues, indent, nesting,
105 flushLeft: flushLeft));
106 }
107
108 String toString() {
109 var result = "prefix $length";
110 if (_indent != 0) result += " indent ${_indent}";
111 if (_nesting.indent != 0) result += " nesting ${_nesting.indent}";
112 if (ruleValues.isNotEmpty) {
113 var rules =
114 ruleValues.keys.map((key) => "$key:${ruleValues[key]}").join(" ");
115
116 result += " rules $rules";
117 }
118 return result;
119 }
120 }
OLDNEW
« no previous file with comments | « lib/src/debug.dart ('k') | lib/src/line_splitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698