Move emptiness-checking to the serializer.

We can't actually know if a rule will be empty until we've evaluated the
entire stylesheet, since it might contain a placeholder that may or may
not be extended.
This commit is contained in:
Natalie Weizenbaum 2016-09-03 02:40:13 -07:00 committed by Natalie Weizenbaum
parent cc56ea0f13
commit 673db13d51
4 changed files with 22 additions and 17 deletions

View File

@ -17,6 +17,8 @@ class CssAtRule extends CssParentNode {
final FileSpan span;
bool get isInvisible => false;
CssAtRule(this.name, this.span, {bool childless: false, this.value})
: isChildless = childless;

View File

@ -14,6 +14,8 @@ abstract class CssNode extends AstNode {
int _indexInParent;
bool get isInvisible => false;
/*=T*/ accept/*<T>*/(CssVisitor/*<T>*/ visitor);
void remove() {
@ -35,6 +37,15 @@ abstract class CssParentNode extends CssNode {
final List<CssNode> children;
final List<CssNode> _children;
bool get isInvisible {
if (_isInvisible == null) {
_isInvisible = children.every((child) => child.isInvisible);
}
return _isInvisible;
}
bool _isInvisible;
CssParentNode() : this._([]);
CssParentNode._(List<CssNode> children)

View File

@ -108,12 +108,6 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
child.accept(this);
}
});
if (innerCopy == null) return;
while (innerCopy != root && innerCopy.children.isEmpty) {
innerCopy.remove();
innerCopy = innerCopy.parent;
}
}
CssParentNode _trimIncluded(List<CssParentNode> nodes) {
@ -245,7 +239,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
for (var child in node.children) {
child.accept(this);
}
}, removeIfEmpty: true);
});
}
}, through: (node) => node is CssStyleRule);
}
@ -371,12 +365,10 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
for (var child in node.children) {
child.accept(this);
}
}, removeIfEmpty: true);
});
}
});
},
through: (node) => node is CssStyleRule || node is CssMediaRule,
removeIfEmpty: true);
}, through: (node) => node is CssStyleRule || node is CssMediaRule);
}
List<CssMediaQuery> _mergeMediaQueries(
@ -427,7 +419,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
child.accept(this);
}
});
}, through: (node) => node is CssStyleRule, removeIfEmpty: true);
}, through: (node) => node is CssStyleRule);
}
void visitSupportsRule(SupportsRule node) {
@ -453,7 +445,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
for (var child in node.children) {
child.accept(this);
}
}, removeIfEmpty: true);
});
}
}, through: (node) => node is CssStyleRule);
}
@ -770,8 +762,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
/*=T*/ _withParent/*<S extends CssParentNode, T>*/(
/*=S*/ node,
/*=T*/ callback(),
{bool through(CssNode node),
bool removeIfEmpty: false}) {
{bool through(CssNode node)}) {
var oldParent = _parent;
// Go up through parents that match [through].
@ -785,7 +776,6 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
parent.addChild(node);
_parent = node;
var result = _environment.scope(callback);
if (removeIfEmpty && node.children.isEmpty) node.remove();
_parent = oldParent;
return result;

View File

@ -50,6 +50,7 @@ class _SerializeCssVisitor
void visitStylesheet(CssStylesheet node) {
for (var child in node.children) {
if (child.isInvisible) continue;
child.accept(this);
_buffer.writeln();
}
@ -394,7 +395,7 @@ class _SerializeCssVisitor
void _visitChildren(Iterable<CssNode> children) {
_buffer.writeCharCode($lbrace);
if (children.isEmpty) {
if (children.every((child) => child.isInvisible)) {
_buffer.writeCharCode($rbrace);
return;
}
@ -402,6 +403,7 @@ class _SerializeCssVisitor
_buffer.writeln();
_indent(() {
for (var child in children) {
if (child.isInvisible) continue;
child.accept(this);
_buffer.writeln();
}