Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

MixinNodeHandler.java 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright 2000-2013 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.sass.internal.visitor;
  17. import java.util.ArrayList;
  18. import com.vaadin.sass.internal.ScssStylesheet;
  19. import com.vaadin.sass.internal.parser.LexicalUnitImpl;
  20. import com.vaadin.sass.internal.tree.IVariableNode;
  21. import com.vaadin.sass.internal.tree.MixinDefNode;
  22. import com.vaadin.sass.internal.tree.MixinNode;
  23. import com.vaadin.sass.internal.tree.Node;
  24. import com.vaadin.sass.internal.tree.VariableNode;
  25. import com.vaadin.sass.internal.util.DeepCopy;
  26. public class MixinNodeHandler {
  27. public static void traverse(MixinNode node) throws Exception {
  28. replaceMixins(node);
  29. }
  30. private static void replaceMixins(MixinNode node) throws Exception {
  31. MixinDefNode mixinDef = ScssStylesheet.getMixinDefinition(node
  32. .getName());
  33. if (mixinDef == null) {
  34. throw new Exception("Mixin Definition: " + node.getName()
  35. + " not found");
  36. }
  37. replaceMixinNode(node, mixinDef);
  38. }
  39. private static void replaceMixinNode(MixinNode mixinNode,
  40. MixinDefNode mixinDef) {
  41. Node pre = mixinNode;
  42. MixinDefNode defClone = (MixinDefNode) DeepCopy.copy(mixinDef);
  43. defClone.traverse();
  44. if (mixinDef.getArglist().isEmpty()) {
  45. for (Node child : new ArrayList<Node>(defClone.getChildren())) {
  46. mixinNode.getParentNode().appendChild(child, pre);
  47. pre = child;
  48. }
  49. } else {
  50. replacePossibleArguments(mixinNode, defClone);
  51. Node previous = mixinNode;
  52. for (final Node child : defClone.getChildren()) {
  53. Node clone = (Node) DeepCopy.copy(child);
  54. replaceChildVariables(defClone, clone);
  55. mixinNode.getParentNode().appendChild(clone, previous);
  56. previous = clone;
  57. }
  58. }
  59. mixinNode.getParentNode().removeChild(mixinNode);
  60. }
  61. /**
  62. * We have to replace all the mixin parameters. This is done in two phases.
  63. * First phase replaces all the named parameters while the second replaces
  64. * in order of remaining unmodified parameters.
  65. *
  66. * @param mixinNode
  67. * @param def
  68. */
  69. private static void replacePossibleArguments(MixinNode mixinNode,
  70. MixinDefNode def) {
  71. if (mixinNode.getArglist().size() > 0) {
  72. ArrayList<VariableNode> remainingNodes = new ArrayList<VariableNode>(
  73. def.getArglist());
  74. ArrayList<LexicalUnitImpl> remainingUnits = new ArrayList<LexicalUnitImpl>(
  75. mixinNode.getArglist());
  76. for (final LexicalUnitImpl unit : mixinNode.getArglist()) {
  77. if (unit.getLexicalUnitType() == LexicalUnitImpl.SCSS_VARIABLE
  78. && unit.getNextLexicalUnit() != null) {
  79. for (final VariableNode node : def.getArglist()) {
  80. if (node.getName().equals(unit.getValue().toString())) {
  81. node.setExpr((LexicalUnitImpl) DeepCopy.copy(unit
  82. .getNextLexicalUnit()));
  83. remainingNodes.remove(node);
  84. remainingUnits.remove(unit);
  85. break;
  86. }
  87. }
  88. }
  89. }
  90. checkExtraParameters(mixinNode, remainingNodes.size(),
  91. remainingUnits.size());
  92. for (int i = 0; i < remainingNodes.size()
  93. && i < remainingUnits.size(); i++) {
  94. LexicalUnitImpl unit = remainingUnits.get(i);
  95. remainingNodes.get(i).setExpr(
  96. (LexicalUnitImpl) DeepCopy.copy(unit));
  97. }
  98. }
  99. }
  100. protected static void checkExtraParameters(MixinNode mixinNode,
  101. int remainingNodesSize, int remainingUnitsSize) {
  102. if (remainingUnitsSize > remainingNodesSize) {
  103. String fileName = null;
  104. Node root = mixinNode.getParentNode();
  105. while (root != null && !(root instanceof ScssStylesheet)) {
  106. root = root.getParentNode();
  107. }
  108. if (root != null) {
  109. fileName = ((ScssStylesheet) root).getFileName();
  110. }
  111. StringBuilder builder = new StringBuilder();
  112. builder.append("More parameters than expected, in Mixin ").append(
  113. mixinNode.getName());
  114. if (fileName != null) {
  115. builder.append(", in file ").append(fileName);
  116. }
  117. throw new RuntimeException(builder.toString());
  118. }
  119. }
  120. private static void replaceChildVariables(MixinDefNode mixinDef, Node node) {
  121. for (final Node child : node.getChildren()) {
  122. replaceChildVariables(mixinDef, child);
  123. }
  124. if (node instanceof IVariableNode) {
  125. ((IVariableNode) node).replaceVariables(mixinDef.getArglist());
  126. }
  127. }
  128. }