Skip to content

Commit

Permalink
feat(completion): add variable completion
Browse files Browse the repository at this point in the history
  • Loading branch information
qvalentin committed Nov 23, 2024
1 parent 7f15ac8 commit 9e2e2d0
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 1 deletion.
1 change: 1 addition & 0 deletions internal/handler/template_handler/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func (h *TemplateHandler) Completion(ctx context.Context, params *lsp.Completion
languagefeatures.NewFunctionCallFeature(genericDocumentUseCase),
languagefeatures.NewTextFeature(ctx, genericDocumentUseCase, h.yamllsConnector, &params.TextDocumentPositionParams),
languagefeatures.NewIncludesCallFeature(genericDocumentUseCase),
languagefeatures.NewVariablesFeature(genericDocumentUseCase),
}

for _, usecase := range usecases {
Expand Down
2 changes: 2 additions & 0 deletions internal/handler/template_handler/completion_main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ func TestCompletionMainSingleLines(t *testing.T) {
notExpectedInsertTexts []string
err error
}{
{`Test completion on {{ $variable := "hello" }} {{ $v^ }}`, []string{"$variable"}, []string{".Values", "include"}, nil},
{`Test completion on {{ $variable := "hello" }} {{ $^ }}`, []string{"$variable"}, []string{".Values", "include"}, nil},
{"Test completion on {{.Bad.^}}", []string{}, []string{}, errors.New("[Bad ] is no valid template context for helm")},
{"Test completion on {{ .Bad.^ }}", []string{}, []string{}, errors.New("[Bad ] is no valid template context for helm")},
{"Test completion on {{ n^ }}", []string{"not"}, []string{}, nil},
Expand Down
7 changes: 6 additions & 1 deletion internal/language_features/variables.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package languagefeatures

import (
"github.com/mrjosh/helm-ls/internal/protocol"
"github.com/mrjosh/helm-ls/internal/tree-sitter/gotemplate"
"github.com/mrjosh/helm-ls/internal/util"
lsp "go.lsp.dev/protocol"
Expand All @@ -17,7 +18,7 @@ func NewVariablesFeature(genericDocumentUseCase *GenericDocumentUseCase) *Variab
}

func (f *VariablesFeature) AppropriateForNode() bool {
return f.NodeType == gotemplate.NodeTypeIdentifier &&
return (f.NodeType == gotemplate.NodeTypeIdentifier || f.NodeType == gotemplate.NodeTypeDollar) &&
f.ParentNodeType == gotemplate.NodeTypeVariable
}

Expand All @@ -41,3 +42,7 @@ func (f *VariablesFeature) References() (result []lsp.Location, err error) {
}
return result, nil
}

func (f *VariablesFeature) Completion() (result *lsp.CompletionList, err error) {
return protocol.CompletionResults{}.WithVariableDefinitions(f.Document.SymbolTable.GetAllVariableDefinitions()).ToList(), nil
}
10 changes: 10 additions & 0 deletions internal/lsp/symbol_table/symbol_table_variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ func (s *SymbolTable) getVariableDefinition(name string, accessRange sitter.Rang
return definition, nil
}

func (s *SymbolTable) GetAllVariableDefinitions() (result map[string][]VariableDefinition) {
result = map[string][]VariableDefinition{}
for name, definitions := range s.variableDefinitions {
result[name] = append(
[]VariableDefinition{},
definitions...)
}
return result
}

func (s *SymbolTable) GetVariableDefinitionForNode(node *sitter.Node, content []byte) (VariableDefinition, error) {
name, err := getVariableName(node, content)
if err != nil {
Expand Down
27 changes: 27 additions & 0 deletions internal/protocol/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package protocol
import (
"github.com/mrjosh/helm-ls/internal/documentation/godocs"
helmdocs "github.com/mrjosh/helm-ls/internal/documentation/helm"
symboltable "github.com/mrjosh/helm-ls/internal/lsp/symbol_table"
lsp "go.lsp.dev/protocol"
)

Expand Down Expand Up @@ -48,3 +49,29 @@ func snippetCompletionItem(gotemplateSnippet godocs.GoTemplateSnippet) lsp.Compl
InsertTextFormat: lsp.InsertTextFormatSnippet,
}
}

func (c CompletionResults) WithVariableDefinitions(variableDefinitions map[string][]symboltable.VariableDefinition) CompletionResults {
items := c.Items
for variableName, definitions := range variableDefinitions {

if len(definitions) == 0 {
continue
}
definition := definitions[0]

items = append(items,
variableCompletionItem(variableName, definition),
)
}
return CompletionResults{Items: items}
}

func variableCompletionItem(variableName string, definition symboltable.VariableDefinition) lsp.CompletionItem {
return lsp.CompletionItem{
Label: variableName,
Detail: definition.Value,
InsertText: variableName,
InsertTextFormat: lsp.InsertTextFormatPlainText,
Kind: lsp.CompletionItemKindVariable,
}
}

0 comments on commit 9e2e2d0

Please sign in to comment.