package com.github.sommeri.less4j.core.compiler.expressions;
import java.util.ArrayList;
import java.util.List;
import com.github.sommeri.less4j.LessFunction;
import com.github.sommeri.less4j.LessProblems;
import com.github.sommeri.less4j.core.ast.ASTCssNode;
import com.github.sommeri.less4j.core.ast.Expression;
import com.github.sommeri.less4j.core.ast.FaultyExpression;
import com.github.sommeri.less4j.core.ast.FunctionExpression;
import com.github.sommeri.less4j.core.problems.ProblemsHandler;
import com.github.sommeri.less4j.utils.ArraysUtils;
public class CustomFunctions implements FunctionsPackage {
private final ProblemsHandler problemsHandler;
private List<LessFunction> functions;
public CustomFunctions(ProblemsHandler problemsHandler, List<LessFunction> functions) {
this.problemsHandler = problemsHandler;
this.functions = functions == null ? new ArrayList<LessFunction>() : functions;
}
@Override
public boolean canEvaluate(FunctionExpression input, List<Expression> parameters) {
for (LessFunction function : functions) {
if (function.canEvaluate(input, parameters))
return true;
}
return false;
}
@Override
public Expression evaluate(FunctionExpression input, List<Expression> parameters, Expression evaluatedParameter) {
for (LessFunction function : functions) {
if (function.canEvaluate(input, parameters)) {
FunctionExpression inputClone = input.clone();
List<Expression> parametersClone = ArraysUtils.deeplyClonedList(parameters);
Expression evaluatedParameterClone = evaluatedParameter.clone();
return fixResult(function.evaluate(inputClone, parametersClone, evaluatedParameterClone, new SafeLessProblem(problemsHandler, inputClone)), input);
}
}
return new FaultyExpression(input);
}
private Expression fixResult(Expression result, FunctionExpression input) {
if (result == null)
return new FaultyExpression(input);
fixNode(result, input);
return result;
}
private void fixNode(ASTCssNode node, FunctionExpression input) {
if (node.getUnderlyingStructure()==null)
node.setUnderlyingStructure(input.getUnderlyingStructure());
node.configureParentToAllChilds();
for (ASTCssNode child : node.getChilds()) {
fixNode(child, input);
}
}
public class SafeLessProblem implements LessProblems {
private static final String DEFAULT_DESCRIPTION = "<custom description was not specified>";
private final ProblemsHandler problemsHandler;
private final FunctionExpression defaultErrorNode;
public SafeLessProblem(ProblemsHandler problemsHandler, FunctionExpression defaultErrorNode) {
this.problemsHandler = problemsHandler;
this.defaultErrorNode = defaultErrorNode;
}
@Override
public void addError(ASTCssNode errorNode, String description) {
errorNode = errorNode == null ? defaultErrorNode : errorNode;
description = description == null ? DEFAULT_DESCRIPTION : description;
problemsHandler.addError(errorNode, description);
}
@Override
public void addWarning(ASTCssNode weirdNode, String description) {
weirdNode = weirdNode == null ? defaultErrorNode : weirdNode;
description = description == null ? DEFAULT_DESCRIPTION : description;
problemsHandler.addWarning(weirdNode, description);
}
}
}