package com.github.sommeri.less4j.core.compiler.stages; import java.util.List; import java.util.Set; import com.github.sommeri.less4j.core.ast.ASTCssNode; import com.github.sommeri.less4j.core.ast.ASTCssNodeType; import com.github.sommeri.less4j.core.ast.Body; import com.github.sommeri.less4j.core.ast.BodyOwner; import com.github.sommeri.less4j.core.ast.CssString; import com.github.sommeri.less4j.core.ast.Directive; import com.github.sommeri.less4j.core.ast.Expression; import com.github.sommeri.less4j.core.ast.FunctionExpression; import com.github.sommeri.less4j.core.ast.ReusableStructure; import com.github.sommeri.less4j.core.ast.SelectorCombinator.CombinatorType; import com.github.sommeri.less4j.core.ast.SimpleSelector; import com.github.sommeri.less4j.core.problems.BugHappened; import com.github.sommeri.less4j.core.problems.ProblemsHandler; import com.github.sommeri.less4j.core.validators.SupportedLessBodyMembers; public class AstLogic { public static boolean hasOwnScope(ASTCssNode node) { return isBody(node) || isBodyOwner(node); } public static boolean isBubleableDirective(ASTCssNode node) { if (!(node instanceof Directive)) return false; return ((Directive) node).hasBody(); } public static boolean isBodyOwner(ASTCssNode node) { return node instanceof BodyOwner; } protected static boolean isBody(ASTCssNode node) { return node instanceof Body; } public static boolean canHaveArguments(ASTCssNode owner) { if (owner.getType()!=ASTCssNodeType.REUSABLE_STRUCTURE) return false; return ((ReusableStructure)owner).hasParameters(); } public static void validateLessBodyCompatibility(ASTCssNode reference, List<ASTCssNode> members, ProblemsHandler problemsHandler) { ASTCssNode parent = reference.getParent(); if (!isBody(parent)) { throw new BugHappened("Parent is not a body instance. " + parent, parent); } SupportedLessBodyMembers allowedBodyMembers = new SupportedLessBodyMembers(); Set<ASTCssNodeType> supportedMembers = allowedBodyMembers.getSupportedMembers((Body) parent); for (ASTCssNode member : members) { if (!supportedMembers.contains(member.getType())) { problemsHandler.wrongMemberBroughtIntoBody(reference, member, parent); } } } public static boolean hasNonSpaceCombinator(SimpleSelector selector) { return selector.hasLeadingCombinator() && selector.getLeadingCombinator().getCombinatorType()!=CombinatorType.DESCENDANT; } public static boolean isQuotelessUrlFunction(ASTCssNode kid) { if (kid.getType() != ASTCssNodeType.FUNCTION) return false; FunctionExpression function = (FunctionExpression) kid; String name = function.getName(); if (!"url".equals(name == null ? null : name.toLowerCase())) return false; Expression parameter = function.getParameter().splitByComma().get(0); if (parameter.getType()!=ASTCssNodeType.STRING_EXPRESSION) return false; CssString stringParameter = (CssString)parameter; return "".equals(stringParameter.getQuoteType()); } public static boolean isExpression(ASTCssNode kid) { return kid instanceof Expression; } public static boolean isDetachedRuleset(Expression value) { return value!=null && value.getType()==ASTCssNodeType.DETACHED_RULESET; } }