Clean up _writeWithIndent() (#216)

This improves formatting and fixes a case where it crashed on trailing
whitespace.
This commit is contained in:
Natalie Weizenbaum 2018-01-20 13:18:14 -08:00 committed by GitHub
parent da2ff6a06d
commit 67494e2b2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -132,6 +132,7 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
void visitComment(CssComment node) { void visitComment(CssComment node) {
var minimumIndentation = _minimumIndentation(node.text); var minimumIndentation = _minimumIndentation(node.text);
assert(minimumIndentation != -1);
if (minimumIndentation == null) { if (minimumIndentation == null) {
_writeIndentation(); _writeIndentation();
_buffer.write(node.text); _buffer.write(node.text);
@ -261,6 +262,10 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
if (minimumIndentation == null) { if (minimumIndentation == null) {
_buffer.write(value); _buffer.write(value);
return; return;
} else if (minimumIndentation == -1) {
_buffer.write(value.trimRight());
_buffer.writeCharCode($space);
return;
} }
if (node.value.span != null) { if (node.value.span != null) {
@ -271,8 +276,11 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
_writeWithIndent(value, minimumIndentation); _writeWithIndent(value, minimumIndentation);
} }
/// Returns the indentation level of the least-indented, non-empty line in /// Returns the indentation level of the least-indented non-empty line in
/// [text]. /// [text] after the first.
///
/// Returns `null` if [text] contains no newlines, and -1 if it contains
/// newlines but no lines are indented.
int _minimumIndentation(String text) { int _minimumIndentation(String text) {
var scanner = new LineScanner(text); var scanner = new LineScanner(text);
while (!scanner.isDone && scanner.readChar() != $lf) {} while (!scanner.isDone && scanner.readChar() != $lf) {}
@ -290,23 +298,54 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
while (!scanner.isDone && scanner.readChar() != $lf) {} while (!scanner.isDone && scanner.readChar() != $lf) {}
} }
return min; return min ?? -1;
} }
/// Writes [text] to [_buffer], adding [minimumIndentation] to each non-empty /// Writes [text] to [_buffer], replacing [minimumIndentation] with
/// line. /// [_indentation] for each non-empty line after the first.
///
/// Compresses trailing empty lines of [text] into a single trailing space.
void _writeWithIndent(String text, int minimumIndentation) { void _writeWithIndent(String text, int minimumIndentation) {
var scanner = new LineScanner(text); var scanner = new LineScanner(text);
while (!scanner.isDone && scanner.peekChar() != $lf) {
_buffer.writeCharCode(scanner.readChar()); // Write the first line as-is.
while (!scanner.isDone) {
var next = scanner.readChar();
if (next == $lf) break;
_buffer.writeCharCode(next);
} }
while (!scanner.isDone) { while (true) {
_buffer.writeCharCode(scanner.readChar()); assert(isWhitespace(scanner.peekChar(-1)));
for (var i = 0; i < minimumIndentation; i++) scanner.readChar();
// Scan forward until we hit non-whitespace or the end of [text].
var lineStart = scanner.position;
var newlines = 1;
while (true) {
// If we hit the end of [text], we still need to preserve the fact that
// whitespace exists because it could matter for custom properties.
if (scanner.isDone) {
_buffer.writeCharCode($space);
return;
}
var next = scanner.readChar();
if (next == $space || next == $tab) continue;
if (next != $lf) break;
lineStart = scanner.position;
newlines++;
}
_writeTimes($lf, newlines);
_writeIndentation(); _writeIndentation();
while (!scanner.isDone && scanner.peekChar() != $lf) { _buffer.write(scanner.substring(lineStart + minimumIndentation));
_buffer.writeCharCode(scanner.readChar());
// Scan and write until we hit a newline or the end of [text].
while (true) {
if (scanner.isDone) return;
var next = scanner.readChar();
if (next == $lf) break;
_buffer.writeCharCode(next);
} }
} }
} }
@ -848,9 +887,13 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
} }
/// Writes indentation based on [_indentation]. /// Writes indentation based on [_indentation].
void _writeIndentation() { void _writeIndentation() =>
for (var i = 0; i < _indentation * _indentWidth; i++) { _writeTimes(_indentCharacter, _indentation * _indentWidth);
_buffer.writeCharCode(_indentCharacter);
/// Writes [char] to [_buffer] with [times] repetitions.
void _writeTimes(int char, int times) {
for (var i = 0; i < times; i++) {
_buffer.writeCharCode(char);
} }
} }