package com.github.sommeri.less4j.core.compiler.stages; import java.util.ArrayList; import java.util.List; import com.github.sommeri.less4j.core.ast.ASTCssNode; import com.github.sommeri.less4j.core.ast.Body; import com.github.sommeri.less4j.core.ast.BodyOwner; import com.github.sommeri.less4j.core.ast.Directive; import com.github.sommeri.less4j.core.ast.GeneralBody; import com.github.sommeri.less4j.core.ast.RuleSet; import com.github.sommeri.less4j.core.ast.Selector; import com.github.sommeri.less4j.core.compiler.selectors.UselessLessElementsRemover; import com.github.sommeri.less4j.utils.ArraysUtils; public class UnNestingAndBubbling { private final ASTManipulator manipulator = new ASTManipulator(); private final UselessLessElementsRemover uselessLessElementsRemover = new UselessLessElementsRemover(); //niekde tu je problem public void unnestRulesetsAndDirectives(Body generalBody) { List<? extends ASTCssNode> childs = new ArrayList<ASTCssNode>(generalBody.getChilds()); for (ASTCssNode kid : childs) { switch (kid.getType()) { case RULE_SET: { List<ASTCssNode> nestedRulesets = collectNestedRuleSets((RuleSet) kid); manipulator.addIntoBody(nestedRulesets, kid); uselessLessElementsRemover.removeFrom((RuleSet) kid); break; } default: if (AstLogic.isBubleableDirective(kid)) { Directive directive = (Directive) kid; unnestRulesetsAndDirectives(directive.getBody()); } else { if (kid instanceof BodyOwner<?>) { BodyOwner<?> bodyOwner = (BodyOwner<?>) kid; if (bodyOwner.getBody() != null) unnestRulesetsAndDirectives(bodyOwner.getBody()); } } } } } private List<ASTCssNode> collectNestedRuleSets(RuleSet topLevelNode) { NestedInRulesetStack nestedNodesStack = new NestedInRulesetStack(topLevelNode); collectChildRuleSets(topLevelNode, nestedNodesStack); return nestedNodesStack.getRulesets(); } private void collectChildRuleSets(ASTCssNode ownerNode, NestedInRulesetStack nestedNodes) { List<? extends ASTCssNode> childs = new ArrayList<ASTCssNode>(ownerNode.getChilds()); for (ASTCssNode kid : childs) { switch (kid.getType()) { case RULE_SET: { RuleSet nestedSet = (RuleSet) kid; manipulator.removeFromBody(nestedSet); nestedNodes.collect(nestedSet); nestedNodes.pushSelectors(nestedSet); collectChildRuleSets(kid, nestedNodes); nestedNodes.popSelectors(); break; } default: if (AstLogic.isBubleableDirective(kid)) { Directive directive = (Directive) kid; manipulator.removeFromBody(directive); nestedNodes.collect(directive); if (!directive.bubleUpWithoutChanges()) { List<Selector> outerSelectors = ArraysUtils.deeplyClonedList(nestedNodes.currentSelectors()); putBodyIntoRuleset(directive, outerSelectors); } unnestRulesetsAndDirectives(directive.getBody()); } else { // unless explicitly set, do not pass take rulessets out of body // owners if (!(kid instanceof BodyOwner<?>)) { collectChildRuleSets(kid, nestedNodes); } else { BodyOwner<?> bodyOwner = (BodyOwner<?>) kid; if (bodyOwner.getBody() != null) unnestRulesetsAndDirectives(bodyOwner.getBody()); } } break; } } } private void putBodyIntoRuleset(Directive bodyOwner, List<Selector> selectors) { RuleSet newRuleset = new RuleSet(bodyOwner.getUnderlyingStructure(), bodyOwner.getBody(), selectors); newRuleset.setVisibility(bodyOwner.getVisibility()); GeneralBody newBodyForOwner = new GeneralBody(bodyOwner.getUnderlyingStructure()); newBodyForOwner.setVisibility(bodyOwner.getVisibility()); newBodyForOwner.addMember(newRuleset); bodyOwner.setBody(newBodyForOwner); newBodyForOwner.configureParentToAllChilds(); bodyOwner.configureParentToAllChilds(); newRuleset.configureParentToAllChilds(); } }