Skip to content

Commit

Permalink
Merge pull request #57 from mrjosh/feat/tests
Browse files Browse the repository at this point in the history
Fixes for completions
  • Loading branch information
qvalentin authored Jan 13, 2024
2 parents 5dbde8a + a3bab9e commit 792ceef
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 39 deletions.
8 changes: 4 additions & 4 deletions internal/adapter/yamlls/trimTemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ func prettyPrintNode(node *sitter.Node, previous []byte, result []byte) {

switch node.Type() {
case gotemplate.NodeTypeIfAction:
trim_if_action(node, previous, result)
trimIfAction(node, previous, result)
case gotemplate.NodeTypeBlockAction, gotemplate.NodeTypeWithAction, gotemplate.NodeTypeRangeAction:
trim_action(childCount, node, previous, result)
trimAction(childCount, node, previous, result)
case gotemplate.NodeTypeDefineAction:
earaseTemplate(node, previous, result)
case gotemplate.NodeTypeFunctionCall:
Expand All @@ -32,7 +32,7 @@ func prettyPrintNode(node *sitter.Node, previous []byte, result []byte) {
}
}

func trim_action(childCount uint32, node *sitter.Node, previous []byte, result []byte) {
func trimAction(childCount uint32, node *sitter.Node, previous []byte, result []byte) {
for i := 0; i < int(childCount); i++ {
child := node.Child(i)
switch child.Type() {
Expand Down Expand Up @@ -60,7 +60,7 @@ func trim_action(childCount uint32, node *sitter.Node, previous []byte, result [
}
}

func trim_if_action(node *sitter.Node, previous []byte, result []byte) {
func trimIfAction(node *sitter.Node, previous []byte, result []byte) {
curser := sitter.NewTreeCursor(node)
curser.GoToFirstChild()
for curser.GoToNextSibling() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package go_docs
package godocs

type GoTemplateSnippet struct {
Name string
Expand Down
14 changes: 7 additions & 7 deletions internal/handler/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
lsp "go.lsp.dev/protocol"
yaml "gopkg.in/yaml.v2"

"github.com/mrjosh/helm-ls/internal/documentation/go_docs"
"github.com/mrjosh/helm-ls/internal/documentation/godocs"
)

var (
Expand All @@ -30,7 +30,7 @@ func init() {
functionsCompletionItems = append(functionsCompletionItems, getFunctionCompletionItems(helmFuncs)...)
functionsCompletionItems = append(functionsCompletionItems, getFunctionCompletionItems(builtinFuncs)...)
functionsCompletionItems = append(functionsCompletionItems, getFunctionCompletionItems(sprigFuncs)...)
textCompletionsItems = append(textCompletionsItems, getTextCompletionItems(go_docs.TextSnippets)...)
textCompletionsItems = append(textCompletionsItems, getTextCompletionItems(godocs.TextSnippets)...)
}

func (h *langHandler) handleTextDocumentCompletion(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) (err error) {
Expand Down Expand Up @@ -73,7 +73,7 @@ func (h *langHandler) handleTextDocumentCompletion(ctx context.Context, reply js
variableSplitted = append(variableSplitted, s)
}

logger.Println(fmt.Sprintf("Word < %s >", word))
logger.Println(fmt.Sprintf("Word found for completions is < %s >", word))

if len(variableSplitted) == 0 {
return reply(ctx, basicItems, err)
Expand Down Expand Up @@ -122,13 +122,13 @@ func completionAstParsing(doc *lsplocal.Document, position lsp.Position) (string
)

logger.Debug("currentNode", currentNode)
logger.Debug("relevantChildNode", relevantChildNode.Type())
logger.Debug("relevantChildNode", relevantChildNode)

switch relevantChildNode.Type() {
case gotemplate.NodeTypeIdentifier:
word = relevantChildNode.Content([]byte(doc.Content))
case gotemplate.NodeTypeDot:
logger.Debug("TraverseIdentifierPathUp")
logger.Debug("TraverseIdentifierPathUp for dot node")
word = lsplocal.TraverseIdentifierPathUp(relevantChildNode, doc)
case gotemplate.NodeTypeDotSymbol:
logger.Debug("GetFieldIdentifierPath")
Expand Down Expand Up @@ -258,14 +258,14 @@ func functionCompletionItem(helmDocumentation HelmDocumentation) lsp.CompletionI
}
}

func getTextCompletionItems(gotemplateSnippet []go_docs.GoTemplateSnippet) (result []lsp.CompletionItem) {
func getTextCompletionItems(gotemplateSnippet []godocs.GoTemplateSnippet) (result []lsp.CompletionItem) {
for _, item := range gotemplateSnippet {
result = append(result, textCompletionItem(item))
}
return result
}

func textCompletionItem(gotemplateSnippet go_docs.GoTemplateSnippet) lsp.CompletionItem {
func textCompletionItem(gotemplateSnippet godocs.GoTemplateSnippet) lsp.CompletionItem {
return lsp.CompletionItem{
Label: gotemplateSnippet.Name,
TextEdit: &lsp.TextEdit{
Expand Down
8 changes: 6 additions & 2 deletions internal/lsp/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package lsp

import (
"context"
"fmt"

"github.com/mrjosh/helm-ls/internal/tree-sitter/gotemplate"
sitter "github.com/smacker/go-tree-sitter"
Expand Down Expand Up @@ -49,12 +50,12 @@ func isPointLargerOrEq(a sitter.Point, b sitter.Point) bool {

func GetFieldIdentifierPath(node *sitter.Node, doc *Document) (path string) {
path = buildFieldIdentifierPath(node, doc)
logger.Debug("buildFieldIdentifierPath:", path)
logger.Debug(fmt.Sprintf("buildFieldIdentifierPath: %s for node %s with parent %s", path, node, node.Parent()))

return path
}

func buildFieldIdentifierPath(node *sitter.Node, doc *Document) string {

prepend := node.PrevNamedSibling()

currentPath := node.Content([]byte(doc.Content))
Expand All @@ -64,6 +65,9 @@ func buildFieldIdentifierPath(node *sitter.Node, doc *Document) string {
nodeContent = ""
}
currentPath = prepend.Content([]byte(doc.Content)) + "." + nodeContent
logger.Println("Adding currentpath", currentPath)
} else if node.Parent() != nil && node.Parent().Type() == gotemplate.NodeTypeError {
return buildFieldIdentifierPath(node.Parent(), doc)
}

if currentPath[0:1] == "$" {
Expand Down
127 changes: 127 additions & 0 deletions internal/lsp/ast_field_identifier_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package lsp

import (
"testing"

sitter "github.com/smacker/go-tree-sitter"
"github.com/stretchr/testify/assert"
lsp "go.lsp.dev/protocol"
)

func TestGetFieldIdentifierPathSimple(t *testing.T) {
template := `{{ .Values.test }}`

var ast = ParseAst(template)
// (template [0, 0] - [1, 0]
// (selector_expression [0, 3] - [0, 15]
// operand: (field [0, 3] - [0, 10]
// name: (identifier [0, 4] - [0, 10]))
// field: (field_identifier [0, 11] - [0, 15]))

test_start := sitter.Point{Row: 0, Column: 12}
testNode := ast.RootNode().NamedDescendantForPointRange(test_start, test_start)

if testNode.Content([]byte(template)) != "test" {
t.Errorf("Nodes were not correctly selected")
}

doc := Document{
Content: template,
Ast: ast,
}

result := GetFieldIdentifierPath(testNode, &doc)
assert.Equal(t, ".Values.test", result)
}

func TestGetFieldIdentifierPathWith(t *testing.T) {
template := `{{ with .Values }}{{ .test }} {{ end }}`

var ast = ParseAst(template)
// (template [0, 0] - [1, 0]
// (with_action [0, 0] - [0, 39]
// condition: (field [0, 8] - [0, 15]
// name: (identifier [0, 9] - [0, 15]))
// consequence: (field [0, 21] - [0, 26]
// name: (identifier [0, 22] - [0, 26]))))

test_start := sitter.Point{Row: 0, Column: 22}
testNode := ast.RootNode().NamedDescendantForPointRange(test_start, test_start)

if testNode.Content([]byte(template)) != "test" {
t.Errorf("Nodes were not correctly selected")
}

doc := Document{
Content: template,
Ast: ast,
}

result := GetFieldIdentifierPath(testNode, &doc)
assert.Equal(t, ".Values.test", result)
}

func TestGetFieldIdentifierPathFunction(t *testing.T) {
template := `{{ and .Values.test1 .Values.test2 }}`

var ast = ParseAst(template)
// (template [0, 0] - [1, 0]
// (function_call [0, 3] - [0, 35]
// function: (identifier [0, 3] - [0, 6])
// arguments: (argument_list [0, 7] - [0, 35]
// (selector_expression [0, 7] - [0, 20]
// operand: (field [0, 7] - [0, 14]
// name: (identifier [0, 8] - [0, 14]))
// field: (field_identifier [0, 15] - [0, 20]))
// (selector_expression [0, 21] - [0, 34]
// operand: (field [0, 21] - [0, 28]
// name: (identifier [0, 22] - [0, 28]))
// field: (field_identifier [0, 29] - [0, 34])))))
//
test1_start := sitter.Point{Row: 0, Column: 16}
test2_start := sitter.Point{Row: 0, Column: 33}
test1Node := ast.RootNode().NamedDescendantForPointRange(test1_start, test1_start)
test2Node := ast.RootNode().NamedDescendantForPointRange(test2_start, test2_start)

test1NodeContent := test1Node.Content([]byte(template))
test2NodeContent := test2Node.Content([]byte(template))

assert.Equal(t, "test1", test1NodeContent, "Nodes were not correctly selected")
assert.Equal(t, "test2", test2NodeContent, "Nodes were not correctly selected")

doc := Document{
Content: template,
Ast: ast,
}

assert.Equal(t, ".Values.test1", GetFieldIdentifierPath(test1Node, &doc))
assert.Equal(t, ".Values.test2", GetFieldIdentifierPath(test2Node, &doc))
}

func TestGetFieldIdentifierPathFunctionForCompletion(t *testing.T) {
template := `{{ and .Values.image .Values. }}`
// | -> complete at dot

var ast = ParseAst(template)

var (
position = lsp.Position{Line: 0, Character: 29}
currentNode = NodeAtPosition(ast, position)
pointToLoopUp = sitter.Point{
Row: position.Line,
Column: position.Character,
}
relevantChildNode = FindRelevantChildNode(currentNode, pointToLoopUp)
)

childNodeContent := relevantChildNode.Content([]byte(template))

assert.Equal(t, ".", childNodeContent, "Nodes were not correctly selected ")

doc := Document{
Content: template,
Ast: ast,
}

assert.Equal(t, ".Values.", GetFieldIdentifierPath(relevantChildNode, &doc))
}
51 changes: 26 additions & 25 deletions internal/tree-sitter/gotemplate/node-types.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
package gotemplate

const (
NodeTypeIdentifier = "identifier"
NodeTypeVariable = "variable"
NodeTypeDot = "dot"
NodeTypeBlock = "block"
NodeTypeBlockAction = "block_action"
NodeTypeChainedPipeline = "chained_pipeline"
NodeTypeCloseBraces = "}}"
NodeTypeCloseBracesDash = "-}}"
NodeTypeComment = "comment"
NodeTypeDefine = "define"
NodeTypeDefineAction = "define_action"
NodeTypeDollar = "$"
NodeTypeDot = "dot"
NodeTypeDotSymbol = "."
NodeTypeVariableDefinition = "variable_definition"
NodeTypeRangeVariableDefinition = "range_variable_definition"
NodeTypeElse = "else"
NodeTypeElseIf = "else if"
NodeTypeEnd = "end"
NodeTypeError = "ERROR"
NodeTypeFieldIdentifier = "field_identifier"
NodeTypeText = "text"
NodeTypeTemplate = "template"
NodeTypeIfAction = "if_action"
NodeTypeFunctionCall = "function_call"
NodeTypeIdentifier = "identifier"
NodeTypeIf = "if"
NodeTypeBlockAction = "block_action"
NodeTypeWithAction = "with_action"
NodeTypeIfAction = "if_action"
NodeTypeInterpretedStringLiteral = "interpreted_string_literal"
NodeTypeOpenBraces = "{{"
NodeTypeOpenBracesDash = "{{-"
NodeTypeRange = "range"
NodeTypeRangeAction = "range_action"
NodeTypeDefineAction = "define_action"
NodeTypeFunctionCall = "function_call"
NodeTypeComment = "comment"
NodeTypeRangeVariableDefinition = "range_variable_definition"
NodeTypeSelectorExpression = "selector_expression"
NodeTypeElse = "else"
NodeTypeElseIf = "else if"
NodeTypeRange = "range"
NodeTypeTemplate = "template"
NodeTypeText = "text"
NodeTypeVariable = "variable"
NodeTypeVariableDefinition = "variable_definition"
NodeTypeWith = "with"
NodeTypeDefine = "define"
NodeTypeOpenBraces = "{{"
NodeTypeOpenBracesDash = "{{-"
NodeTypeCloseBraces = "}}"
NodeTypeCloseBracesDash = "-}}"
NodeTypeEnd = "end"
NodeTypeInterpretedStringLiteral = "interpreted_string_literal"
NodeTypeBlock = "block"
NodeTypeChainedPipeline = "chained_pipeline"
NodeTypeWithAction = "with_action"

FieldNameAlternative = "alternative"
FieldNameCondition = "condition"
Expand Down

0 comments on commit 792ceef

Please sign in to comment.