diff --git a/internal/handler/completion.go b/internal/handler/completion.go index 2407c503..b4c57f3f 100644 --- a/internal/handler/completion.go +++ b/internal/handler/completion.go @@ -22,6 +22,7 @@ func (h *langHandler) Completion(ctx context.Context, params *lsp.CompletionPara languagefeatures.NewTemplateContextFeature(genericDocumentUseCase), languagefeatures.NewFunctionCallFeature(genericDocumentUseCase), languagefeatures.NewTextFeature(ctx, genericDocumentUseCase, h.yamllsConnector, params.TextDocumentPositionParams), + languagefeatures.NewIncludesCallFeature(genericDocumentUseCase), } for _, usecase := range usecases { diff --git a/internal/language_features/includes.go b/internal/language_features/includes.go index 5a643908..656a59ad 100644 --- a/internal/language_features/includes.go +++ b/internal/language_features/includes.go @@ -7,6 +7,7 @@ import ( "github.com/mrjosh/helm-ls/internal/protocol" "github.com/mrjosh/helm-ls/internal/tree-sitter/gotemplate" "github.com/mrjosh/helm-ls/internal/util" + sitter "github.com/smacker/go-tree-sitter" ) type IncludesFeature struct { @@ -19,14 +20,29 @@ type IncludesCallFeature struct { // should be called on {{ include "name" . }} func (f *IncludesCallFeature) AppropriateForNode() bool { - if f.ParentNodeType != gotemplate.NodeTypeArgumentList { + functionCallNode := f.getFunctionCallNode() + + if functionCallNode == nil { return false } - functionCallNode := f.Node.Parent().Parent() _, err := lsplocal.ParseIncludeFunctionCall(functionCallNode, []byte(f.GenericDocumentUseCase.Document.Content)) return err == nil } +func (f *IncludesCallFeature) getFunctionCallNode() *sitter.Node { + var functionCallNode *sitter.Node + if f.ParentNodeType == gotemplate.NodeTypeArgumentList { + functionCallNode = f.Node.Parent().Parent() + } + if f.ParentNodeType == gotemplate.NodeTypeInterpretedStringLiteral { + parentParent := f.ParentNode.Parent() + if parentParent != nil && parentParent.Type() == gotemplate.NodeTypeArgumentList { + functionCallNode = parentParent.Parent() + } + } + return functionCallNode +} + type IncludesDefinitionFeature struct { *IncludesFeature } @@ -58,7 +74,7 @@ func (f *IncludesCallFeature) References() (result []lsp.Location, err error) { } func (f *IncludesCallFeature) getIncludeName() (string, error) { - functionCallNode := f.Node.Parent().Parent() + functionCallNode := f.getFunctionCallNode() return lsplocal.ParseIncludeFunctionCall(functionCallNode, []byte(f.GenericDocumentUseCase.Document.Content)) } @@ -126,3 +142,18 @@ func (f *IncludesCallFeature) Definition() (result []lsp.Location, err error) { } return f.getDefinitionLocations(includeName), nil } + +func (f *IncludesCallFeature) Completion() (*lsp.CompletionList, error) { + items := []lsp.CompletionItem{} + for _, doc := range f.GenericDocumentUseCase.DocumentStore.GetAllDocs() { + inlcudeDefinitionNames := doc.SymbolTable.GetAllIncludeDefinitionsNames() + for _, includeDefinitionName := range inlcudeDefinitionNames { + items = append(items, lsp.CompletionItem{ + InsertText: includeDefinitionName, + Kind: lsp.CompletionItemKindFunction, + Label: includeDefinitionName, + }) + } + } + return &lsp.CompletionList{IsIncomplete: false, Items: items}, nil +} diff --git a/internal/lsp/symbol_table.go b/internal/lsp/symbol_table.go index 2f3d6719..29d3a2c8 100644 --- a/internal/lsp/symbol_table.go +++ b/internal/lsp/symbol_table.go @@ -66,6 +66,13 @@ func (s *SymbolTable) GetIncludeDefinitions(symbol string) []sitter.Range { return s.includeDefinitions[symbol] } +func (s *SymbolTable) GetAllIncludeDefinitionsNames() (result []string) { + for k := range s.includeDefinitions { + result = append(result, k) + } + return result +} + func (s *SymbolTable) GetIncludeReference(symbol string) []sitter.Range { result := s.includeUseages[symbol] definitions := s.includeDefinitions[symbol]