From b60d3d0ba0601e9ab047fe1f58c48d9d6fbdc223 Mon Sep 17 00:00:00 2001 From: qvalentin Date: Sun, 14 Jan 2024 14:01:23 +0100 Subject: [PATCH] feat(completion): completion for multiple values files --- internal/handler/completion.go | 15 ++++++- internal/handler/completion_values_test.go | 38 ++++++++++++++++ internal/handler/hover.go | 7 +-- internal/handler/hover_test.go | 51 ++++++++++++++++++++++ 4 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 internal/handler/hover_test.go diff --git a/internal/handler/completion.go b/internal/handler/completion.go index bce97f80..cd1172d1 100644 --- a/internal/handler/completion.go +++ b/internal/handler/completion.go @@ -9,6 +9,7 @@ import ( "strings" + "github.com/mrjosh/helm-ls/internal/charts" lsplocal "github.com/mrjosh/helm-ls/internal/lsp" gotemplate "github.com/mrjosh/helm-ls/internal/tree-sitter/gotemplate" "github.com/mrjosh/helm-ls/pkg/chartutil" @@ -48,6 +49,10 @@ func (h *langHandler) handleTextDocumentCompletion(ctx context.Context, reply js if !ok { return errors.New("Could not get document: " + params.TextDocument.URI.Filename()) } + chart, err := h.chartStore.GetChartForDoc(params.TextDocument.URI) + if err != nil { + logger.Error("Error getting chart info for file", params.TextDocument.URI, err) + } word, isTextNode := completionAstParsing(doc, params.Position) @@ -89,7 +94,7 @@ func (h *langHandler) handleTextDocumentCompletion(ctx context.Context, reply js case "Chart": items = getVariableCompletionItems(chartVals) case "Values": - items = h.getValue(h.values, variableSplitted[1:]) + items = h.getValuesCompletions(chart, variableSplitted[1:]) case "Release": items = getVariableCompletionItems(releaseVals) case "Files": @@ -139,8 +144,14 @@ func completionAstParsing(doc *lsplocal.Document, position lsp.Position) (string return word, false } -func (h *langHandler) getValue(values chartutil.Values, splittedVar []string) []lsp.CompletionItem { +func (h *langHandler) getValuesCompletions(chart *charts.Chart, splittedVar []string) (result []lsp.CompletionItem) { + for _, valuesFile := range chart.ValuesFiles.AllValuesFiles() { + result = append(result, h.getValue(valuesFile.Values, splittedVar)...) + } + return result +} +func (h *langHandler) getValue(values chartutil.Values, splittedVar []string) []lsp.CompletionItem { var ( err error tableName = strings.Join(splittedVar, ".") diff --git a/internal/handler/completion_values_test.go b/internal/handler/completion_values_test.go index e7df2152..4c10a96f 100644 --- a/internal/handler/completion_values_test.go +++ b/internal/handler/completion_values_test.go @@ -3,8 +3,11 @@ package handler import ( "testing" + "github.com/mrjosh/helm-ls/internal/charts" lsplocal "github.com/mrjosh/helm-ls/internal/lsp" + "github.com/stretchr/testify/assert" "go.lsp.dev/protocol" + "gopkg.in/yaml.v3" ) func TestEmptyValues(t *testing.T) { @@ -104,3 +107,38 @@ func TestCompletionAstParsing(t *testing.T) { } } +func TestGetValuesCompletions(t *testing.T) { + handler := &langHandler{ + linterName: "helm-lint", + connPool: nil, + documents: nil, + values: make(map[string]interface{}), + } + var nested = map[string]interface{}{"nested": "value"} + var valuesMain = map[string]interface{}{"global": nested} + var valuesAdditional = map[string]interface{}{"glob": nested} + chart := &charts.Chart{ + ValuesFiles: &charts.ValuesFiles{ + MainValuesFile: &charts.ValuesFile{ + Values: valuesMain, + ValueNode: yaml.Node{}, + URI: "", + }, + AdditionalValuesFiles: []*charts.ValuesFile{ + { + Values: valuesAdditional, + ValueNode: yaml.Node{}, + URI: "", + }, + }, + }, + RootURI: "", + } + + result := handler.getValuesCompletions(chart, []string{"g"}) + + assert.Equal(t, 2, len(result)) + + result = handler.getValuesCompletions(chart, []string{"something", "different"}) + assert.Empty(t, result) +} diff --git a/internal/handler/hover.go b/internal/handler/hover.go index 191facbe..ba8a420e 100644 --- a/internal/handler/hover.go +++ b/internal/handler/hover.go @@ -8,6 +8,7 @@ import ( "reflect" "strings" + "github.com/mrjosh/helm-ls/internal/charts" lspinternal "github.com/mrjosh/helm-ls/internal/lsp" "github.com/mrjosh/helm-ls/internal/util" @@ -95,7 +96,7 @@ func (h *langHandler) handleHover(ctx context.Context, reply jsonrpc2.Replier, r if len(variableSplitted) > 1 { switch variableSplitted[0] { case "Values": - value, err = h.getValueHover(variableSplitted[1:]) + value, err = h.getValueHover(chart, variableSplitted[1:]) case "Chart": value, err = h.getChartMetadataHover(&chart.ChartMetadata.Metadata, variableSplitted[1]) case "Release": @@ -149,9 +150,9 @@ func (h *langHandler) getChartMetadataHover(metadata *chart.Metadata, key string return "", fmt.Errorf("%s was no known Chart Metadata property", key) } -func (h *langHandler) getValueHover(splittedVar []string) (string, error) { +func (h *langHandler) getValueHover(chart *charts.Chart, splittedVar []string) (string, error) { var ( - values = h.values + values = chart.ValuesFiles.MainValuesFile.Values tableName = strings.Join(splittedVar, ".") err error localValues chartutil.Values diff --git a/internal/handler/hover_test.go b/internal/handler/hover_test.go new file mode 100644 index 00000000..dbf7b222 --- /dev/null +++ b/internal/handler/hover_test.go @@ -0,0 +1,51 @@ +package handler + +import ( + "testing" + + "github.com/mrjosh/helm-ls/internal/charts" +) + +func Test_langHandler_getValueHover(t *testing.T) { + type args struct { + chart *charts.Chart + splittedVar []string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "test", + args: args{ + chart: &charts.Chart{ + ValuesFiles: &charts.ValuesFiles{ + MainValuesFile: &charts.ValuesFile{ + Values: map[string]interface{}{ + "key": "value", + }, + }, + }, + }, + splittedVar: []string{"key"}, + }, + want: "value", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + h := &langHandler{} + got, err := h.getValueHover(tt.args.chart, tt.args.splittedVar) + if (err != nil) != tt.wantErr { + t.Errorf("langHandler.getValueHover() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("langHandler.getValueHover() = %v, want %v", got, tt.want) + } + }) + } +}