Skip to content

Commit

Permalink
Merge pull request #629 from HubSpot/chunk-resolver-parser
Browse files Browse the repository at this point in the history
AST deferred value handling
  • Loading branch information
jasmith-hs authored Apr 7, 2021
2 parents f0cc594 + b63cb63 commit f7f3a7f
Show file tree
Hide file tree
Showing 63 changed files with 2,222 additions and 585 deletions.
17 changes: 17 additions & 0 deletions src/main/java/com/hubspot/jinjava/Jinjava.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.hubspot.jinjava.doc.JinjavaDocFactory;
import com.hubspot.jinjava.el.ExtendedSyntaxBuilder;
import com.hubspot.jinjava.el.TruthyTypeConverter;
import com.hubspot.jinjava.el.ext.eager.EagerExtendedSyntaxBuilder;
import com.hubspot.jinjava.interpret.Context;
import com.hubspot.jinjava.interpret.FatalTemplateErrorsException;
import com.hubspot.jinjava.interpret.InterpretException;
Expand Down Expand Up @@ -61,6 +62,7 @@
*/
public class Jinjava {
private ExpressionFactory expressionFactory;
private ExpressionFactory eagerExpressionFactory;
private ResourceLocator resourceLocator;

private Context globalContext;
Expand All @@ -84,13 +86,21 @@ public Jinjava(JinjavaConfig globalConfig) {
this.globalContext = new Context();

Properties expConfig = new Properties();

expConfig.setProperty(
TreeBuilder.class.getName(),
ExtendedSyntaxBuilder.class.getName()
);
Properties eagerExpConfig = new Properties();

eagerExpConfig.setProperty(
TreeBuilder.class.getName(),
EagerExtendedSyntaxBuilder.class.getName()
);

TypeConverter converter = new TruthyTypeConverter();
this.expressionFactory = new ExpressionFactoryImpl(expConfig, converter);
this.eagerExpressionFactory = new ExpressionFactoryImpl(eagerExpConfig, converter);

this.resourceLocator = new ClasspathResourceLocator();
}
Expand All @@ -112,6 +122,13 @@ public ExpressionFactory getExpressionFactory() {
return expressionFactory;
}

/**
* @return The EL factory used to eagerly process expressions in templates by this instance.
*/
public ExpressionFactory getEagerExpressionFactory() {
return eagerExpressionFactory;
}

/**
* @return The global config used as a base for all render operations performed by this instance.
*/
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/com/hubspot/jinjava/el/ExpressionResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ public class ExpressionResolver {

public ExpressionResolver(JinjavaInterpreter interpreter, Jinjava jinjava) {
this.interpreter = interpreter;
this.expressionFactory = jinjava.getExpressionFactory();
this.expressionFactory =
interpreter.getConfig().getExecutionMode().useEagerParser()
? jinjava.getEagerExpressionFactory()
: jinjava.getExpressionFactory();

this.resolver = new JinjavaInterpreterResolver(interpreter);
this.elContext = new JinjavaELContext(interpreter, resolver);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import com.google.common.collect.ImmutableMap;
import com.hubspot.jinjava.el.ext.AbstractCallableMethod;
import com.hubspot.jinjava.el.ext.DeferredParsingException;
import com.hubspot.jinjava.el.ext.ExtendedParser;
import com.hubspot.jinjava.el.ext.JinjavaBeanELResolver;
import com.hubspot.jinjava.el.ext.JinjavaListELResolver;
Expand Down Expand Up @@ -241,11 +242,15 @@ private Object getValue(
}

if (value instanceof DeferredValue) {
throw new DeferredValueException(
propertyName,
interpreter.getLineNumber(),
interpreter.getPosition()
);
if (interpreter.getConfig().getExecutionMode().useEagerParser()) {
throw new DeferredParsingException(this, propertyName);
} else {
throw new DeferredValueException(
propertyName,
interpreter.getLineNumber(),
interpreter.getPosition()
);
}
}
} catch (PropertyNotFoundException e) {
if (errOnUnknownProp) {
Expand Down
80 changes: 43 additions & 37 deletions src/main/java/com/hubspot/jinjava/el/ext/AbsOperator.java
Original file line number Diff line number Diff line change
@@ -1,51 +1,57 @@
package com.hubspot.jinjava.el.ext;

import com.hubspot.jinjava.el.ext.eager.EagerAstUnary;
import de.odysseus.el.misc.TypeConverter;
import de.odysseus.el.tree.impl.Parser.ExtensionHandler;
import de.odysseus.el.tree.impl.Parser.ExtensionPoint;
import de.odysseus.el.tree.impl.Scanner;
import de.odysseus.el.tree.impl.Scanner.ExtensionToken;
import de.odysseus.el.tree.impl.ast.AstNode;
import de.odysseus.el.tree.impl.ast.AstUnary;
import de.odysseus.el.tree.impl.ast.AstUnary.SimpleOperator;

public class AbsOperator {
public class AbsOperator extends SimpleOperator {
public static final ExtensionToken TOKEN = new Scanner.ExtensionToken("+");
public static final AbsOperator OP = new AbsOperator();

public static final ExtensionHandler HANDLER = new ExtensionHandler(
ExtensionPoint.UNARY
) {

@Override
public AstNode createAstNode(AstNode... children) {
return new AstUnary(
children[0],
new AstUnary.SimpleOperator() {

@Override
protected Object apply(TypeConverter converter, Object o) {
if (o == null) {
return null;
}

if (o instanceof Float) {
return Math.abs((Float) o);
}
if (o instanceof Double) {
return Math.abs((Double) o);
}
if (o instanceof Integer) {
return Math.abs((Integer) o);
}
if (o instanceof Long) {
return Math.abs((Long) o);
}

throw new IllegalArgumentException(
"Unable to apply abs operator on object of type: " + o.getClass()
);
}
}
);
public static final ExtensionHandler HANDLER = getHandler(false);

@Override
protected Object apply(TypeConverter converter, Object o) {
if (o == null) {
return null;
}

if (o instanceof Float) {
return Math.abs((Float) o);
}
if (o instanceof Double) {
return Math.abs((Double) o);
}
if (o instanceof Integer) {
return Math.abs((Integer) o);
}
};
if (o instanceof Long) {
return Math.abs((Long) o);
}

throw new IllegalArgumentException(
"Unable to apply abs operator on object of type: " + o.getClass()
);
}

@Override
public String toString() {
return "+";
}

public static ExtensionHandler getHandler(boolean eager) {
return new ExtensionHandler(ExtensionPoint.UNARY) {

@Override
public AstNode createAstNode(AstNode... children) {
return eager ? new EagerAstUnary(children[0], OP) : new AstUnary(children[0], OP);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,10 @@ protected Object apply(TypeConverter converter, Object o1, Object o2) {
return NumberOperations.add(converter, o1, o2);
}

@Override
public String toString() {
return "+";
}

public static final AdditionOperator OP = new AdditionOperator();
}
2 changes: 1 addition & 1 deletion src/main/java/com/hubspot/jinjava/el/ext/AstDict.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import javax.el.ELContext;

public class AstDict extends AstLiteral {
private final Map<AstNode, AstNode> dict;
protected final Map<AstNode, AstNode> dict;

public AstDict(Map<AstNode, AstNode> dict) {
this.dict = dict;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/hubspot/jinjava/el/ext/AstList.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.apache.commons.lang3.StringUtils;

public class AstList extends AstLiteral {
private final AstParameters elements;
protected final AstParameters elements;

public AstList(AstParameters elements) {
this.elements = elements;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.hubspot.jinjava.el.ext;

import com.hubspot.jinjava.el.ext.eager.EagerAstBinary;
import de.odysseus.el.misc.TypeConverter;
import de.odysseus.el.tree.impl.Parser.ExtensionHandler;
import de.odysseus.el.tree.impl.Parser.ExtensionPoint;
Expand Down Expand Up @@ -58,16 +59,25 @@ public Object apply(TypeConverter converter, Object o1, Object o2) {
return Boolean.FALSE;
}

@Override
public String toString() {
return TOKEN.getImage();
}

public static final CollectionMembershipOperator OP = new CollectionMembershipOperator();
public static final Scanner.ExtensionToken TOKEN = new Scanner.ExtensionToken("in");

public static final ExtensionHandler HANDLER = new ExtensionHandler(
ExtensionPoint.CMP
) {
public static final ExtensionHandler HANDLER = getHandler(false);

@Override
public AstNode createAstNode(AstNode... children) {
return new AstBinary(children[0], children[1], OP);
}
};
public static ExtensionHandler getHandler(boolean eager) {
return new ExtensionHandler(ExtensionPoint.CMP) {

@Override
public AstNode createAstNode(AstNode... children) {
return eager
? new EagerAstBinary(children[0], children[1], OP)
: new AstBinary(children[0], children[1], OP);
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.hubspot.jinjava.el.ext;

import com.hubspot.jinjava.interpret.DeferredValueException;

public class DeferredParsingException extends DeferredValueException {
private final String deferredEvalResult;
private final Object sourceNode;

public DeferredParsingException(Object sourceNode, String deferredEvalResult) {
super(
String.format(
"%s could not be parsed more than: %s",
sourceNode.getClass(),
deferredEvalResult
)
);
this.deferredEvalResult = deferredEvalResult;
this.sourceNode = sourceNode;
}

public String getDeferredEvalResult() {
return deferredEvalResult;
}

public Object getSourceNode() {
return sourceNode;
}
}
Loading

0 comments on commit f7f3a7f

Please sign in to comment.