Index: packages/dart_style/lib/src/chunk.dart |
diff --git a/packages/dart_style/lib/src/chunk.dart b/packages/dart_style/lib/src/chunk.dart |
index e92a85b115c506d7d752aedd2cb726c40a21db3a..da6d7bbc011ac9e7d82055ec4d43b76b66c48b52 100644 |
--- a/packages/dart_style/lib/src/chunk.dart |
+++ b/packages/dart_style/lib/src/chunk.dart |
@@ -92,9 +92,13 @@ class Chunk extends Selection { |
NestingLevel get nesting => _nesting; |
NestingLevel _nesting; |
- /// If this chunk marks the beginning of a block, these are the chunks |
- /// contained in the block. |
- final blockChunks = <Chunk>[]; |
+ /// If this chunk marks the beginning of a block, this contains the child |
+ /// chunks and other data about that nested block. |
+ ChunkBlock get block => _block; |
+ ChunkBlock _block; |
+ |
+ /// Whether this chunk has a [block]. |
+ bool get isBlock => _block != null; |
/// Whether it's valid to add more text to this chunk or not. |
/// |
@@ -110,10 +114,6 @@ class Chunk extends Selection { |
Rule get rule => _rule; |
Rule _rule; |
- /// Whether this chunk is always followed by a newline or whether the line |
- /// splitter may choose to keep the next chunk on the same line. |
- bool get isHardSplit => _rule is HardSplitRule; |
- |
/// Whether or not an extra blank line should be output after this chunk if |
/// it's split. |
/// |
@@ -136,9 +136,9 @@ class Chunk extends Selection { |
/// If `true`, then the line after this chunk and its contained block should |
/// be flush left. |
bool get flushLeftAfter { |
- if (blockChunks.isEmpty) return _flushLeft; |
+ if (!isBlock) return _flushLeft; |
- return blockChunks.last.flushLeftAfter; |
+ return _block.chunks.last.flushLeftAfter; |
} |
/// Whether this chunk should append an extra space if it does not split. |
@@ -165,8 +165,10 @@ class Chunk extends Selection { |
/// Does not include this chunk's own length, just the length of its child |
/// block chunks (recursively). |
int get unsplitBlockLength { |
+ if (_block == null) return 0; |
+ |
var length = 0; |
- for (var chunk in blockChunks) { |
+ for (var chunk in _block.chunks) { |
length += chunk.length + chunk.unsplitBlockLength; |
} |
@@ -191,15 +193,6 @@ class Chunk extends Selection { |
_text += text; |
} |
- /// Forces this soft split to become a hard split. |
- /// |
- /// This is called on the soft splits owned by a rule that decides to harden |
- /// when it finds out another hard split occurs within its chunks. |
- void harden() { |
- _rule = new HardSplitRule(); |
- spans.clear(); |
- } |
- |
/// Finishes off this chunk with the given [rule] and split information. |
/// |
/// This may be called multiple times on the same split since the splits |
@@ -207,10 +200,10 @@ class Chunk extends Selection { |
/// preserved whitespace often overlap. When that happens, this has logic to |
/// combine that information into a single split. |
void applySplit(Rule rule, int indent, NestingLevel nesting, |
- {bool flushLeft, bool spaceWhenUnsplit, bool isDouble}) { |
+ {bool flushLeft, bool isDouble, bool space}) { |
if (flushLeft == null) flushLeft = false; |
- if (spaceWhenUnsplit == null) spaceWhenUnsplit = false; |
- if (isHardSplit || rule is HardSplitRule) { |
+ if (space == null) space = false; |
+ if (rule.isHardened) { |
// A hard split always wins. |
_rule = rule; |
} else if (_rule == null) { |
@@ -223,12 +216,28 @@ class Chunk extends Selection { |
_nesting = nesting; |
_indent = indent; |
- _spaceWhenUnsplit = spaceWhenUnsplit; |
+ _spaceWhenUnsplit = space; |
// Pin down the double state, if given and we haven't already. |
if (_isDouble == null) _isDouble = isDouble; |
} |
+ /// Turns this chunk into one that can contain a block of child chunks. |
+ void makeBlock(Chunk blockArgument) { |
+ assert(_block == null); |
+ _block = new ChunkBlock(blockArgument); |
+ } |
+ |
+ /// Returns `true` if the block body owned by this chunk should be expression |
+ /// indented given a set of rule values provided by [getValue]. |
+ bool indentBlock(int getValue(Rule rule)) { |
+ if (_block == null) return false; |
+ if (_block.argument == null) return false; |
+ |
+ return _block.argument.rule |
+ .isSplit(getValue(_block.argument.rule), _block.argument); |
+ } |
+ |
// Mark whether this chunk can divide the range of chunks. |
void markDivide(canDivide) { |
// Should only do this once. |
@@ -243,19 +252,18 @@ class Chunk extends Selection { |
if (text.isNotEmpty) parts.add(text); |
if (_indent != null) parts.add("indent:$_indent"); |
- if (spaceWhenUnsplit) parts.add("space"); |
- if (_isDouble) parts.add("double"); |
- if (_flushLeft) parts.add("flush"); |
+ if (spaceWhenUnsplit == true) parts.add("space"); |
+ if (_isDouble == true) parts.add("double"); |
+ if (_flushLeft == true) parts.add("flush"); |
if (_rule == null) { |
parts.add("(no split)"); |
- } else if (isHardSplit) { |
- parts.add("hard"); |
} else { |
parts.add(rule.toString()); |
+ if (rule.isHardened) parts.add("(hard)"); |
- if (_rule.outerRules.isNotEmpty) { |
- parts.add("-> ${_rule.outerRules.join(' ')}"); |
+ if (_rule.constrainedRules.isNotEmpty) { |
+ parts.add("-> ${_rule.constrainedRules.join(' ')}"); |
} |
} |
@@ -263,6 +271,22 @@ class Chunk extends Selection { |
} |
} |
+/// The child chunks owned by a chunk that begins a "block" -- an actual block |
+/// statement, function expression, or collection literal. |
+class ChunkBlock { |
+ /// If this block is for a collection literal in an argument list, this will |
+ /// be the chunk preceding this literal argument. |
+ /// |
+ /// That chunk is owned by the argument list and if it splits, this collection |
+ /// may need extra expression-level indentation. |
+ final Chunk argument; |
+ |
+ /// The child chunks in this block. |
+ final List<Chunk> chunks = []; |
+ |
+ ChunkBlock(this.argument); |
+} |
+ |
/// Constants for the cost heuristics used to determine which set of splits is |
/// most desirable. |
class Cost { |
@@ -280,8 +304,11 @@ class Cost { |
/// number of nested spans. |
static const normal = 1; |
- /// Splitting after a "=" both for assignment and initialization. |
- static const assignment = 2; |
+ /// Splitting after a "=". |
+ static const assign = 1; |
+ |
+ /// Splitting after a "=" when the right-hand side is a collection or cascade. |
+ static const assignBlock = 2; |
/// Splitting before the first argument when it happens to be a function |
/// expression with a block body. |
@@ -299,6 +326,9 @@ class Cost { |
/// collection contents. |
static const splitCollections = 2; |
+ /// Splitting on the "." in a named constructor. |
+ static const constructorName = 3; |
+ |
/// Splitting before a type argument or type parameter. |
static const typeArgument = 4; |
} |