in lib/src/line_splitting/solve_state.dart [313:422]
void _calculateCost() {
// Calculate the length of each line and apply the cost of any spans that
// get split.
var cost = 0;
var length = _splitter.firstLineIndent;
// The unbound rules in use by the current line. This will be null after
// the first long line has completed.
var foundOverflowRules = false;
var start = 0;
void endLine(int end) {
// Track lines that went over the length. It is only rules contained in
// long lines that we may want to split.
if (length > _splitter.writer.pageWidth) {
_overflowChars += length - _splitter.writer.pageWidth;
// Only try rules that are in the first long line, since we know at
// least one of them *will* be split.
if (!foundOverflowRules) {
for (var i = start; i < end; i++) {
if (_addLiveRules(_splitter.chunks[i].rule)) {
foundOverflowRules = true;
}
}
}
}
start = end;
}
// The set of spans that contain chunks that ended up splitting. We store
// these in a set so a span's cost doesn't get double-counted if more than
// one split occurs in it.
var splitSpans = <Span>{};
// The nesting level of the chunk that ended the previous line.
NestingLevel? previousNesting;
for (var i = 0; i < _splitter.chunks.length; i++) {
var chunk = _splitter.chunks[i];
length += chunk.text.length;
// Ignore the split after the last chunk.
if (i == _splitter.chunks.length - 1) break;
if (_splits.shouldSplitAt(i)) {
endLine(i);
splitSpans.addAll(chunk.spans);
// Include the cost of the nested block.
if (chunk.isBlock) {
cost +=
_splitter.writer.formatBlock(chunk, _splits.getColumn(i)).cost;
}
// Do not allow sequential lines to have the same indentation but for
// different reasons. In other words, don't allow different expressions
// to claim the same nesting level on subsequent lines.
//
// A contrived example would be:
//
// function(inner(
// argument), second(
// another);
//
// For the most part, we prevent this by the constraints on splits.
// For example, the above can't happen because the split before
// "argument", forces the split before "second".
//
// But there are a couple of squirrely cases where it's hard to prevent
// by construction. Instead, this outlaws it by penalizing it very
// heavily if it happens to get this far.
var totalIndent = chunk.nesting!.totalUsedIndent;
if (previousNesting != null &&
totalIndent != 0 &&
totalIndent == previousNesting.totalUsedIndent &&
!identical(chunk.nesting, previousNesting)) {
_overflowChars += 10000;
}
previousNesting = chunk.nesting;
// Start the new line.
length = _splits.getColumn(i);
} else {
if (chunk.spaceWhenUnsplit) length++;
// Include the nested block inline, if any.
length += chunk.unsplitBlockLength;
}
}
// Add the costs for the rules that have any splits.
_ruleValues.forEach(_splitter.rules, (rule, value) {
if (value != Rule.unsplit) cost += rule.cost;
});
// Add the costs for the spans containing splits.
for (var span in splitSpans) {
cost += span.cost;
}
// Finish the last line.
endLine(_splitter.chunks.length);
_splits.setCost(cost);
}