Skip to content
This repository has been archived by the owner on Feb 23, 2022. It is now read-only.

Commit

Permalink
Allow conditional statements inside rulesets, including mixins.
Browse files Browse the repository at this point in the history
This change allows for conditionally including properties within a ruleset or
mixin, like so:

@defmixin foo() {
  @if (COND) {
    bar: baz
  }
}

Previously, this would cause an IllegalStateException in the @defmixin case
from the precondition in CssConditionalRuleNode or an unknown @ rule in the
ruleset case.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=118486801
  • Loading branch information
iflan committed Jun 8, 2016
1 parent edb3d2b commit 1bdf5f8
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public CssConditionalRuleNode(Type type, CssLiteralNode name) {
*/
public CssConditionalRuleNode(Type type, CssLiteralNode name,
@Nullable CssBooleanExpressionNode condition,
CssBlockNode block) {
CssAbstractBlockNode block) {
super(type, name, block);
Preconditions.checkArgument(this.getType().isConditional());
if (condition != null) {
Expand Down Expand Up @@ -98,9 +98,8 @@ void setCondition(CssBooleanExpressionNode condition) {
}

@Override
public CssBlockNode getBlock() {
// This type is ensured by the constructor.
return (CssBlockNode) super.getBlock();
public CssAbstractBlockNode getBlock() {
return super.getBlock();
}

// TODO(user): Make sure that the parameters list is made up of a single
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
import com.google.common.collect.ImmutableList;

/**
* A {@link CssAbstractBlockNode} that contains only declarations and @-rules.
* A {@link CssAbstractBlockNode} that contains only declarations, @-rules,
* and conditional blocks.
*
* @author fbenz@google.com (Florian Benz)
*/
public class CssDeclarationBlockNode extends CssAbstractBlockNode {

private static final ImmutableList<Class<? extends CssNode>>
VALID_NODE_CLASSES = ImmutableList.of(
CssDeclarationNode.class, CssAtRuleNode.class);
CssDeclarationNode.class, CssAtRuleNode.class, CssConditionalBlockNode.class);

public CssDeclarationBlockNode() {
super(true, VALID_NODE_CLASSES);
Expand Down
6 changes: 3 additions & 3 deletions src/com/google/common/css/compiler/ast/CssTreeBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ enum State {
private boolean treeIsConstructed = false;

// TODO(user): Use Collections.asLifoQueue(new ArrayDeque()) for openBlocks
private List<CssBlockNode> openBlocks = null;
private List<CssAbstractBlockNode> openBlocks = null;
private List<CssConditionalBlockNode> openConditionalBlocks = null;
private CssDeclarationBlockNode declarationBlock = null;
private CssDeclarationNode declaration = null;
Expand Down Expand Up @@ -114,11 +114,11 @@ private void startMainBody() {
}
}

private CssBlockNode getEnclosingBlock() {
private CssAbstractBlockNode getEnclosingBlock() {
return openBlocks.get(openBlocks.size() - 1);
}

private void pushEnclosingBlock(CssBlockNode block) {
private void pushEnclosingBlock(CssAbstractBlockNode block) {
openBlocks.add(block);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ public void transitionToNextState() {
@VisibleForTesting
class VisitConditionalRuleChildrenState extends VisitReplaceChildrenState<CssNode> {

VisitConditionalRuleChildrenState(CssBlockNode block) {
VisitConditionalRuleChildrenState(CssAbstractBlockNode block) {
super(block);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@

package com.google.common.css.compiler.passes;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.css.SourceCodeLocation;
import com.google.common.css.compiler.ast.CssAbstractBlockNode;
import com.google.common.css.compiler.ast.CssAtRuleNode;
import com.google.common.css.compiler.ast.CssBlockNode;
import com.google.common.css.compiler.ast.CssBooleanExpressionNode;
import com.google.common.css.compiler.ast.CssCompilerPass;
import com.google.common.css.compiler.ast.CssConditionalBlockNode;
Expand Down Expand Up @@ -108,7 +107,7 @@ public void leaveUnknownAtRule(CssUnknownAtRuleNode node) {
@Override
public boolean enterRuleset(CssRulesetNode node) {
activeBlockNode = null;
return false;
return true;
}

@Override
Expand All @@ -119,9 +118,7 @@ public boolean enterDefinition(CssDefinitionNode node) {

private CssConditionalRuleNode createConditionalRuleNode(
CssUnknownAtRuleNode node, String name) {
Preconditions.checkState(node.getBlock() == null
|| node.getBlock() instanceof CssBlockNode);
CssBlockNode block = (CssBlockNode) node.getBlock();
CssAbstractBlockNode block = node.getBlock();
if (block == null) {
errorManager.report(new GssError("@" + name + " without block",
node.getSourceCodeLocation()));
Expand Down
9 changes: 5 additions & 4 deletions src/com/google/common/css/compiler/passes/PassRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public void runPasses(CssTree cssTree) {
new ProcessRefiners(cssTree.getMutatingVisitController(), errorManager,
job.simplifyCss).runPass();

// Eliminate conditional nodes.
new EliminateConditionalNodes(
cssTree.getMutatingVisitController(),
ImmutableSet.copyOf(job.trueConditionNames)).runPass();

// Collect mixin definitions and replace mixins
CollectMixinDefinitions collectMixinDefinitions =
new CollectMixinDefinitions(cssTree.getMutatingVisitController(),
Expand All @@ -106,10 +111,6 @@ public void runPasses(CssTree cssTree) {

new ProcessComponents<Object>(cssTree.getMutatingVisitController(),
errorManager).runPass();
// Eliminate conditional nodes.
new EliminateConditionalNodes(
cssTree.getMutatingVisitController(),
ImmutableSet.copyOf(job.trueConditionNames)).runPass();
// Collect constant definitions.
CollectConstantDefinitions collectConstantDefinitionsPass =
new CollectConstantDefinitions(cssTree);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import com.google.common.css.compiler.ast.CssConditionalBlockNode;
import com.google.common.css.compiler.ast.CssConditionalRuleNode;
import com.google.common.css.compiler.ast.CssDeclarationBlockNode;
import com.google.common.css.compiler.ast.CssNode;
import com.google.common.css.compiler.ast.CssRulesetNode;
import com.google.common.css.compiler.ast.testing.NewFunctionalTestBase;

/**
Expand Down Expand Up @@ -72,6 +74,26 @@ public void testCreateNestedConditionalBlockNode() throws Exception {
assertEquals("[[d]{[e:[f]]}]", elseCondRuleIf.getBlock().toString());
}

public void testCreateConditionalBlockNodeInRuleset() throws Exception {
parseAndRun("a {@if X {b: c} @else {d: e} }");
assertTrue(getFirstActualNode() instanceof CssRulesetNode);
CssRulesetNode ruleset = (CssRulesetNode) getFirstActualNode();
assertEquals("[a]{[[@if[X]{[b:[c]]}, @else[]{[d:[e]]}]]}", ruleset.toString());
CssDeclarationBlockNode declarationBlock = ruleset.getDeclarations();
assertEquals(1, declarationBlock.getChildren().size());
assertTrue(declarationBlock.getChildAt(0) instanceof CssConditionalBlockNode);
CssConditionalBlockNode condBlock = (CssConditionalBlockNode) declarationBlock.getChildAt(0);
assertEquals(2, condBlock.getChildren().size());
CssConditionalRuleNode condRuleIf = condBlock.getChildren().get(0);
CssConditionalRuleNode condRuleElse = condBlock.getChildren().get(1);
assertEquals("if", condRuleIf.getName().getValue());
assertEquals(1, condRuleIf.getParametersCount());
assertEquals("[b:[c]]", condRuleIf.getBlock().toString());
assertEquals("else", condRuleElse.getName().getValue());
assertEquals(0, condRuleElse.getParametersCount());
assertEquals("[d:[e]]", condRuleElse.getBlock().toString());
}

public void testIfWithoutBlockError() throws Exception {
parseAndRun("@if (X) ;", "@if without block");
}
Expand Down

0 comments on commit 1bdf5f8

Please sign in to comment.