Skip to content

Commit 027cdcc

Browse files
authored
Merge pull request #1199 from HubSpot/macro-current-path-fix
Wrap the current path around reconstructed macro functions
2 parents 789cfe2 + 6497990 commit 027cdcc

16 files changed

Lines changed: 146 additions & 12 deletions

File tree

src/main/java/com/hubspot/jinjava/Jinjava.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.hubspot.jinjava.lib.fn.ELFunctionDefinition;
3636
import com.hubspot.jinjava.lib.tag.Tag;
3737
import com.hubspot.jinjava.loader.ClasspathResourceLocator;
38+
import com.hubspot.jinjava.loader.RelativePathResolver;
3839
import com.hubspot.jinjava.loader.ResourceLocator;
3940
import de.odysseus.el.ExpressionFactoryImpl;
4041
import de.odysseus.el.misc.TypeConverter;
@@ -244,6 +245,10 @@ public RenderResult renderForResult(
244245
} else {
245246
context = new Context(copyGlobalContext(), bindings, renderConfig.getDisabled());
246247
}
248+
Object currentPath = context.get(RelativePathResolver.CURRENT_PATH_CONTEXT_KEY);
249+
if (currentPath != null) {
250+
context.getCurrentPathStack().pushWithoutCycleCheck(currentPath.toString(), 0, 0);
251+
}
247252

248253
JinjavaInterpreter interpreter = globalConfig
249254
.getInterpreterFactory()
@@ -290,6 +295,9 @@ public RenderResult renderForResult(
290295
);
291296
} finally {
292297
globalContext.reset();
298+
if (currentPath != null) {
299+
context.getCurrentPathStack().pop();
300+
}
293301
JinjavaInterpreter.popCurrent();
294302
}
295303
}

src/main/java/com/hubspot/jinjava/lib/fn/eager/EagerMacroFunction.java

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.hubspot.jinjava.lib.fn.eager;
22

3+
import static com.hubspot.jinjava.loader.RelativePathResolver.CURRENT_PATH_CONTEXT_KEY;
4+
35
import com.google.common.annotations.Beta;
46
import com.hubspot.jinjava.el.ext.AstMacroFunction;
57
import com.hubspot.jinjava.el.ext.DeferredInvocationResolutionException;
@@ -13,6 +15,7 @@
1315
import com.hubspot.jinjava.lib.fn.MacroFunction;
1416
import com.hubspot.jinjava.lib.tag.MacroTag;
1517
import com.hubspot.jinjava.lib.tag.eager.EagerExecutionResult;
18+
import com.hubspot.jinjava.lib.tag.eager.importing.EagerImportingStrategyFactory;
1619
import com.hubspot.jinjava.objects.serialization.PyishObjectMapper;
1720
import com.hubspot.jinjava.tree.Node;
1821
import com.hubspot.jinjava.util.EagerContextWatcher;
@@ -80,6 +83,11 @@ public Object doEvaluate(
8083
() -> getEvaluationResultDirectly(argMap, kwargMap, varArgs, interpreter),
8184
interpreter
8285
);
86+
return wrapCurrentPathSetting(
87+
interpreter,
88+
importFile,
89+
result.asTemplateString()
90+
);
8391
}
8492
return result.asTemplateString();
8593
} finally {
@@ -121,12 +129,45 @@ public Object doEvaluate(
121129
.put(
122130
tempVarName,
123131
new MacroFunctionTempVariable(
124-
prefixToPreserveState + eagerExecutionResult.asTemplateString()
132+
wrapCurrentPathSetting(
133+
interpreter,
134+
Optional
135+
.ofNullable(localContextScope.get(Context.IMPORT_RESOURCE_PATH_KEY))
136+
.map(Object::toString),
137+
prefixToPreserveState + eagerExecutionResult.asTemplateString()
138+
)
125139
)
126140
);
127141
throw new DeferredInvocationResolutionException(tempVarName);
128142
}
129-
return eagerExecutionResult.getResult().toString(true);
143+
return wrapCurrentPathSetting(
144+
interpreter,
145+
Optional
146+
.ofNullable(localContextScope.get(Context.IMPORT_RESOURCE_PATH_KEY))
147+
.map(Object::toString),
148+
eagerExecutionResult.getResult().toString(true)
149+
);
150+
}
151+
152+
private static String wrapCurrentPathSetting(
153+
JinjavaInterpreter interpreter,
154+
Optional<String> importFile,
155+
String resultToWrap
156+
) {
157+
if (!importFile.isPresent()) {
158+
return resultToWrap;
159+
}
160+
final String initialPathSetter =
161+
EagerImportingStrategyFactory.getSetTagForCurrentPath(interpreter);
162+
final String newPathSetter = EagerReconstructionUtils.buildBlockOrInlineSetTag(
163+
CURRENT_PATH_CONTEXT_KEY,
164+
importFile.get(),
165+
interpreter
166+
);
167+
if (initialPathSetter.equals(newPathSetter)) {
168+
return resultToWrap;
169+
}
170+
return newPathSetter + resultToWrap + initialPathSetter;
130171
}
131172

132173
private String getEvaluationResultDirectly(
@@ -312,6 +353,7 @@ private boolean differentMacroWithSameNameExists(JinjavaInterpreter interpreter)
312353
return false;
313354
}
314355
MacroFunction mostRecent = context.getGlobalMacro(getName());
356+
//noinspection ErrorProne
315357
if (this != mostRecent) {
316358
return true;
317359
}

src/main/java/com/hubspot/jinjava/lib/tag/eager/importing/EagerImportingStrategyFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ public static String getSetTagForCurrentPath(JinjavaInterpreter interpreter) {
3434
.getContext()
3535
.getCurrentPathStack()
3636
.peek()
37+
.map(c -> {
38+
interpreter
39+
.getContext()
40+
.replace(RelativePathResolver.CURRENT_PATH_CONTEXT_KEY, c);
41+
return c;
42+
})
3743
.orElseGet(() ->
3844
(String) interpreter
3945
.getContext()

src/test/java/com/hubspot/jinjava/EagerTest.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ public void itDefersMacroInIf() {
625625

626626
@Test
627627
public void itPutsDeferredImportedMacroInOutput() {
628-
expectedTemplateInterpreter.assertExpectedOutput(
628+
expectedTemplateInterpreter.assertExpectedOutputNonIdempotent(
629629
"puts-deferred-imported-macro-in-output"
630630
);
631631
}
@@ -643,7 +643,7 @@ public void itPutsDeferredImportedMacroInOutputSecondPass() {
643643

644644
@Test
645645
public void itPutsDeferredFromedMacroInOutput() {
646-
expectedTemplateInterpreter.assertExpectedOutput(
646+
expectedTemplateInterpreter.assertExpectedOutputNonIdempotent(
647647
"puts-deferred-fromed-macro-in-output"
648648
);
649649
}
@@ -1597,4 +1597,11 @@ public void prepareContext(Context context) {
15971597
"keeps-meta-context-variables-through-import/test"
15981598
);
15991599
}
1600+
1601+
@Test
1602+
public void itWrapsCurrentPathAroundMacro() {
1603+
expectedTemplateInterpreter.assertExpectedOutputNonIdempotent(
1604+
"wraps-current-path-around-macro/test"
1605+
);
1606+
}
16001607
}

src/test/java/com/hubspot/jinjava/ExpectedTemplateInterpreter.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class ExpectedTemplateInterpreter {
1515
private Jinjava jinjava;
1616
private JinjavaInterpreter interpreter;
1717
private String path;
18+
private boolean sensibleCurrentPath = false;
1819

1920
public ExpectedTemplateInterpreter(
2021
Jinjava jinjava,
@@ -26,6 +27,26 @@ public ExpectedTemplateInterpreter(
2627
this.path = path;
2728
}
2829

30+
public static ExpectedTemplateInterpreter withSensibleCurrentPath(
31+
Jinjava jinjava,
32+
JinjavaInterpreter interpreter,
33+
String path
34+
) {
35+
return new ExpectedTemplateInterpreter(jinjava, interpreter, path, true);
36+
}
37+
38+
private ExpectedTemplateInterpreter(
39+
Jinjava jinjava,
40+
JinjavaInterpreter interpreter,
41+
String path,
42+
boolean sensibleCurrentPath
43+
) {
44+
this.jinjava = jinjava;
45+
this.interpreter = interpreter;
46+
this.path = path;
47+
this.sensibleCurrentPath = sensibleCurrentPath;
48+
}
49+
2950
public String assertExpectedOutput(String name) {
3051
String template = getFixtureTemplate(name);
3152
String output = JinjavaInterpreter.getCurrent().render(template);
@@ -116,6 +137,13 @@ public String assertExpectedNonEagerOutput(String name) {
116137

117138
public String getFixtureTemplate(String name) {
118139
try {
140+
if (sensibleCurrentPath) {
141+
JinjavaInterpreter
142+
.getCurrent()
143+
.getContext()
144+
.getCurrentPathStack()
145+
.push(String.format("%s/%s.jinja", path, name), 0, 0);
146+
}
119147
return Resources.toString(
120148
Resources.getResource(String.format("%s/%s.jinja", path, name)),
121149
StandardCharsets.UTF_8
@@ -127,10 +155,12 @@ public String getFixtureTemplate(String name) {
127155

128156
private String expected(String name) {
129157
try {
130-
return Resources.toString(
131-
Resources.getResource(String.format("%s/%s.expected.jinja", path, name)),
132-
StandardCharsets.UTF_8
133-
);
158+
return Resources
159+
.toString(
160+
Resources.getResource(String.format("%s/%s.expected.jinja", path, name)),
161+
StandardCharsets.UTF_8
162+
)
163+
.replaceAll("\\\\\n\\s*", "");
134164
} catch (IOException e) {
135165
throw new RuntimeException(e);
136166
}

src/test/java/com/hubspot/jinjava/FullSnippetsTest.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public String getString(
3939
JinjavaInterpreter interpreter
4040
) throws IOException {
4141
return Resources.toString(
42-
Resources.getResource(String.format("tags/macrotag/%s", fullName)),
42+
Resources.getResource(relativePathResolver.resolve(fullName, interpreter)),
4343
StandardCharsets.UTF_8
4444
);
4545
}
@@ -66,7 +66,11 @@ public Optional<LocationResolver> getLocationResolver() {
6666
);
6767
interpreter = new JinjavaInterpreter(parentInterpreter);
6868
expectedTemplateInterpreter =
69-
new ExpectedTemplateInterpreter(jinjava, interpreter, "snippets");
69+
ExpectedTemplateInterpreter.withSensibleCurrentPath(
70+
jinjava,
71+
interpreter,
72+
"snippets"
73+
);
7074
localContext = interpreter.getContext();
7175

7276
JinjavaInterpreter.pushCurrent(interpreter);
@@ -101,4 +105,11 @@ public void itUsesLowerScopeValueInMacroEvaluation() {
101105
"uses-lower-scope-value-in-macro-evaluation"
102106
);
103107
}
108+
109+
@Test
110+
public void itFromTagDoesntStealExtends() {
111+
expectedTemplateInterpreter.assertExpectedOutput(
112+
"from-tag-doesnt-steal-extends/test"
113+
);
114+
}
104115
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{% set myname = deferred + 3 %}{% set __macro_getPath_331491059_temp_variable_1__ %}Hello {{ myname }}{% endset %}{% print __macro_getPath_331491059_temp_variable_1__ %}
1+
{% set myname = deferred + 3 %}{% set __macro_getPath_331491059_temp_variable_1__ %}{% set current_path = 'simple-with-call.jinja' %}Hello {{ myname }}{% set current_path = '' %}{% endset %}{% print __macro_getPath_331491059_temp_variable_1__ %}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{% set myname = deferred + 3 %}{% set __macro_getPath_331491059_temp_variable_1__ %}Hello {{ myname }}{% endset %}{% print __macro_getPath_331491059_temp_variable_1__ %}
1+
{% set myname = deferred + 3 %}{% set __macro_getPath_331491059_temp_variable_1__ %}{% set current_path = 'simple-with-call.jinja' %}Hello {{ myname }}{% set current_path = '' %}{% endset %}{% print __macro_getPath_331491059_temp_variable_1__ %}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{% macro foo_importer() -%}
2+
{%- import "../../../eager/wraps-current-path-around-macro/dir2/imported.jinja" -%}
3+
{%- print foo -%}
4+
{%- endmacro %}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{% set foo = deferred %}

0 commit comments

Comments
 (0)