Repository: quarkusio/quarkus
Issue: Error when putting Qute include inside if/when/for

**Describe the bug**
When putting an `{include}` inside a `{for}`, `{if}`, or `{with}` (maybe others), the inclusion fails with an error.

**To Reproduce**

The following works as expected:

```
<!-- some HTML file -->
{#include includes/teaser}
    {#title}My Title{/title}
    {#content}My content{/content}
{/include}
```
```
<!-- includes/teaser.html -->
<h2>{#insert title/}</h2>
<p>{#insert content/}</p>
```
```
<!-- output -->
<h2>My Title</h2>
<p>My content</p>
```

The following...

```
<!-- some HTML file -->
{#if hello == 'world'}
    {#include includes/teaser}
        {#title}My Title{/title}
        {#content}My content{/content}
    {/include}
{/if}
```

fails with:

```
org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
	at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:381)
	at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:216)
	at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:610)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:520)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:259)
	at org.jboss.resteasy.core.SynchronousDispatcher$$Lambda$717/0000000000000000.run(Unknown Source)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:160)
	at org.jboss.resteasy.core.SynchronousDispatcher$$Lambda$718/0000000000000000.get(Unknown Source)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:163)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:245)
	at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:249)
	at io.quarkus.resteasy.runtime.ResteasyFilter$ResteasyResponseWrapper.sendError(ResteasyFilter.java:65)
	at io.undertow.servlet.handlers.DefaultServlet.doGet(DefaultServlet.java:172)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:503)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
	at io.quarkus.resteasy.runtime.ResteasyFilter.doFilter(ResteasyFilter.java:28)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:63)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:133)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:65)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:270)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:59)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:116)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:113)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$9$1$1.call(UndertowDeploymentRecorder.java:496)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:250)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:175)
	at io.undertow.server.handlers.HttpContinueReadHandler.handleRequest(HttpContinueReadHandler.java:43)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$1.handleRequest(UndertowDeploymentRecorder.java:102)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:290)
	at io.undertow.server.DefaultExchangeHandler.handle(DefaultExchangeHandler.java:18)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$6$1.run(UndertowDeploymentRecorder.java:379)
	at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:231)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2027)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1551)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1442)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at java.base/java.lang.Thread.run(Thread.java:835)
	at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: java.lang.NullPointerException
	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1693)
	at io.quarkus.qute.EngineImpl.getTemplate(EngineImpl.java:109)
	at io.quarkus.qute.IncludeSectionHelper$Factory$1.get(IncludeSectionHelper.java:54)
	at io.quarkus.qute.IncludeSectionHelper$Factory$1.get(IncludeSectionHelper.java:49)
	at io.quarkus.qute.IncludeSectionHelper.resolve(IncludeSectionHelper.java:23)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:34)
	at io.quarkus.qute.SectionNode$SectionResolutionContextImpl.execute(SectionNode.java:119)
	at io.quarkus.qute.SectionHelper$SectionResolutionContext.execute(SectionHelper.java:33)
	at io.quarkus.qute.Parser$1$1.resolve(Parser.java:80)
	at io.quarkus.qute.SectionNode.resolve(SectionNode.java:34)
	at io.quarkus.qute.TemplateImpl.renderData(TemplateImpl.java:99)
	at io.quarkus.qute.TemplateImpl.access$200(TemplateImpl.java:14)
	at io.quarkus.qute.TemplateImpl$TemplateInstanceImpl.renderAsync(TemplateImpl.java:80)
	at io.quarkus.resteasy.qute.runtime.TemplateResponseFilter.filter(TemplateResponseFilter.java:58)
	at org.jboss.resteasy.core.interception.jaxrs.ContainerResponseContextImpl.filter(ContainerResponseContextImpl.java:360)
	at org.jboss.resteasy.core.ServerResponseWriter.executeFilters(ServerResponseWriter.java:251)
	at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:101)
	at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:74)
	at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:590)
	... 58 more
```

And putting `{include}` inside a `{for}` (for example) fails with:

```
java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:248)
	at io.quarkus.runtime.Application.start(Application.java:90)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at io.quarkus.runner.bootstrap.StartupActionImpl.run(StartupActionImpl.java:99)
	at io.quarkus.dev.IsolatedDevModeMain.restartApp(IsolatedDevModeMain.java:103)
	at io.quarkus.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:138)
	at io.quarkus.vertx.http.runtime.devmode.VertxHotReplacementSetup$1.handle(VertxHotReplacementSetup.java:50)
	at io.quarkus.vertx.http.runtime.devmode.VertxHotReplacementSetup$1.handle(VertxHotReplacementSetup.java:42)
	at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$2(ContextImpl.java:316)
	at io.vertx.core.impl.ContextImpl$$Lambda$713/0000000000000000.run(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:373)
	at java.base/java.util.ArrayList.get(ArrayList.java:426)
	at io.quarkus.qute.SectionInitContextImpl.getParameters(SectionInitContextImpl.java:28)
	at io.quarkus.qute.SectionInitContextImpl.getParameter(SectionInitContextImpl.java:36)
	at io.quarkus.qute.LoopSectionHelper$Factory.initialize(LoopSectionHelper.java:125)
	at io.quarkus.qute.LoopSectionHelper$Factory.initialize(LoopSectionHelper.java:102)
	at io.quarkus.qute.SectionNode$Builder.build(SectionNode.java:88)
	at io.quarkus.qute.Parser.flushTag(Parser.java:358)
	at io.quarkus.qute.Parser.tag(Parser.java:197)
	at io.quarkus.qute.Parser.processCharacter(Parser.java:148)
	at io.quarkus.qute.Parser.parse(Parser.java:105)
	at io.quarkus.qute.EngineImpl.load(EngineImpl.java:135)
	at io.quarkus.qute.EngineImpl$$Lambda$475/0000000000000000.apply(Unknown Source)
	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
	at io.quarkus.qute.EngineImpl.getTemplate(EngineImpl.java:109)
	at io.quarkus.qute.runtime.EngineProducer.<init>(EngineProducer.java:126)
	at io.quarkus.qute.runtime.EngineProducer_Bean.create(EngineProducer_Bean.zig:382)
	at io.quarkus.qute.runtime.EngineProducer_Bean.create(EngineProducer_Bean.zig:299)
	at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:80)
	at io.quarkus.arc.impl.AbstractSharedContext$$Lambda$59/0000000000000000.apply(Unknown Source)
	at io.quarkus.arc.impl.ComputingCache$CacheFunction.lambda$apply$0(ComputingCache.java:99)
	at io.quarkus.arc.impl.ComputingCache$CacheFunction$$Lambda$468/0000000000000000.get(Unknown Source)
	at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
	at io.quarkus.arc.impl.ComputingCache.getValue(ComputingCache.java:41)
	at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:25)
	at io.quarkus.qute.runtime.EngineProducer_Bean.get(EngineProducer_Bean.zig:283)
	at io.quarkus.qute.runtime.EngineProducer_Bean.get(EngineProducer_Bean.zig:251)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:376)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:389)
	at io.quarkus.arc.impl.ArcContainerImpl.instance(ArcContainerImpl.java:249)
	at io.quarkus.qute.runtime.EngineProducer_Observer_Synthetic_5ca7449e3ab1631e7e8ed910338051c00d29a79b.notify(EngineProducer_Observer_Synthetic_5ca7449e3ab1631e7e8ed910338051c00d29a79b.zig:71)
	at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:282)
	at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:267)
	at io.quarkus.arc.impl.EventImpl.fire(EventImpl.java:69)
	at io.quarkus.arc.runtime.LifecycleEventRunner.fireStartupEvent(LifecycleEventRunner.java:23)
	at io.quarkus.arc.runtime.ArcRecorder.handleLifecycleEvents(ArcRecorder.java:113)
	at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent276.deploy_0(LifecycleEventsBuildStep$startupEvent276.zig:77)
	at io.quarkus.deployment.steps.LifecycleEventsBuildStep$startupEvent276.deploy(LifecycleEventsBuildStep$startupEvent276.zig:36)
	at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:210)
	... 16 more
```

However, if the `{include}` is empty, like in the following, there is no error (but also no way to use the include as expected):

```
{#for entry in entries}
    {#include includes/teaser}
    {/include}
{/}
```
```
<!-- output -->
<h2></h2>
<p></p>
```

Tested with Quarkus version `1.3.0.Final` and `1.3.1.Final`.


Changed files:
independent-projects/qute/core/src/main/java/io/quarkus/qute/Parser.java
independent-projects/qute/core/src/main/java/io/quarkus/qute/LoopSectionHelper.java
independent-projects/qute/core/src/test/java/io/quarkus/qute/IncludeTest.java
independent-projects/qute/core/src/main/java/io/quarkus/qute/SectionInitContextImpl.java

diff --git a/independent-projects/qute/core/src/main/java/io/quarkus/qute/LoopSectionHelper.java b/independent-projects/qute/core/src/main/java/io/quarkus/qute/LoopSectionHelper.java
index 23e146ef787..36e8526dac4 100644
--- a/independent-projects/qute/core/src/main/java/io/quarkus/qute/LoopSectionHelper.java
+++ b/independent-projects/qute/core/src/main/java/io/quarkus/qute/LoopSectionHelper.java
@@ -28,7 +28,7 @@ public class LoopSectionHelper implements SectionHelper {
     private final Expression iterable;
 
     LoopSectionHelper(String alias, Expression iterable) {
-        this.alias = alias.equals(Parameter.EMPTY) ? DEFAULT_ALIAS : alias;
+        this.alias = Parameter.EMPTY.equals(alias) ? DEFAULT_ALIAS : alias;
         this.iterable = Objects.requireNonNull(iterable);
     }
 
diff --git a/independent-projects/qute/core/src/main/java/io/quarkus/qute/Parser.java b/independent-projects/qute/core/src/main/java/io/quarkus/qute/Parser.java
index 6eef6d20bf3..7b7324a3d18 100644
--- a/independent-projects/qute/core/src/main/java/io/quarkus/qute/Parser.java
+++ b/independent-projects/qute/core/src/main/java/io/quarkus/qute/Parser.java
@@ -289,6 +289,7 @@ private void flushTag() {
                     typeInfoStack.addFirst(typeInfos);
                 }
 
+                // A new block - stop ignoring the block content
                 ignoreContent = false;
 
             } else {
@@ -345,6 +346,7 @@ private void flushTag() {
                             "section block end tag [" + name + "] does not match the start tag [" + block.getLabel() + "]");
                 }
                 section.addBlock(sectionBlockStack.pop().build());
+                // Ignore the block content until a next block starts or the current section ends
                 ignoreContent = true;
             } else {
                 // Section end
@@ -354,7 +356,11 @@ private void flushTag() {
                 }
                 section = sectionStack.pop();
                 if (!ignoreContent) {
+                    // Add the current block to the current section
                     section.addBlock(sectionBlockStack.pop().build());
+                } else {
+                    // The current section ends - stop ignoring the block content
+                    ignoreContent = false;
                 }
                 sectionBlockStack.peek().addNode(section.build());
             }
diff --git a/independent-projects/qute/core/src/main/java/io/quarkus/qute/SectionInitContextImpl.java b/independent-projects/qute/core/src/main/java/io/quarkus/qute/SectionInitContextImpl.java
index 39b512fb967..6388cf957a0 100644
--- a/independent-projects/qute/core/src/main/java/io/quarkus/qute/SectionInitContextImpl.java
+++ b/independent-projects/qute/core/src/main/java/io/quarkus/qute/SectionInitContextImpl.java
@@ -1,6 +1,7 @@
 package io.quarkus.qute;
 
 import io.quarkus.qute.SectionHelperFactory.SectionInitContext;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -25,7 +26,7 @@ public SectionInitContextImpl(EngineImpl engine, List<SectionBlock> blocks, Func
      * @return the params of the main block
      */
     public Map<String, String> getParameters() {
-        return blocks.get(0).parameters;
+        return blocks.isEmpty() ? Collections.emptyMap() : blocks.get(0).parameters;
     }
 
     public boolean hasParameter(String name) {
@@ -38,7 +39,7 @@ public String getParameter(String name) {
 
     @Override
     public Expression getExpression(String parameterName) {
-        return blocks.get(0).expressions.get(parameterName);
+        return blocks.isEmpty() ? null : blocks.get(0).expressions.get(parameterName);
     }
 
     @Override
diff --git a/independent-projects/qute/core/src/test/java/io/quarkus/qute/IncludeTest.java b/independent-projects/qute/core/src/test/java/io/quarkus/qute/IncludeTest.java
index 147cb0de2a8..88ed9c6de02 100644
--- a/independent-projects/qute/core/src/test/java/io/quarkus/qute/IncludeTest.java
+++ b/independent-projects/qute/core/src/test/java/io/quarkus/qute/IncludeTest.java
@@ -58,4 +58,22 @@ public void testOptionalBlockEndTags() {
                 engine.parse("{#include super}{#header}super header{#footer}super footer{/include}").render());
     }
 
+    @Test
+    public void testIncludeInLoop() {
+        Engine engine = Engine.builder().addDefaults().build();
+        engine.putTemplate("foo", engine.parse("{#insert snippet}empty{/insert}"));
+        assertEquals("1.2.3.4.5.",
+                engine.parse("{#for i in 5}{#include foo}{#snippet}{count}.{/snippet} this should be ingored {/include}{/for}")
+                        .render());
+    }
+
+    @Test
+    public void testIncludeInIf() {
+        Engine engine = Engine.builder().addDefaults().build();
+        engine.putTemplate("foo", engine.parse("{#insert snippet}empty{/insert}"));
+        assertEquals("1",
+                engine.parse("{#if true}{#include foo} {#snippet}1{/snippet} {/include}{/if}")
+                        .render());
+    }
+
 }