Package com.github.sommeri.less4j.core.parser

Source Code of com.github.sommeri.less4j.core.parser.SelectorBuilder

package com.github.sommeri.less4j.core.parser;

import java.util.ArrayList;
import java.util.Iterator;

import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.ast.ASTCssNodeType;
import com.github.sommeri.less4j.core.ast.ElementSubsequent;
import com.github.sommeri.less4j.core.ast.Extend;
import com.github.sommeri.less4j.core.ast.PseudoClass;
import com.github.sommeri.less4j.core.ast.Selector;
import com.github.sommeri.less4j.core.ast.SelectorCombinator;
import com.github.sommeri.less4j.core.ast.SelectorCombinator.CombinatorType;
import com.github.sommeri.less4j.core.ast.SelectorPart;
import com.github.sommeri.less4j.core.problems.BugHappened;

public class SelectorBuilder {

  private static String EXTEND_PSEUDO = "extend";

  private final HiddenTokenAwareTree token;
  private final ASTBuilderSwitch parent;

  public SelectorBuilder(HiddenTokenAwareTree token, ASTBuilderSwitch astBuilderSwitch) {
    this.token = token;
    this.parent = astBuilderSwitch;
  }

  public Selector buildSelector() {
    Iterator<HiddenTokenAwareTree> iterator = token.getChildren().iterator();
    Selector result = new Selector(token, new ArrayList<SelectorPart>());
    while (iterator.hasNext()) {
      SelectorCombinator combinator = null;
      SelectorPart part = null;
      HiddenTokenAwareTree kid = iterator.next();

      if (ConversionUtils.isSelectorCombinator(kid)) {
        combinator = ConversionUtils.createSelectorCombinator(kid);
        kid = iterator.next();
        part = (SelectorPart) parent.switchOn(kid);
        // Ignore descendant combinator before appender. This info is already hidden in appender.isDirectlyBefore.
        if (isDescendant(combinator) && kid.getType() == LessLexer.NESTED_APPENDER)
          combinator = null;
      } else {
        //if it is not a combinator, then it is either nested appender, simple selector or escaped selector  
        part = (SelectorPart) parent.switchOn(kid);
      }

      part.setLeadingCombinator(combinator);
      if (combinator != null)
        part.getUnderlyingStructure().moveHidden(combinator.getUnderlyingStructure(), null);

      addPart(result, part);
    }
    return result;
  }

  private void addPart(Selector selector, SelectorPart part) {
    ElementSubsequent lastSubsequent = part.getLastSubsequent();
    while (lastSubsequent!=null && isExtends(lastSubsequent)) {
      Extend extend = convertToExtend((PseudoClass) lastSubsequent);
      selector.addExtend(extend);
      part.removeSubsequent(lastSubsequent);
      lastSubsequent = part.getLastSubsequent();
    }
   
    //if the part had only extend as members
    if (!part.isEmpty())
      selector.addPart(part);
  }
 
  private Extend convertToExtend(PseudoClass extend) {
    ASTCssNode parameter = extend.getParameter();
    if (parameter.getType()!=ASTCssNodeType.EXTEND) {
      throw new BugHappened(ASTBuilderSwitch.GRAMMAR_MISMATCH, parameter.getUnderlyingStructure());
    }
   
    return (Extend) parameter;
  }

  private boolean isExtends(ElementSubsequent subsequent) {
    return (subsequent instanceof PseudoClass) && EXTEND_PSEUDO.equals(subsequent.getName());
  }


  private boolean isDescendant(SelectorCombinator combinator) {
    return combinator != null && combinator.getCombinatorType() == CombinatorType.DESCENDANT;
  }
}
TOP

Related Classes of com.github.sommeri.less4j.core.parser.SelectorBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.