Skip to content

Commit

Permalink
hover finished
Browse files Browse the repository at this point in the history
  • Loading branch information
qvalentin committed Apr 14, 2024
1 parent 388d686 commit 6341043
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 82 deletions.
17 changes: 17 additions & 0 deletions internal/documentation/helm/helm-documentation.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package helmdocs

import "github.com/mrjosh/helm-ls/internal/util"

type HelmDocumentation struct {
Name string
Detail string
Expand Down Expand Up @@ -253,3 +255,18 @@ var (
"Template": TemplateVals,
}
)

func GetFunctionByName(name string) (HelmDocumentation, bool) {
completionItems := [][]HelmDocumentation{
BuiltinFuncs,
SprigFuncs,
HelmFuncs,
}
toSearch := util.ConcatMultipleSlices(completionItems)
for _, completionItem := range toSearch {
if name == completionItem.Name {
return completionItem, true
}
}
return HelmDocumentation{}, false
}
82 changes: 5 additions & 77 deletions internal/handler/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ package handler

import (
"context"
"errors"
"fmt"
"strings"

helmdocs "github.com/mrjosh/helm-ls/internal/documentation/helm"
languagefeatures "github.com/mrjosh/helm-ls/internal/language_features"
lspinternal "github.com/mrjosh/helm-ls/internal/lsp"
"github.com/mrjosh/helm-ls/internal/tree-sitter/gotemplate"
Expand All @@ -20,23 +16,14 @@ func (h *langHandler) Hover(ctx context.Context, params *lsp.HoverParams) (resul
if err != nil {
return nil, err
}
doc := genericDocumentUseCase.Document

var (
currentNode = lspinternal.NodeAtPosition(doc.Ast, params.Position)
parent = currentNode.Parent()
wordRange = lspinternal.GetLspRangeForNode(currentNode)
word string
)

if parent == nil {
err = errors.New("Could not parse ast correctly")
return nil, err
}
wordRange := lspinternal.GetLspRangeForNode(genericDocumentUseCase.Node)

usecases := []languagefeatures.HoverUseCase{
languagefeatures.NewBuiltInObjectsFeature(genericDocumentUseCase), // has to be before template context
languagefeatures.NewTemplateContextFeature(genericDocumentUseCase),
languagefeatures.NewIncludesCallFeature(genericDocumentUseCase),
languagefeatures.NewFunctionCallFeature(genericDocumentUseCase),
}

for _, usecase := range usecases {
Expand All @@ -46,73 +33,14 @@ func (h *langHandler) Hover(ctx context.Context, params *lsp.HoverParams) (resul
}
}

pt := parent.Type()
ct := currentNode.Type()
if ct == gotemplate.NodeTypeText {
word := doc.WordAt(params.Position)
if genericDocumentUseCase.NodeType == gotemplate.NodeTypeText {
word := genericDocumentUseCase.Document.WordAt(params.Position)
if len(word) > 2 && string(word[len(word)-1]) == ":" {
word = word[0 : len(word)-1]
}
response, err := h.yamllsConnector.CallHover(ctx, *params, word)
return response, err
}
if pt == gotemplate.NodeTypeFunctionCall && ct == gotemplate.NodeTypeIdentifier {
word = currentNode.Content([]byte(doc.Content))
}
if pt == gotemplate.NodeTypeArgumentList && ct == gotemplate.NodeTypeInterpretedStringLiteral {
includesCallFeature := languagefeatures.NewIncludesCallFeature(genericDocumentUseCase)
response, err := includesCallFeature.Hover()
return util.BuildHoverResponse(response, wordRange), err
}

var (
splitted = strings.Split(word, ".")
variableSplitted = []string{}
value string
)

if word == "" {
return nil, err
}

for _, s := range splitted {
if s != "" {
variableSplitted = append(variableSplitted, s)
}
}

// // $ always points to the root context so we must remove it before looking up tables
if variableSplitted[0] == "$" && len(variableSplitted) > 1 {
variableSplitted = variableSplitted[1:]
}

logger.Println(fmt.Sprintf("Hover checking for word < %s >", word))

if len(variableSplitted) > 1 {
if err == nil {
if value == "" {
value = "\"\""
}
result := util.BuildHoverResponse(value, wordRange)
return result, err
}
return nil, err
}

searchWord := variableSplitted[0]
completionItems := [][]helmdocs.HelmDocumentation{
helmdocs.BuiltinFuncs,
helmdocs.SprigFuncs,
helmdocs.HelmFuncs,
}
toSearch := util.ConcatMultipleSlices(completionItems)

logger.Println("Start search with word " + searchWord)
for _, completionItem := range toSearch {
if searchWord == completionItem.Name {
result := util.BuildHoverResponse(fmt.Sprint(completionItem.Doc), wordRange)
return result, err
}
}
return nil, err
}
11 changes: 10 additions & 1 deletion internal/handler/hover_main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestHoverMain(t *testing.T) {
Line: 7,
Character: 10,
},
expected: "negate the boolean value of $x",
expected: "not $x\n\nnegate the boolean value of $x",
expectedError: nil,
},
{
Expand Down Expand Up @@ -77,6 +77,15 @@ func TestHoverMain(t *testing.T) {
expected: "Returns a list of files whose names match the given shell glob pattern.",
expectedError: nil,
},
{
desc: "Test hover on .Files",
position: lsp.Position{
Line: 68,
Character: 20,
},
expected: "access non-template files within the chart",
expectedError: nil,
},
{
desc: "Test hover on yaml text",
position: lsp.Position{
Expand Down
8 changes: 6 additions & 2 deletions internal/language_features/built_in_objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ func NewBuiltInObjectsFeature(genericDocumentUseCase *GenericDocumentUseCase) *B
}

func (f *BuiltInObjectsFeature) AppropriateForNode(currentNodeType string, parentNodeType string, node *sitter.Node) bool {
if !(parentNodeType == gotemplate.NodeTypeField && currentNodeType == gotemplate.NodeTypeIdentifier) && currentNodeType != gotemplate.NodeTypeDot && currentNodeType != gotemplate.NodeTypeDotSymbol {
if !(parentNodeType == gotemplate.NodeTypeField && currentNodeType == gotemplate.NodeTypeIdentifier) &&
currentNodeType != gotemplate.NodeTypeIdentifier &&
currentNodeType != gotemplate.NodeTypeFieldIdentifier &&
currentNodeType != gotemplate.NodeTypeDot &&
currentNodeType != gotemplate.NodeTypeDotSymbol {
return false
}

allowedBuiltIns := []string{"Chart", "Values"}
allowedBuiltIns := []string{"Chart", "Values", "Files", "Template", "Release"}

templateContext, _ := f.getTemplateContext()
if len(templateContext) != 1 {
Expand Down
31 changes: 31 additions & 0 deletions internal/language_features/function_call.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package languagefeatures

import (
"fmt"

helmdocs "github.com/mrjosh/helm-ls/internal/documentation/helm"
"github.com/mrjosh/helm-ls/internal/tree-sitter/gotemplate"
sitter "github.com/smacker/go-tree-sitter"
)

type FunctionCallFeature struct {
*GenericDocumentUseCase
}

func NewFunctionCallFeature(genericDocumentUseCase *GenericDocumentUseCase) *FunctionCallFeature {
return &FunctionCallFeature{
GenericDocumentUseCase: genericDocumentUseCase,
}
}

func (f *FunctionCallFeature) AppropriateForNode(currentNodeType string, parentNodeType string, node *sitter.Node) bool {
return currentNodeType == gotemplate.NodeTypeIdentifier && parentNodeType == gotemplate.NodeTypeFunctionCall
}

func (f *FunctionCallFeature) Hover() (string, error) {
documentation, ok := helmdocs.GetFunctionByName(f.NodeContent())
if !ok {
return "", fmt.Errorf("could not find documentation for function %s", f.NodeContent())
}
return fmt.Sprintf("%s\n\n%s", documentation.Detail, documentation.Doc), nil
}
4 changes: 2 additions & 2 deletions internal/lsp/symbol_table_includes.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ func ParseIncludeFunctionCall(node *sitter.Node, content []byte) (string, error)
return "", fmt.Errorf("node is not a function call")
}
functionName := node.ChildByFieldName("function").Content(content)
if functionName != "include" {
return "", fmt.Errorf("function name is not include")
if functionName != "include" && functionName != "template" { // template is not documented but was seen in the wild
return "", fmt.Errorf("function name is not include or template")
}
arguments := node.ChildByFieldName("arguments")
if arguments == nil || arguments.ChildCount() == 0 {
Expand Down

0 comments on commit 6341043

Please sign in to comment.