import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
node.traverse();
- @SuppressWarnings("unchecked")
- HashMap<String, VariableNode> variableScope = (HashMap<String, VariableNode>) variables
- .clone();
+ Map<String, VariableNode> variableScope = openVariableScope();
// the size of the child list may change on each iteration: current node
// may get deleted and possibly other nodes have been inserted where it
}
}
- variables.clear();
- variables.putAll(variableScope);
+ closeVariableScope(variableScope);
// clean up insert point so that processing of the next block will
// insert after that block
}
}
+ /**
+ * Start a new scope for variables. Any variables set or modified after
+ * opening a new scope are only valid until the scope is closed, at which
+ * time they are replaced with their old values.
+ *
+ * @return old scope to give to a paired {@link #closeVariableScope(Map)}
+ * call at the end of the scope (unmodifiable map).
+ */
+ public static Map<String, VariableNode> openVariableScope() {
+ @SuppressWarnings("unchecked")
+ HashMap<String, VariableNode> variableScope = (HashMap<String, VariableNode>) variables
+ .clone();
+ return Collections.unmodifiableMap(variableScope);
+ }
+
+ /**
+ * End a scope for variables, replacing all active variables with those from
+ * the original scope (obtained from {@link #openVariableScope()}).
+ *
+ * @param originalScope
+ * original scope
+ */
+ public static void closeVariableScope(
+ Map<String, VariableNode> originalScope) {
+ variables.clear();
+ variables.putAll(originalScope);
+ }
+
public void removeEmptyBlocks(Node node) {
// depth first for avoiding re-checking parents of removed nodes
for (Node child : new ArrayList<Node>(node.getChildren())) {
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Map;
import com.vaadin.sass.internal.ScssStylesheet;
import com.vaadin.sass.internal.parser.LexicalUnitImpl;
this.arglist = arglist;
}
+ /**
+ * Replace variable references with their values in the mixin argument list.
+ */
@Override
public void replaceVariables(ArrayList<VariableNode> variables) {
for (final VariableNode var : variables) {
for (final LexicalUnitImpl arg : new ArrayList<LexicalUnitImpl>(
arglist)) {
- if (arg.getLexicalUnitType() == LexicalUnitImpl.SCSS_VARIABLE
- && arg.getStringValue().equals(var.getName())) {
- arg.replaceValue(var.getExpr());
+ LexicalUnitImpl unit = arg;
+ // only perform replace in the value if separate argument name
+ // and value
+ if (unit.getNextLexicalUnit() != null) {
+ unit = unit.getNextLexicalUnit();
+ }
+ if (unit.getLexicalUnitType() == LexicalUnitImpl.SCSS_VARIABLE
+ && unit.getStringValue().equals(var.getName())) {
+ unit.replaceValue(var.getExpr());
}
}
@Override
public void traverse() {
try {
+ // limit variable scope to the mixin
+ Map<String, VariableNode> variableScope = ScssStylesheet
+ .openVariableScope();
+
replaceVariables(ScssStylesheet.getVariables());
MixinNodeHandler.traverse(this);
+
+ ScssStylesheet.closeVariableScope(variableScope);
+
} catch (Exception e) {
e.printStackTrace();
}