Skip to content

Commit

Permalink
feat(symbol-table): read in template context with variables
Browse files Browse the repository at this point in the history
  • Loading branch information
qvalentin committed May 19, 2024
1 parent bab4b4c commit da5d643
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 15 deletions.
28 changes: 18 additions & 10 deletions internal/handler/hover_main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package handler

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -24,6 +23,24 @@ func TestHoverMain(t *testing.T) {
expected string
expectedError error
}{
{
desc: "Test hover on template context with variables",
position: lsp.Position{
Line: 74,
Character: 50,
},
expected: "$root.Values.deployments",
expectedError: nil,
},
{
desc: "Test hover on template context with variables in range loop",
position: lsp.Position{
Line: 80,
Character: 35,
},
expected: "$config.hpa.minReplicas",
expectedError: nil,
},
{
desc: "Test hover on dot",
position: lsp.Position{
Expand Down Expand Up @@ -114,15 +131,6 @@ func TestHoverMain(t *testing.T) {
expected: fmt.Sprintf("### %s\n%s\n\n", filepath.Join("..", "..", "testdata", "example", "values.yaml"), "1"),
expectedError: nil,
},
{
desc: "Test hover on template context with variables",
position: lsp.Position{
Line: 74,
Character: 50,
},
expected: "",
expectedError: errors.New("no template context found"),
},
}
for _, tt := range testCases {
t.Run(tt.desc, func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion internal/lsp/symbol_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (t TemplateContext) Tail() TemplateContext {
}

func (t TemplateContext) IsVariable() bool {
return len(t) > 0 && t[0] == "$"
return len(t) > 0 && strings.HasPrefix(t[0], "$")
}

func (t TemplateContext) AppendSuffix(suffix string) TemplateContext {
Expand Down
15 changes: 12 additions & 3 deletions internal/lsp/symbol_table_template_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,12 @@ func (v *TemplateContextVisitor) Enter(node *sitter.Node) {
GetRangeForNode(node.Child(int(node.ChildCount())-1)))
case gotemplate.NodeTypeSelectorExpression:
operandNode := node.ChildByFieldName("operand")
if operandNode.Type() == gotemplate.NodeTypeVariable && operandNode.Content(v.content) == "$" {
if operandNode.Type() == gotemplate.NodeTypeVariable {
v.StashContext()
if operandNode.Content(v.content) != "$" {
v.symbolTable.AddTemplateContext(append(v.currentContext, operandNode.Content(v.content)), GetRangeForNode(operandNode))
v.PushContext(operandNode.Content(v.content))
}
}
}
}
Expand All @@ -77,7 +81,10 @@ func (v *TemplateContextVisitor) Exit(node *sitter.Node) {
switch node.Type() {
case gotemplate.NodeTypeSelectorExpression, gotemplate.NodeTypeUnfinishedSelectorExpression:
operandNode := node.ChildByFieldName("operand")
if operandNode.Type() == gotemplate.NodeTypeVariable && operandNode.Content(v.content) == "$" {
if operandNode.Type() == gotemplate.NodeTypeVariable {
if operandNode.Content(v.content) != "$" {
v.PopContext()
}
v.RestoreStashedContext()
}
}
Expand All @@ -97,7 +104,9 @@ func (v *TemplateContextVisitor) EnterContextShift(node *sitter.Node, suffix str
s = s.AppendSuffix(suffix)
if s.IsVariable() {
v.StashContext()
s = s.Tail()
if s[0] == "$" {
s = s.Tail()
}
}
}
v.PushContextMany(s)
Expand Down
40 changes: 40 additions & 0 deletions internal/lsp/symbol_table_template_context_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package lsp

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetContextForSelectorExpression(t *testing.T) {
testCases := []struct {
desc string
template string
nodeContent string
expected TemplateContext
}{
{
desc: "Selects single selector expression correctly",
template: `{{ .Values.test }}`,
nodeContent: ".Values.test",
expected: TemplateContext{"Values", "test"},
},
{
desc: "Selects selector expression with variable correctly",
template: `{{ $x.test }}`,
nodeContent: "$x.test",
expected: TemplateContext{"$x", "test"},
},
}
for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
ast := ParseAst(nil, tC.template)
node := ast.RootNode().Child(1)

assert.Equal(t, tC.nodeContent, node.Content([]byte(tC.template)))
result := getContextForSelectorExpression(node, []byte(tC.template))

assert.Equal(t, tC.expected, result)
})
}
}
22 changes: 22 additions & 0 deletions internal/lsp/symbol_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,28 @@ func TestSymbolTableForValuesSingleTests(t *testing.T) {
}

testCases := []testCase{
{
template: `
{{- $root := . -}}
{{- range $type, $config := $root.Values.deployments }}
{{- .InLoop }}
{{- end }}
{{ .Values.test }}
`,
path: []string{"$root", "Values"},
startPoint: sitter.Point{
Row: 2,
Column: 40,
},
},
{
template: `{{ $x := .Values }}{{ $x.test }}{{ .Values.test }}`,
path: []string{"$x", "test"},
startPoint: sitter.Point{
Row: 0,
Column: 25,
},
},
{
template: `{{ if (and .Values. ) }} {{ end }} `,
path: []string{"Values"},
Expand Down
6 changes: 5 additions & 1 deletion internal/lsp/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ func (v *Visitors) visitNodesRecursiveWithScopeShift(node *sitter.Node) {
case gotemplate.NodeTypeRangeAction:
rangeNode := node.ChildByFieldName("range")
if rangeNode == nil {
break // range is optional (e.g. {{ range $index, $element := pipeline }})
rangeNode = node.NamedChild(0).ChildByFieldName("range")
if rangeNode == nil {
logger.Error("Could not find range node")
break
}
}
v.visitNodesRecursiveWithScopeShift(rangeNode)
for _, visitor := range v.visitors {
Expand Down
1 change: 1 addition & 0 deletions testdata/example/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,6 @@ spec:
name: my-app-{{ $type }}
spec:
replicas: {{ $config.hpa.minReplicas }}
{{ $.Values.ingress.hosts }}
---
{{- end }}

0 comments on commit da5d643

Please sign in to comment.