From 9510047c965df3e526918b7533d1d598be842f4c Mon Sep 17 00:00:00 2001 From: qvalentin Date: Mon, 8 Jul 2024 10:15:04 +0200 Subject: [PATCH] feat(yamlls): use glob pattern to enable yamlls for files --- README.md | 4 ++-- internal/adapter/yamlls/documentSync.go | 9 ++++++++- internal/adapter/yamlls/yamlls.go | 11 +++++------ internal/adapter/yamlls/yamlls_test.go | 18 ++++++++++++------ internal/handler/initialization.go | 7 +++++++ internal/lsp/document.go | 1 + internal/lsp/document_store.go | 12 ++++++++++++ internal/lsp/document_store_test.go | 17 +++++++++++++++++ internal/util/config.go | 22 +++++++++++++--------- 9 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 internal/lsp/document_store_test.go diff --git a/README.md b/README.md index 24dac8da..e55f959c 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ You can configure helm-ls with lsp workspace configurations. ### yaml-language-server config - **Enabled yaml-language-server**: Toggle support of this feature. -- **EnabledForFileExtensions yaml-language-server**: For wich file extensions (or suffixes) yaml-language-server should be enabled. +- **EnabledForFilesGlob**: For wich files matchig the glob pattern yaml-language-server should be enabled. - **Path to yaml-language-server**: Specify the executable location. - **Diagnostics Settings**: @@ -182,7 +182,7 @@ settings = { }, yamlls = { enabled = true, - enabledForFileExtensions = {".yaml", ".yml"}, + enabledForFilesGlob = "*.{yaml,yml}", diagnosticsLimit = 50, showDiagnosticsDirectly = false, path = "yaml-language-server", diff --git a/internal/adapter/yamlls/documentSync.go b/internal/adapter/yamlls/documentSync.go index 31c40ec7..45b0e6cc 100644 --- a/internal/adapter/yamlls/documentSync.go +++ b/internal/adapter/yamlls/documentSync.go @@ -13,10 +13,17 @@ func (yamllsConnector Connector) InitiallySyncOpenDocuments(docs []*lsplocal.Doc if yamllsConnector.server == nil { return } + for _, doc := range docs { - if !doc.IsOpen || !yamllsConnector.isRelevantFile(doc.URI) { + if !doc.IsOpen { continue } + + doc.IsYaml = lsplocal.IsYamlDocument(doc.URI, yamllsConnector.config) + if !yamllsConnector.isRelevantFile(doc.URI) { + continue + } + yamllsConnector.DocumentDidOpen(doc.Ast, lsp.DidOpenTextDocumentParams{ TextDocument: lsp.TextDocumentItem{ URI: doc.URI, diff --git a/internal/adapter/yamlls/yamlls.go b/internal/adapter/yamlls/yamlls.go index dd9442de..2d07a068 100644 --- a/internal/adapter/yamlls/yamlls.go +++ b/internal/adapter/yamlls/yamlls.go @@ -5,7 +5,6 @@ import ( "io" "os" "os/exec" - "strings" "github.com/mrjosh/helm-ls/internal/log" lsplocal "github.com/mrjosh/helm-ls/internal/lsp" @@ -79,12 +78,12 @@ func NewConnector(ctx context.Context, yamllsConfiguration util.YamllsConfigurat } func (yamllsConnector *Connector) isRelevantFile(uri lsp.URI) bool { - for _, fileExtension := range yamllsConnector.config.EnabledForFileExtensions { - if strings.HasSuffix(uri.Filename(), fileExtension) { - return true - } + doc, ok := yamllsConnector.documents.Get(uri) + if !ok { + logger.Error("Could not find document", uri) + return true } - return false + return doc.IsYaml } func (yamllsConnector *Connector) shouldRun(uri lsp.DocumentURI) bool { diff --git a/internal/adapter/yamlls/yamlls_test.go b/internal/adapter/yamlls/yamlls_test.go index feaa82c5..af0ae636 100644 --- a/internal/adapter/yamlls/yamlls_test.go +++ b/internal/adapter/yamlls/yamlls_test.go @@ -3,6 +3,7 @@ package yamlls import ( "testing" + lsplocal "github.com/mrjosh/helm-ls/internal/lsp" "github.com/mrjosh/helm-ls/internal/util" "github.com/stretchr/testify/assert" "go.lsp.dev/uri" @@ -11,19 +12,24 @@ import ( func TestIsRelevantFile(t *testing.T) { connector := Connector{ config: util.YamllsConfiguration{ - Enabled: true, - EnabledForFileExtensions: []string{".yaml", ".yml"}, + Enabled: true, }, } - assert.True(t, connector.isRelevantFile(uri.File("test.yaml"))) - assert.False(t, connector.isRelevantFile(uri.File("_helpers.tpl"))) + + connector.documents = &lsplocal.DocumentStore{} + yamlFile := uri.File("../../../testdata/example/templates/deployment.yaml") + nonYamlFile := uri.File("../../../testdata/example/templates/_helpers.tpl") + connector.documents.Store(yamlFile, util.DefaultConfig) + connector.documents.Store(nonYamlFile, util.DefaultConfig) + + assert.True(t, connector.isRelevantFile(yamlFile)) + assert.False(t, connector.isRelevantFile(nonYamlFile)) } func TestShouldRun(t *testing.T) { connector := Connector{ config: util.YamllsConfiguration{ - Enabled: true, - EnabledForFileExtensions: []string{".yaml", ".yml"}, + Enabled: true, }, } assert.False(t, connector.shouldRun(uri.File("test.yaml"))) diff --git a/internal/handler/initialization.go b/internal/handler/initialization.go index 40f3923d..67a6e8f5 100644 --- a/internal/handler/initialization.go +++ b/internal/handler/initialization.go @@ -4,6 +4,7 @@ import ( "context" "os" + "github.com/gobwas/glob" "github.com/mrjosh/helm-ls/internal/adapter/yamlls" "github.com/mrjosh/helm-ls/internal/charts" "github.com/mrjosh/helm-ls/internal/util" @@ -56,6 +57,12 @@ func (h *langHandler) Initialized(ctx context.Context, _ *lsp.InitializedParams) } func (h *langHandler) initializationWithConfig(ctx context.Context) { + globObject, err := glob.Compile(h.helmlsConfig.YamllsConfiguration.EnabledForFilesGlob) + if err != nil { + logger.Error("Error compiling glob for yamlls EnabledForFilesGlob", err) + globObject = util.DefaultConfig.YamllsConfiguration.EnabledForFilesGlobObject + } + h.helmlsConfig.YamllsConfiguration.EnabledForFilesGlobObject = globObject configureLogLevel(h.helmlsConfig) h.chartStore.SetValuesFilesConfig(h.helmlsConfig.ValuesFilesConfig) configureYamlls(ctx, h) diff --git a/internal/lsp/document.go b/internal/lsp/document.go index 70265950..f20ffbf3 100644 --- a/internal/lsp/document.go +++ b/internal/lsp/document.go @@ -21,6 +21,7 @@ type Document struct { DiagnosticsCache DiagnosticsCache IsOpen bool SymbolTable *SymbolTable + IsYaml bool } // ApplyChanges updates the content of the document from LSP textDocument/didChange events. diff --git a/internal/lsp/document_store.go b/internal/lsp/document_store.go index d7c8428d..46432e77 100644 --- a/internal/lsp/document_store.go +++ b/internal/lsp/document_store.go @@ -44,6 +44,7 @@ func (s *DocumentStore) DidOpen(params *lsp.DidOpenTextDocumentParams, helmlsCon DiagnosticsCache: NewDiagnosticsCache(helmlsConfig), IsOpen: true, SymbolTable: NewSymbolTable(ast, []byte(params.TextDocument.Text)), + IsYaml: IsYamlDocument(uri, helmlsConfig.YamllsConfiguration), } logger.Debug("Storing doc ", path) s.documents.Store(path, doc) @@ -51,6 +52,11 @@ func (s *DocumentStore) DidOpen(params *lsp.DidOpenTextDocumentParams, helmlsCon } func (s *DocumentStore) Store(uri uri.URI, helmlsConfig util.HelmlsConfiguration) error { + _, ok := s.documents.Load(uri.Filename()) + if ok { + return nil + } + content, err := os.ReadFile(uri.Filename()) if err != nil { logger.Error("Could not open file ", uri.Filename(), " ", err) @@ -67,6 +73,7 @@ func (s *DocumentStore) Store(uri uri.URI, helmlsConfig util.HelmlsConfiguration DiagnosticsCache: NewDiagnosticsCache(helmlsConfig), IsOpen: false, SymbolTable: NewSymbolTable(ast, content), + IsYaml: IsYamlDocument(uri, helmlsConfig.YamllsConfiguration), }, ) return nil @@ -75,8 +82,13 @@ func (s *DocumentStore) Store(uri uri.URI, helmlsConfig util.HelmlsConfiguration func (s *DocumentStore) Get(docuri uri.URI) (*Document, bool) { path := docuri.Filename() d, ok := s.documents.Load(path) + if !ok { return nil, false } return d.(*Document), ok } + +func IsYamlDocument(uri lsp.URI, yamllsConfiguration util.YamllsConfiguration) bool { + return yamllsConfiguration.EnabledForFilesGlobObject.Match(uri.Filename()) +} diff --git a/internal/lsp/document_store_test.go b/internal/lsp/document_store_test.go new file mode 100644 index 00000000..31ad645b --- /dev/null +++ b/internal/lsp/document_store_test.go @@ -0,0 +1,17 @@ +package lsp + +import ( + "testing" + + "github.com/mrjosh/helm-ls/internal/util" + "github.com/stretchr/testify/assert" + "go.lsp.dev/uri" +) + +func TestIsYamlDocument(t *testing.T) { + assert := assert.New(t) + assert.True(IsYamlDocument(uri.File("test.yaml"), util.DefaultConfig.YamllsConfiguration)) + assert.False(IsYamlDocument(uri.File("test.tpl"), util.DefaultConfig.YamllsConfiguration)) + assert.True(IsYamlDocument(uri.File("../../testdata/example/templates/hpa.yaml"), util.DefaultConfig.YamllsConfiguration)) + assert.False(IsYamlDocument(uri.File("../../testdata/example/templates/_helpers.tpl"), util.DefaultConfig.YamllsConfiguration)) +} diff --git a/internal/util/config.go b/internal/util/config.go index b8a782a4..18fb0c6e 100644 --- a/internal/util/config.go +++ b/internal/util/config.go @@ -1,5 +1,7 @@ package util +import "github.com/gobwas/glob" + type HelmlsConfiguration struct { YamllsConfiguration YamllsConfiguration `json:"yamlls,omitempty"` ValuesFilesConfig ValuesFilesConfig `json:"valuesFiles,omitempty"` @@ -13,9 +15,10 @@ type ValuesFilesConfig struct { } type YamllsConfiguration struct { - Enabled bool `json:"enabled,omitempty"` - EnabledForFileExtensions []string `json:"enabledForFileExtensions,omitempty"` - Path string `json:"path,omitempty"` + Enabled bool `json:"enabled,omitempty"` + EnabledForFilesGlob string `json:"enabledForFilesGlob,omitempty"` + EnabledForFilesGlobObject glob.Glob + Path string `json:"path,omitempty"` // max diagnostics from yamlls that are shown for a single file DiagnosticsLimit int `json:"diagnosticsLimit,omitempty"` // if set to false diagnostics will only be shown after saving the file @@ -33,12 +36,13 @@ var DefaultConfig = HelmlsConfiguration{ AdditionalValuesFilesGlobPattern: "values*.yaml", }, YamllsConfiguration: YamllsConfiguration{ - Enabled: true, - EnabledForFileExtensions: []string{".yaml", ".yml"}, - Path: "yaml-language-server", - DiagnosticsLimit: 50, - ShowDiagnosticsDirectly: false, - YamllsSettings: DefaultYamllsSettings, + Enabled: true, + EnabledForFilesGlob: "*.{yaml,yml}", + EnabledForFilesGlobObject: glob.MustCompile("*.{yaml,yml}"), + Path: "yaml-language-server", + DiagnosticsLimit: 50, + ShowDiagnosticsDirectly: false, + YamllsSettings: DefaultYamllsSettings, }, }