Apply review feedback.
diff --git a/lib/src/argument_list_visitor.dart b/lib/src/argument_list_visitor.dart
index aa6d28a..a22864f 100644
--- a/lib/src/argument_list_visitor.dart
+++ b/lib/src/argument_list_visitor.dart
@@ -172,7 +172,10 @@
this._allArguments,
this._arguments,
this._functions,
- this._argumentsAfterFunctions);
+ this._argumentsAfterFunctions) {
+ assert(_functions == null || _argumentsAfterFunctions != null,
+ 'If _functions is passed, _argumentsAfterFunctions must be too.');
+ }
/// Builds chunks for the argument list.
void visit() {
@@ -187,20 +190,21 @@
_visitor.builder.endSpan();
- if (_functions != null) {
+ var functions = _functions;
+ if (functions != null) {
// TODO(rnystrom): It might look better to treat the parameter list of the
// first function as if it were an argument in the preceding argument list
// instead of just having this little solo split here. That would try to
// keep the parameter list with other arguments when possible, and, I
// think, generally look nicer.
- if (_functions!.first == _allArguments.first) {
+ if (functions.first == _allArguments.first) {
_visitor.soloZeroSplit();
} else {
_visitor.soloSplit();
}
- for (var argument in _functions!) {
- if (argument != _functions!.first) _visitor.space();
+ for (var argument in functions) {
+ if (argument != functions.first) _visitor.space();
_visitor.visit(argument);
@@ -437,11 +441,12 @@
void _visitArgument(
SourceVisitor visitor, ArgumentRule rule, Expression argument) {
// If we're about to write a block argument, handle it specially.
- if (_blocks.containsKey(argument)) {
+ var argumentBlock = _blocks[argument];
+ if (argumentBlock != null) {
rule.disableSplitOnInnerRules();
// Tell it to use the rule we've already created.
- visitor.beforeBlock(_blocks[argument]!, blockRule!, previousSplit);
+ visitor.beforeBlock(argumentBlock, blockRule!, previousSplit);
} else if (_allArguments.length > 1) {
// Edge case: Only bump the nesting if there are multiple arguments. This
// lets us avoid spurious indentation in cases like:
@@ -465,7 +470,7 @@
visitor.visit(argument);
}
- if (_blocks.containsKey(argument)) {
+ if (argumentBlock != null) {
rule.enableSplitOnInnerRules();
} else if (_allArguments.length > 1) {
visitor.builder.endBlockArgumentNesting();
diff --git a/lib/src/call_chain_visitor.dart b/lib/src/call_chain_visitor.dart
index df6bd9b..5af43f7 100644
--- a/lib/src/call_chain_visitor.dart
+++ b/lib/src/call_chain_visitor.dart
@@ -242,12 +242,13 @@
// If there are block calls, end the chain and write those without any
// extra indentation.
- if (_blockCalls != null) {
+ var blockCalls = _blockCalls;
+ if (blockCalls != null) {
_enableRule();
_visitor.zeroSplit();
_disableRule();
- for (var blockCall in _blockCalls!) {
+ for (var blockCall in blockCalls) {
blockCall.write(this);
}
diff --git a/lib/src/chunk.dart b/lib/src/chunk.dart
index aad9eb1..02dbfb6 100644
--- a/lib/src/chunk.dart
+++ b/lib/src/chunk.dart
@@ -87,8 +87,8 @@
/// someFunctionName(argument, argument,
/// argument, anotherFunction(argument,
/// argument));
- NestingLevel? get nesting => _nesting;
- NestingLevel? _nesting;
+ NestingLevel get nesting => _nesting;
+ late NestingLevel _nesting;
/// If this chunk marks the beginning of a block, this contains the child
/// chunks and other data about that nested block.
@@ -251,14 +251,15 @@
if (_isDouble == true) parts.add('double');
if (_flushLeft == true) parts.add('flush');
- if (_rule == null) {
+ var rule = _rule;
+ if (rule == null) {
parts.add('(no split)');
} else {
- parts.add(rule!.toString());
- if (rule!.isHardened) parts.add('(hard)');
+ parts.add(rule.toString());
+ if (rule.isHardened) parts.add('(hard)');
- if (rule!.constrainedRules.isNotEmpty) {
- parts.add("-> ${rule!.constrainedRules.join(' ')}");
+ if (rule.constrainedRules.isNotEmpty) {
+ parts.add("-> ${rule.constrainedRules.join(' ')}");
}
}
diff --git a/lib/src/chunk_builder.dart b/lib/src/chunk_builder.dart
index e8b5505..a17c89a 100644
--- a/lib/src/chunk_builder.dart
+++ b/lib/src/chunk_builder.dart
@@ -884,7 +884,7 @@
var chunk = _chunks[i];
if (!chunk.rule!.isHardened) return false;
- if (chunk.nesting!.isNested) return false;
+ if (chunk.nesting.isNested) return false;
if (chunk.isBlock) return false;
return true;
diff --git a/lib/src/debug.dart b/lib/src/debug.dart
index f796af3..5934afd 100644
--- a/lib/src/debug.dart
+++ b/lib/src/debug.dart
@@ -146,7 +146,7 @@
writeIf(chunk.indent != null && chunk.indent != 0,
() => 'indent ${chunk.indent}');
- writeIf(chunk.nesting?.indent != 0, () => 'nest ${chunk.nesting}');
+ writeIf(chunk.nesting.indent != 0, () => 'nest ${chunk.nesting}');
writeIf(chunk.flushLeft, () => 'flush');
diff --git a/lib/src/io.dart b/lib/src/io.dart
index 960236e..c0064b4 100644
--- a/lib/src/io.dart
+++ b/lib/src/io.dart
@@ -14,7 +14,7 @@
import 'exceptions.dart';
import 'source_code.dart';
-/// Reads input from stdin until it's closed, and the formats it.
+/// Reads and formats input from stdin until closed.
void formatStdin(FormatterOptions options, List<int>? selection, String name) {
var selectionStart = 0;
var selectionLength = 0;
diff --git a/lib/src/line_splitting/line_splitter.dart b/lib/src/line_splitting/line_splitter.dart
index 3c0d90d..8ef5926 100644
--- a/lib/src/line_splitting/line_splitter.dart
+++ b/lib/src/line_splitting/line_splitter.dart
@@ -118,9 +118,6 @@
/// and can stop looking.
final _queue = SolveStateQueue();
- /// The lowest cost solution found so far.
- SolveState? _bestSolution;
-
/// Creates a new splitter for [_writer] that tries to fit [chunks] into the
/// page width.
LineSplitter(this.writer, List<Chunk> chunks, int blockIndentation,
@@ -162,20 +159,22 @@
// Start with a completely unbound, unsplit solution.
_queue.add(SolveState(this, RuleSet(rules.length)));
+ SolveState? bestSolution;
+
var attempts = 0;
while (_queue.isNotEmpty) {
var state = _queue.removeFirst();
- if (state.isBetterThan(_bestSolution)) {
- _bestSolution = state;
+ if (state.isBetterThan(bestSolution)) {
+ bestSolution = state;
// Since we sort solutions by cost the first solution we find that
// fits is the winner.
- if (_bestSolution!.overflowChars == 0) break;
+ if (bestSolution.overflowChars == 0) break;
}
if (debug.traceSplitter) {
- var best = state == _bestSolution ? ' (best)' : '';
+ var best = state == bestSolution ? ' (best)' : '';
debug.log('$state$best');
debug.dumpLines(chunks, firstLineIndent, state.splits);
debug.log();
@@ -188,12 +187,12 @@
}
if (debug.traceSplitter) {
- debug.log('$_bestSolution (winner)');
- debug.dumpLines(chunks, firstLineIndent, _bestSolution!.splits);
+ debug.log('$bestSolution (winner)');
+ debug.dumpLines(chunks, firstLineIndent, bestSolution!.splits);
debug.log();
}
- return _bestSolution!.splits;
+ return bestSolution!.splits;
}
void enqueue(SolveState state) {
diff --git a/lib/src/line_splitting/solve_state.dart b/lib/src/line_splitting/solve_state.dart
index 47ec632..708353e 100644
--- a/lib/src/line_splitting/solve_state.dart
+++ b/lib/src/line_splitting/solve_state.dart
@@ -83,7 +83,7 @@
/// The constraints the bound rules in this state have on the remaining
/// unbound rules.
- Map<Rule, int>? _constraints;
+ late final Map<Rule, int> _constraints = _initConstraints();
/// The unbound rule values that are disallowed because they would place
/// invalid constraints on the currently bound values.
@@ -96,14 +96,16 @@
///
/// It's important to track this, because we can't allow to states to overlap
/// if one permits more values for some unbound rule than the other does.
- Map<Rule, Set<int>>? _unboundConstraints;
+ late final Map<Rule, Set<int>> _unboundConstraints =
+ _initUnboundConstraints();
/// The bound rules that appear inside lines also containing unbound rules.
///
/// By appearing in the same line, it means these bound rules may affect the
/// results of binding those unbound rules. This is used to tell if two
/// states may diverge by binding unbound rules or not.
- Set<Rule>? _boundRulesInUnboundLines;
+ late final Set<Rule> _boundRulesInUnboundLines =
+ _initBoundRulesInUnboundLines();
SolveState(this._splitter, this._ruleValues) {
_calculateSplits();
@@ -233,38 +235,31 @@
bool _isOverlapping(SolveState other) {
// Lines that contain both bound and unbound rules must have the same
// bound values.
- var boundRulesInUnboundLines = _ensureBoundRulesInUnboundLines();
- var otherBoundRulesInUnboundLines = other._ensureBoundRulesInUnboundLines();
-
- if (boundRulesInUnboundLines.length !=
- otherBoundRulesInUnboundLines.length) {
+ if (_boundRulesInUnboundLines.length !=
+ other._boundRulesInUnboundLines.length) {
return false;
}
- for (var rule in boundRulesInUnboundLines) {
- if (!otherBoundRulesInUnboundLines.contains(rule)) return false;
+ for (var rule in _boundRulesInUnboundLines) {
+ if (!other._boundRulesInUnboundLines.contains(rule)) return false;
if (_ruleValues.getValue(rule) != other._ruleValues.getValue(rule)) {
return false;
}
}
- var constraints = _ensureConstraints();
- var otherConstraints = other._ensureConstraints();
- if (constraints.length != otherConstraints.length) return false;
+ if (_constraints.length != other._constraints.length) return false;
- for (var rule in constraints.keys) {
- if (constraints[rule] != otherConstraints[rule]) return false;
+ for (var rule in _constraints.keys) {
+ if (_constraints[rule] != other._constraints[rule]) return false;
}
- var unboundConstraints = _ensureUnboundConstraints();
- var otherUnboundConstraints = other._ensureUnboundConstraints();
- if (unboundConstraints.length != otherUnboundConstraints.length) {
+ if (_unboundConstraints.length != other._unboundConstraints.length) {
return false;
}
- for (var rule in unboundConstraints.keys) {
- var disallowed = unboundConstraints[rule]!;
- var otherDisallowed = otherUnboundConstraints[rule]!;
+ for (var rule in _unboundConstraints.keys) {
+ var disallowed = _unboundConstraints[rule]!;
+ var otherDisallowed = other._unboundConstraints[rule]!;
if (disallowed.length != otherDisallowed.length) return false;
for (var value in disallowed) {
@@ -284,8 +279,8 @@
for (var i = 0; i < _splitter.chunks.length - 1; i++) {
var chunk = _splitter.chunks[i];
if (chunk.rule!.isSplit(getValue(chunk.rule!), chunk)) {
- usedNestingLevels.add(chunk.nesting!);
- chunk.nesting!.clearTotalUsedIndent();
+ usedNestingLevels.add(chunk.nesting);
+ chunk.nesting.clearTotalUsedIndent();
}
}
@@ -303,7 +298,7 @@
indent = _splitter.blockIndentation + chunk.indent!;
// And any expression nesting.
- indent += chunk.nesting!.totalUsedIndent;
+ indent += chunk.nesting.totalUsedIndent;
if (chunk.indentBlock(getValue)) indent += Indent.expression;
}
@@ -391,8 +386,8 @@
// by construction. Instead, this outlaws it by penalizing it very
// heavily if it happens to get this far.
if (previousNesting != null &&
- chunk.nesting!.totalUsedIndent != 0 &&
- chunk.nesting!.totalUsedIndent == previousNesting.totalUsedIndent &&
+ chunk.nesting.totalUsedIndent != 0 &&
+ chunk.nesting.totalUsedIndent == previousNesting.totalUsedIndent &&
!identical(chunk.nesting, previousNesting)) {
_overflowChars += 10000;
}
@@ -443,16 +438,13 @@
return added;
}
- /// Lazily initializes the [_boundInUnboundLines], which is needed to compare
+ /// Used to lazy initialize [_boundInUnboundLines], which is needed to compare
/// two states for overlap.
///
/// We do this lazily because the calculation is a bit slow, and is only
/// needed when we have two states with the same score.
- Set<Rule> _ensureBoundRulesInUnboundLines() {
- var rules = _boundRulesInUnboundLines;
- if (rules != null) return rules;
-
- rules = <Rule>{};
+ Set<Rule> _initBoundRulesInUnboundLines() {
+ var rules = <Rule>{};
var boundInLine = <Rule>{};
var hasUnbound = false;
@@ -475,19 +467,15 @@
}
if (hasUnbound) rules.addAll(boundInLine);
- _boundRulesInUnboundLines = rules;
return rules;
}
- /// Lazily initializes the [_constraints], which is needed to compare two
- /// states for overlap.
+ /// Used to lazy initializes the [_constraints], which is needed to compare
+ /// two states for overlap.
///
/// We do this lazily because the calculation is a bit slow, and is only
/// needed when we have two states with the same score.
- Map<Rule, int> _ensureConstraints() {
- var constraints = _constraints;
- if (constraints != null) return constraints;
-
+ Map<Rule, int> _initConstraints() {
_unboundRules = <Rule>{};
_boundRules = <Rule>{};
@@ -499,7 +487,7 @@
}
}
- constraints = <Rule, int>{};
+ var constraints = <Rule, int>{};
for (var bound in _boundRules) {
for (var unbound in bound.constrainedRules) {
@@ -513,24 +501,19 @@
}
}
- _constraints = constraints;
return constraints;
}
- /// Lazily initializes the [_unboundConstraints], which is needed to compare
- /// two states for overlap.
+ /// Used to lazy initialize the [_unboundConstraints], which is needed to
+ /// compare two states for overlap.
///
/// We do this lazily because the calculation is a bit slow, and is only
/// needed when we have two states with the same score.
- ///
- /// [_ensureConstraints()] should be called first.
- Map<Rule, Set<int>> _ensureUnboundConstraints() {
- var unboundConstraints = _unboundConstraints;
- if (unboundConstraints != null) return unboundConstraints;
-
- unboundConstraints = <Rule, Set<int>>{};
+ Map<Rule, Set<int>> _initUnboundConstraints() {
+ var unboundConstraints = <Rule, Set<int>>{};
for (var unbound in _unboundRules) {
- Set<int>? disallowedValues;
+ // Lazily create and add the set to the constraints only if needed.
+ late final disallowedValues = unboundConstraints[unbound] = {};
for (var bound in unbound.constrainedRules) {
if (!_boundRules.contains(bound)) continue;
@@ -553,17 +536,11 @@
continue;
}
- if (disallowedValues == null) {
- disallowedValues = <int>{};
- unboundConstraints[unbound] = disallowedValues;
- }
-
disallowedValues.add(value);
}
}
}
- _unboundConstraints = unboundConstraints;
return unboundConstraints;
}