Index: lib/src/nesting.dart |
diff --git a/lib/src/nesting.dart b/lib/src/nesting.dart |
deleted file mode 100644 |
index 66b4b4fd24f2273e5536aebda8bf328c40955363..0000000000000000000000000000000000000000 |
--- a/lib/src/nesting.dart |
+++ /dev/null |
@@ -1,291 +0,0 @@ |
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library dart_style.src.nesting; |
- |
-/// A single level of expression nesting. |
-/// |
-/// When a line is split in the middle of an expression, this tracks the |
-/// context of where in the expression that split occurs. It ensures that the |
-/// [LineSplitter] obeys the expression nesting when deciding what column to |
-/// start lines at when split inside an expression. |
-/// |
-/// Each instance of this represents a single level of expression nesting. If we |
-/// split at to chunks with different levels of nesting, the splitter ensures |
-/// they each get assigned to different columns. |
-/// |
-/// In addition, each level has an indent. This is the number of spaces it is |
-/// indented relative to the outer expression. It's almost always |
-/// [Indent.expression], but cascades are special magic snowflakes and use |
-/// [Indent.cascade]. |
-class NestingLevel { |
- /// The nesting level surrounding this one, or `null` if this is represents |
- /// top level code in a block. |
- NestingLevel get parent => _parent; |
- NestingLevel _parent; |
- |
- /// The number of characters that this nesting level is indented relative to |
- /// the containing level. |
- /// |
- /// Normally, this is [Indent.expression], but cascades use [Indent.cascade]. |
- final int indent; |
- |
- /// The number of nesting levels surrounding this one. |
- int get depth { |
- var result = 0; |
- var nesting = this; |
- while (nesting != null) { |
- result++; |
- nesting = nesting.parent; |
- } |
- |
- return result - 1; |
- } |
- |
- NestingLevel() : indent = 0; |
- |
- NestingLevel._(this._parent, this.indent); |
- |
- /// Creates a new deeper level of nesting indented [spaces] more characters |
- /// that the outer level. |
- NestingLevel nest(int spaces) => new NestingLevel._(this, spaces); |
- |
- /// Gets the relative indentation of the nesting level at [depth]. |
- int indentAtDepth(int depth) { |
- // How many levels do we need to walk up to reach [depth]? |
- var levels = this.depth - depth; |
- assert(levels >= 0); |
- |
- var nesting = this; |
- for (var i = 0; i < levels; i++) { |
- nesting = nesting._parent; |
- } |
- |
- return nesting.indent; |
- } |
- |
- /// Discards this level's parent if it is not in [used] (or is not the top |
- /// level nesting). |
- void removeUnused(Set<NestingLevel> used) { |
- // Always keep the top level zero nesting. |
- if (_parent == null) return; |
- if (_parent._parent == null) return; |
- |
- // Unlink the unused parent from the chain. |
- if (!used.contains(_parent)) _parent = _parent._parent; |
- |
- // Walk up the whole chain. |
- _parent.removeUnused(used); |
- } |
- |
- String toString() => depth.toString(); |
-} |
- |
-/// Maintains a stack of nested expressions that have currently been split. |
-/// |
-/// A single statement may have multiple different levels of indentation based |
-/// on the expression nesting level at the point where the line is broken. For |
-/// example: |
-/// |
-/// someFunction(argument, argument, |
-/// innerFunction(argument, |
-/// innermost), argument); |
-/// |
-/// This means that when splitting a line, we need to keep track of the nesting |
-/// level of the previous line(s) to determine how far the next line must be |
-/// indented. |
-/// |
-/// This class is a persistent collection. Each instance is immutable and |
-/// methods to modify it return a new collection. |
-class NestingSplitter { |
- final NestingSplitter _parent; |
- |
- /// The number of characters of indentation for the current nesting. |
- int get indent => _indent; |
- final int _indent; |
- |
- /// The number of surrounding expression nesting levels. |
- int get depth => _depth; |
- final int _depth; |
- |
- NestingSplitter() : this._(null, 0, 0); |
- |
- NestingSplitter._(this._parent, this._depth, this._indent); |
- |
- /// LinePrefixes implement their own value equality to ensure that two |
- /// prefixes with the same nesting stack are considered equal even if the |
- /// nesting occurred from different splits. |
- /// |
- /// For example, consider these two prefixes with `^` marking where splits |
- /// have been applied: |
- /// |
- /// fn( first, second, ... |
- /// ^ |
- /// fn( first, second, ... |
- /// ^ |
- /// |
- /// These are equivalent from the view of the suffix because they have the |
- /// same nesting stack, even though the nesting came from different tokens. |
- /// This lets us reuse memoized suffixes more frequently when solving. |
- bool operator ==(other) { |
- if (other is! NestingSplitter) return false; |
- |
- var self = this; |
- while (self != null) { |
- if (self._indent != other._indent) return false; |
- if (self._depth != other._depth) return false; |
- self = self._parent; |
- other = other._parent; |
- |
- // They should be the same length. |
- if ((self == null) != (other == null)) return false; |
- } |
- |
- return true; |
- } |
- |
- int get hashCode { |
- // TODO(rnystrom): Is it worth iterating through the stack? |
- return _indent.hashCode ^ _depth.hashCode; |
- } |
- |
- /// Takes this nesting stack and produces all of the new nesting stacks that |
- /// are possible when followed by [nesting]. |
- /// |
- /// This may produce multiple solutions because a non-incremental jump in |
- /// nesting depth can be sliced up multiple ways. Let's say the prefix is: |
- /// |
- /// first(second(third(... |
- /// |
- /// The current nesting stack is empty (since we're on the first line). How |
- /// do we modify it by taking into account the split after `third(`? The |
- /// simple answer is to just increase the indentation by one level: |
- /// |
- /// first(second(third( |
- /// argumentToThird))); |
- /// |
- /// This is correct in most cases, but not all. Consider: |
- /// |
- /// first(second(third( |
- /// argumentToThird), |
- /// argumentToSecond)); |
- /// |
- /// Oops! There's no place for `argumentToSecond` to go. To handle that, the |
- /// second line needs to be indented one more level to make room for the later |
- /// line: |
- /// |
- /// first(second(third( |
- /// argumentToThird), |
- /// argumentToSecond)); |
- /// |
- /// It's even possible we may need to do: |
- /// |
- /// first(second(third( |
- /// argumentToThird), |
- /// argumentToSecond), |
- /// argumentToFirst); |
- /// |
- /// To accommodate those, this returns the list of all possible ways the |
- /// nesting stack can be modified. |
- List<NestingSplitter> update(NestingLevel nesting) { |
- if (nesting.depth == _depth) return [this]; |
- |
- // If the new split is less nested than we currently are, pop and discard |
- // the previous nesting levels. |
- if (nesting.depth < _depth) { |
- // Pop items off the stack until we find the level we are now at. |
- var stack = this; |
- while (stack != null) { |
- if (stack._depth == nesting.depth) return [stack]; |
- stack = stack._parent; |
- } |
- |
- // If we got here, the level wasn't found. That means there is no correct |
- // stack level to pop to, since the stack skips past our indentation |
- // level. |
- return []; |
- } |
- |
- // Going deeper, so try every indentation for every subset of expression |
- // nesting levels between the old and new one. |
- return _intermediateDepths(_depth, nesting.depth).map((depths) { |
- var result = this; |
- |
- for (var depth in depths) { |
- result = new NestingSplitter._( |
- result, depth, result._indent + nesting.indentAtDepth(depth)); |
- } |
- |
- return new NestingSplitter._( |
- result, nesting.depth, result._indent + nesting.indent); |
- }).toList(); |
- } |
- |
- /// Given [min] and [max], generates all of the subsets of numbers in that |
- /// range (exclusive), including the empty set. |
- /// |
- /// This is used to determine what sets of intermediate nesting levels to |
- /// consider when jumping from a shallow nesting level to a much deeper one. |
- /// Subsets are generated in order of increasing length. For example, `(2, 6)` |
- /// yields: |
- /// |
- /// [] |
- /// [3] [4] [5] |
- /// [3, 4] [3, 5] [4, 5] |
- /// [3, 4, 5] |
- /// |
- /// This ensures the splitter prefers solutions that use the least |
- /// indentation. |
- List<List<int>> _intermediateDepths(int min, int max) { |
- assert(min < max); |
- |
- var subsets = [[]]; |
- |
- var lastLengthStart = 0; |
- var lastLengthEnd = subsets.length; |
- |
- // Generate subsets in order of increasing length. |
- for (var length = 1; length <= max - min + 1; length++) { |
- // Start with each subset containing one fewer element. |
- for (var i = lastLengthStart; i < lastLengthEnd; i++) { |
- var previousSubset = subsets[i]; |
- |
- var start = |
- previousSubset.isNotEmpty ? previousSubset.last + 1 : min + 1; |
- |
- // Then for each value in the remainer, make a new subset that is the |
- // union of the shorter subset and that value. |
- for (var j = start; j < max; j++) { |
- var subset = previousSubset.toList()..add(j); |
- subsets.add(subset); |
- } |
- } |
- |
- // Move on to the next length range. |
- lastLengthStart = lastLengthEnd; |
- lastLengthEnd = subsets.length; |
- } |
- |
- return subsets; |
- } |
- |
- /// Shows each indentation level and the nesting depth associated with it. |
- /// |
- /// For example: |
- /// |
- /// |1|3 |
- /// |
- /// Means that the first level of indentation is associated with nesting |
- /// level one, and the second level of indentation is associated with nesting |
- /// level three. |
- String toString() { |
- var result = ""; |
- |
- for (var nesting = this; nesting._depth != 0; nesting = nesting._parent) { |
- result = "|${nesting._depth}$result"; |
- } |
- |
- return result; |
- } |
-} |