mirror of https://github.com/rancher/hull.git
81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
package parse
|
|
|
|
import (
|
|
"fmt"
|
|
"text/template/parse"
|
|
)
|
|
|
|
type Node struct {
|
|
node parse.Node
|
|
parent *Node
|
|
|
|
// fieldContext is the root context to use when adding fields
|
|
// For example, in a range or with block, anything that is parsed within it
|
|
// will need to append the fieldContext before adding the field
|
|
//
|
|
// If fieldContext is an empty string, that implies that it was impossible to identify
|
|
// what the root context of this node is, so it's impossible to figure out what
|
|
// a field parsed from within this node is
|
|
//
|
|
// i.e. If you have the following template:
|
|
// {{ range (toYaml .Values.namespaces | fromYaml) }}
|
|
// {{ .data }}
|
|
// {{ end }}
|
|
//
|
|
// (toYaml .Values.namespaces | fromYaml) is considered ambiguous since we don't have
|
|
// a direct reference to a field in the built-in object, so the only thing that
|
|
// should be collected here is .Values.namespace, not .Values.namespace.data, since the
|
|
// only way you could know that (toYaml .Values.namespaces | fromYaml) is equivalent to
|
|
// .Values.namespaces is by understanding how toYaml and fromYaml manipulate the data. This
|
|
// is something that is not capable for Hull to do today.
|
|
fieldContext string
|
|
}
|
|
|
|
func (n *Node) isAmbiguous() bool {
|
|
return len(n.fieldContext) == 0
|
|
}
|
|
|
|
func (n *Node) getFieldContext(fieldContext string) string {
|
|
if n.parent == nil {
|
|
return fieldContext
|
|
}
|
|
if n.parent.isAmbiguous() {
|
|
// ambiguous parent implies ambiguous child; ignore fieldContext provided
|
|
return ""
|
|
}
|
|
if len(fieldContext) == 0 {
|
|
// ambiguous values provided
|
|
return fieldContext
|
|
}
|
|
if fieldContext == "." {
|
|
// use parent fieldContext
|
|
return n.parent.fieldContext
|
|
}
|
|
if n.parent.fieldContext == "." {
|
|
// use child fieldContext
|
|
return fieldContext
|
|
}
|
|
// parent has fieldContext and provided fieldContext is not ambiguous or ., so prepend it
|
|
return n.parent.fieldContext + fieldContext
|
|
}
|
|
|
|
func toNode(node parse.Node, parent *Node, fieldContext string) *Node {
|
|
if node == nil {
|
|
panic(fmt.Errorf("cannot convert nil node toNode"))
|
|
}
|
|
n := &Node{
|
|
node: node,
|
|
parent: parent,
|
|
}
|
|
n.fieldContext = n.getFieldContext(fieldContext)
|
|
return n
|
|
}
|
|
|
|
func toNodes(parseNodes []parse.Node, parent *Node, fieldContext string) []*Node {
|
|
nodes := make([]*Node, len(parseNodes))
|
|
for i, parseNode := range parseNodes {
|
|
nodes[i] = toNode(parseNode, parent, fieldContext)
|
|
}
|
|
return nodes
|
|
}
|