From 673db13d5158a1c4635cd96df19e33be522f3486 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Sat, 3 Sep 2016 02:40:13 -0700 Subject: [PATCH] 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. --- lib/src/ast/css/at_rule.dart | 2 ++ lib/src/ast/css/node.dart | 11 +++++++++++ lib/src/visitor/perform.dart | 22 ++++++---------------- lib/src/visitor/serialize.dart | 4 +++- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/lib/src/ast/css/at_rule.dart b/lib/src/ast/css/at_rule.dart index d4adfe90..0adf90e3 100644 --- a/lib/src/ast/css/at_rule.dart +++ b/lib/src/ast/css/at_rule.dart @@ -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; diff --git a/lib/src/ast/css/node.dart b/lib/src/ast/css/node.dart index 508078db..6d21fa73 100644 --- a/lib/src/ast/css/node.dart +++ b/lib/src/ast/css/node.dart @@ -14,6 +14,8 @@ abstract class CssNode extends AstNode { int _indexInParent; + bool get isInvisible => false; + /*=T*/ accept/**/(CssVisitor/**/ visitor); void remove() { @@ -35,6 +37,15 @@ abstract class CssParentNode extends CssNode { final List children; final List _children; + bool get isInvisible { + if (_isInvisible == null) { + _isInvisible = children.every((child) => child.isInvisible); + } + return _isInvisible; + } + + bool _isInvisible; + CssParentNode() : this._([]); CssParentNode._(List children) diff --git a/lib/src/visitor/perform.dart b/lib/src/visitor/perform.dart index c173576e..17913796 100644 --- a/lib/src/visitor/perform.dart +++ b/lib/src/visitor/perform.dart @@ -108,12 +108,6 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor { child.accept(this); } }); - - if (innerCopy == null) return; - while (innerCopy != root && innerCopy.children.isEmpty) { - innerCopy.remove(); - innerCopy = innerCopy.parent; - } } CssParentNode _trimIncluded(List nodes) { @@ -245,7 +239,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor { 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 { 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 _mergeMediaQueries( @@ -427,7 +419,7 @@ class PerformVisitor implements StatementVisitor, ExpressionVisitor { 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 { 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 { /*=T*/ _withParent/**/( /*=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 { parent.addChild(node); _parent = node; var result = _environment.scope(callback); - if (removeIfEmpty && node.children.isEmpty) node.remove(); _parent = oldParent; return result; diff --git a/lib/src/visitor/serialize.dart b/lib/src/visitor/serialize.dart index 10c6027f..9681bd26 100644 --- a/lib/src/visitor/serialize.dart +++ b/lib/src/visitor/serialize.dart @@ -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 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(); }