| Index: dart_style/lib/src/chunk.dart
|
| diff --git a/dart_style/lib/src/chunk.dart b/dart_style/lib/src/chunk.dart
|
| deleted file mode 100644
|
| index e92a85b115c506d7d752aedd2cb726c40a21db3a..0000000000000000000000000000000000000000
|
| --- a/dart_style/lib/src/chunk.dart
|
| +++ /dev/null
|
| @@ -1,368 +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.chunk;
|
| -
|
| -import 'fast_hash.dart';
|
| -import 'nesting_level.dart';
|
| -import 'rule/rule.dart';
|
| -
|
| -/// Tracks where a selection start or end point may appear in some piece of
|
| -/// text.
|
| -abstract class Selection {
|
| - /// The chunk of text.
|
| - String get text;
|
| -
|
| - /// The offset from the beginning of [text] where the selection starts, or
|
| - /// `null` if the selection does not start within this chunk.
|
| - int get selectionStart => _selectionStart;
|
| - int _selectionStart;
|
| -
|
| - /// The offset from the beginning of [text] where the selection ends, or
|
| - /// `null` if the selection does not start within this chunk.
|
| - int get selectionEnd => _selectionEnd;
|
| - int _selectionEnd;
|
| -
|
| - /// Sets [selectionStart] to be [start] characters into [text].
|
| - void startSelection(int start) {
|
| - _selectionStart = start;
|
| - }
|
| -
|
| - /// Sets [selectionStart] to be [fromEnd] characters from the end of [text].
|
| - void startSelectionFromEnd(int fromEnd) {
|
| - _selectionStart = text.length - fromEnd;
|
| - }
|
| -
|
| - /// Sets [selectionEnd] to be [end] characters into [text].
|
| - void endSelection(int end) {
|
| - _selectionEnd = end;
|
| - }
|
| -
|
| - /// Sets [selectionEnd] to be [fromEnd] characters from the end of [text].
|
| - void endSelectionFromEnd(int fromEnd) {
|
| - _selectionEnd = text.length - fromEnd;
|
| - }
|
| -}
|
| -
|
| -/// A chunk of non-breaking output text terminated by a hard or soft newline.
|
| -///
|
| -/// Chunks are created by [LineWriter] and fed into [LineSplitter]. Each
|
| -/// contains some text, along with the data needed to tell how the next line
|
| -/// should be formatted and how desireable it is to split after the chunk.
|
| -///
|
| -/// Line splitting after chunks comes in a few different forms.
|
| -///
|
| -/// * A "hard" split is a mandatory newline. The formatted output will contain
|
| -/// at least one newline after the chunk's text.
|
| -/// * A "soft" split is a discretionary newline. If a line doesn't fit within
|
| -/// the page width, one or more soft splits may be turned into newlines to
|
| -/// wrap the line to fit within the bounds. If a soft split is not turned
|
| -/// into a newline, it may instead appear as a space or zero-length string
|
| -/// in the output, depending on [spaceWhenUnsplit].
|
| -/// * A "double" split expands to two newlines. In other words, it leaves a
|
| -/// blank line in the output. Hard or soft splits may be doubled. This is
|
| -/// determined by [isDouble].
|
| -///
|
| -/// A split controls the leading spacing of the subsequent line, both
|
| -/// block-based [indent] and expression-wrapping-based [nesting].
|
| -class Chunk extends Selection {
|
| - /// The literal text output for the chunk.
|
| - String get text => _text;
|
| - String _text;
|
| -
|
| - /// The number of characters of indentation from the left edge of the block
|
| - /// that contains this chunk.
|
| - ///
|
| - /// For top level chunks that are not inside any block, this also includes
|
| - /// leading indentation.
|
| - int get indent => _indent;
|
| - int _indent;
|
| -
|
| - /// The expression nesting level following this chunk.
|
| - ///
|
| - /// This is used to determine how much to increase the indentation when a
|
| - /// line starts after this chunk. A single statement may be indented multiple
|
| - /// times if the splits occur in more deeply nested expressions, for example:
|
| - ///
|
| - /// // 40 columns |
|
| - /// someFunctionName(argument, argument,
|
| - /// argument, anotherFunction(argument,
|
| - /// argument));
|
| - 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>[];
|
| -
|
| - /// Whether it's valid to add more text to this chunk or not.
|
| - ///
|
| - /// Chunks are built up by adding text and then "capped off" by having their
|
| - /// split information set by calling [handleSplit]. Once the latter has been
|
| - /// called, no more text should be added to the chunk since it would appear
|
| - /// *before* the split.
|
| - bool get canAddText => _rule == null;
|
| -
|
| - /// The [Rule] that controls when a split should occur after this chunk.
|
| - ///
|
| - /// Multiple splits may share a [Rule].
|
| - 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.
|
| - ///
|
| - /// Internally, this can be either `true`, `false`, or `null`. The latter is
|
| - /// an indeterminate state that lets later modifications to the split decide
|
| - /// whether it should be double or not.
|
| - ///
|
| - /// However, this getter does not expose that. It will return `false` if the
|
| - /// chunk is still indeterminate.
|
| - bool get isDouble => _isDouble != null ? _isDouble : false;
|
| - bool _isDouble;
|
| -
|
| - /// If `true`, then the line after this chunk should always be at column
|
| - /// zero regardless of any indentation or expression nesting.
|
| - ///
|
| - /// Used for multi-line strings and commented out code.
|
| - bool get flushLeft => _flushLeft;
|
| - bool _flushLeft = false;
|
| -
|
| - /// If `true`, then the line after this chunk and its contained block should
|
| - /// be flush left.
|
| - bool get flushLeftAfter {
|
| - if (blockChunks.isEmpty) return _flushLeft;
|
| -
|
| - return blockChunks.last.flushLeftAfter;
|
| - }
|
| -
|
| - /// Whether this chunk should append an extra space if it does not split.
|
| - ///
|
| - /// This is `true`, for example, in a chunk that ends with a ",".
|
| - bool get spaceWhenUnsplit => _spaceWhenUnsplit;
|
| - bool _spaceWhenUnsplit = false;
|
| -
|
| - /// Whether this chunk marks the end of a range of chunks that can be line
|
| - /// split independently of the following chunks.
|
| - bool get canDivide {
|
| - // Have to call markDivide() before accessing this.
|
| - assert(_canDivide != null);
|
| - return _canDivide;
|
| - }
|
| -
|
| - bool _canDivide;
|
| -
|
| - /// The number of characters in this chunk when unsplit.
|
| - int get length => _text.length + (spaceWhenUnsplit ? 1 : 0);
|
| -
|
| - /// The unsplit length of all of this chunk's block contents.
|
| - ///
|
| - /// Does not include this chunk's own length, just the length of its child
|
| - /// block chunks (recursively).
|
| - int get unsplitBlockLength {
|
| - var length = 0;
|
| - for (var chunk in blockChunks) {
|
| - length += chunk.length + chunk.unsplitBlockLength;
|
| - }
|
| -
|
| - return length;
|
| - }
|
| -
|
| - /// The [Span]s that contain this chunk.
|
| - final spans = <Span>[];
|
| -
|
| - /// Creates a new chunk starting with [_text].
|
| - Chunk(this._text);
|
| -
|
| - /// Discard the split for the chunk and put it back into the state where more
|
| - /// text can be appended.
|
| - void allowText() {
|
| - _rule = null;
|
| - }
|
| -
|
| - /// Append [text] to the end of the split's text.
|
| - void appendText(String text) {
|
| - assert(canAddText);
|
| - _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
|
| - /// produced by walking the source and the splits coming from comments and
|
| - /// 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}) {
|
| - if (flushLeft == null) flushLeft = false;
|
| - if (spaceWhenUnsplit == null) spaceWhenUnsplit = false;
|
| - if (isHardSplit || rule is HardSplitRule) {
|
| - // A hard split always wins.
|
| - _rule = rule;
|
| - } else if (_rule == null) {
|
| - // If the chunk hasn't been initialized yet, just inherit the rule.
|
| - _rule = rule;
|
| - }
|
| -
|
| - // Last split settings win.
|
| - _flushLeft = flushLeft;
|
| - _nesting = nesting;
|
| - _indent = indent;
|
| -
|
| - _spaceWhenUnsplit = spaceWhenUnsplit;
|
| -
|
| - // Pin down the double state, if given and we haven't already.
|
| - if (_isDouble == null) _isDouble = isDouble;
|
| - }
|
| -
|
| - // Mark whether this chunk can divide the range of chunks.
|
| - void markDivide(canDivide) {
|
| - // Should only do this once.
|
| - assert(_canDivide == null);
|
| -
|
| - _canDivide = canDivide;
|
| - }
|
| -
|
| - String toString() {
|
| - var parts = [];
|
| -
|
| - 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 (_rule == null) {
|
| - parts.add("(no split)");
|
| - } else if (isHardSplit) {
|
| - parts.add("hard");
|
| - } else {
|
| - parts.add(rule.toString());
|
| -
|
| - if (_rule.outerRules.isNotEmpty) {
|
| - parts.add("-> ${_rule.outerRules.join(' ')}");
|
| - }
|
| - }
|
| -
|
| - return parts.join(" ");
|
| - }
|
| -}
|
| -
|
| -/// Constants for the cost heuristics used to determine which set of splits is
|
| -/// most desirable.
|
| -class Cost {
|
| - /// The cost of splitting after the `=>` in a lambda or arrow-bodied member.
|
| - ///
|
| - /// We make this zero because there is already a span around the entire body
|
| - /// and we generally do prefer splitting after the `=>` over other places.
|
| - static const arrow = 0;
|
| -
|
| - /// The default cost.
|
| - ///
|
| - /// This isn't zero because we want to ensure all splitting has *some* cost,
|
| - /// otherwise, the formatter won't try to keep things on one line at all.
|
| - /// Most splits and spans use this. Greater costs tend to come from a greater
|
| - /// number of nested spans.
|
| - static const normal = 1;
|
| -
|
| - /// Splitting after a "=" both for assignment and initialization.
|
| - static const assignment = 2;
|
| -
|
| - /// Splitting before the first argument when it happens to be a function
|
| - /// expression with a block body.
|
| - static const firstBlockArgument = 2;
|
| -
|
| - /// The series of positional arguments.
|
| - static const positionalArguments = 2;
|
| -
|
| - /// Splitting inside the brackets of a list with only one element.
|
| - static const singleElementList = 2;
|
| -
|
| - /// Splitting the internals of collection literal arguments.
|
| - ///
|
| - /// Used to prefer splitting at the argument boundary over splitting the
|
| - /// collection contents.
|
| - static const splitCollections = 2;
|
| -
|
| - /// Splitting before a type argument or type parameter.
|
| - static const typeArgument = 4;
|
| -}
|
| -
|
| -/// The in-progress state for a [Span] that has been started but has not yet
|
| -/// been completed.
|
| -class OpenSpan {
|
| - /// Index of the first chunk contained in this span.
|
| - int get start => _start;
|
| - int _start;
|
| -
|
| - /// The cost applied when the span is split across multiple lines or `null`
|
| - /// if the span is for a multisplit.
|
| - final int cost;
|
| -
|
| - OpenSpan(this._start, this.cost);
|
| -
|
| - String toString() => "OpenSpan($start, \$$cost)";
|
| -}
|
| -
|
| -/// Delimits a range of chunks that must end up on the same line to avoid an
|
| -/// additional cost.
|
| -///
|
| -/// These are used to encourage the line splitter to try to keep things
|
| -/// together, like parameter lists and binary operator expressions.
|
| -///
|
| -/// This is a wrapper around the cost so that spans have unique identities.
|
| -/// This way we can correctly avoid paying the cost multiple times if the same
|
| -/// span is split by multiple chunks.
|
| -class Span extends FastHash {
|
| - /// The cost applied when the span is split across multiple lines or `null`
|
| - /// if the span is for a multisplit.
|
| - final int cost;
|
| -
|
| - Span(this.cost);
|
| -
|
| - String toString() => "$id\$$cost";
|
| -}
|
| -
|
| -/// A comment in the source, with a bit of information about the surrounding
|
| -/// whitespace.
|
| -class SourceComment extends Selection {
|
| - /// The text of the comment, including `//`, `/*`, and `*/`.
|
| - final String text;
|
| -
|
| - /// The number of newlines between the comment or token preceding this comment
|
| - /// and the beginning of this one.
|
| - ///
|
| - /// Will be zero if the comment is a trailing one.
|
| - int linesBefore;
|
| -
|
| - /// Whether this comment is a line comment.
|
| - final bool isLineComment;
|
| -
|
| - /// Whether this comment starts at column one in the source.
|
| - ///
|
| - /// Comments that start at the start of the line will not be indented in the
|
| - /// output. This way, commented out chunks of code do not get erroneously
|
| - /// re-indented.
|
| - final bool flushLeft;
|
| -
|
| - /// Whether this comment is an inline block comment.
|
| - bool get isInline => linesBefore == 0 && !isLineComment;
|
| -
|
| - SourceComment(this.text, this.linesBefore,
|
| - {this.isLineComment, this.flushLeft});
|
| -}
|
|
|