From bdc02edfa8fb3178808420f529599e5970012304 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Bj=C3=B8rn=20Erik=20Pedersen?=
 <bjorn.erik.pedersen@gmail.com>
Date: Sat, 18 Feb 2017 09:08:00 +0100
Subject: [PATCH] tplimpl: Fix issue with recursive templates

Fixes #2927
---
 tpl/tplimpl/template_ast_transformers.go      | 18 +++++++++++-----
 tpl/tplimpl/template_ast_transformers_test.go | 21 +++++++++++++++++++
 2 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/tpl/tplimpl/template_ast_transformers.go b/tpl/tplimpl/template_ast_transformers.go
index 68090497..339e2264 100644
--- a/tpl/tplimpl/template_ast_transformers.go
+++ b/tpl/tplimpl/template_ast_transformers.go
@@ -35,12 +35,21 @@ var paramsPaths = [][]string{
 }
 
 type templateContext struct {
-	decl  decl
-	templ *template.Template
+	decl    decl
+	templ   *template.Template
+	visited map[string]bool
+}
+
+func (c templateContext) getIfNotVisited(name string) *template.Template {
+	if c.visited[name] {
+		return nil
+	}
+	c.visited[name] = true
+	return c.templ.Lookup(name)
 }
 
 func newTemplateContext(templ *template.Template) *templateContext {
-	return &templateContext{templ: templ, decl: make(map[string]string)}
+	return &templateContext{templ: templ, decl: make(map[string]string), visited: make(map[string]bool)}
 
 }
 
@@ -59,7 +68,6 @@ func applyTemplateTransformers(templ *template.Template) error {
 // paramsKeysToLower is made purposely non-generic to make it not so tempting
 // to do more of these hard-to-maintain AST transformations.
 func (c *templateContext) paramsKeysToLower(n parse.Node) {
-
 	switch x := n.(type) {
 	case *parse.ListNode:
 		if x != nil {
@@ -74,7 +82,7 @@ func (c *templateContext) paramsKeysToLower(n parse.Node) {
 	case *parse.RangeNode:
 		c.paramsKeysToLowerForNodes(x.Pipe, x.List, x.ElseList)
 	case *parse.TemplateNode:
-		subTempl := c.templ.Lookup(x.Name)
+		subTempl := c.getIfNotVisited(x.Name)
 		if subTempl != nil {
 			c.paramsKeysToLowerForNodes(subTempl.Tree.Root)
 		}
diff --git a/tpl/tplimpl/template_ast_transformers_test.go b/tpl/tplimpl/template_ast_transformers_test.go
index 048d52fe..deeeae0a 100644
--- a/tpl/tplimpl/template_ast_transformers_test.go
+++ b/tpl/tplimpl/template_ast_transformers_test.go
@@ -267,3 +267,24 @@ P2: {{ .Params.LOWER }}
 	require.Contains(t, result, "P1: P1L")
 	require.Contains(t, result, "P2: P1L")
 }
+
+// Issue #2927
+func TestTransformRecursiveTemplate(t *testing.T) {
+
+	recursive := `
+{{ define "menu-nodes" }}
+{{ template "menu-node" }}
+{{ end }}
+{{ define "menu-node" }}
+{{ template "menu-node" }}
+{{ end }}
+{{ template "menu-nodes" }}
+`
+
+	templ, err := template.New("foo").Parse(recursive)
+	require.NoError(t, err)
+
+	c := newTemplateContext(templ)
+	c.paramsKeysToLower(templ.Tree.Root)
+
+}
-- 
2.30.2