From 0a444cef9568bace1db2597e5fab0b700ae43991 Mon Sep 17 00:00:00 2001 From: qvalentin Date: Tue, 19 Nov 2024 09:06:08 +0100 Subject: [PATCH] wip: integra test --- .../yamlls/completion_integration_test.go | 2 +- ...ew_client.go => custom_schema_provider.go} | 2 +- ...custom_schema_provider_integration_test.go | 79 +++++++++++++++++++ .../yamlls/diagnostics_integration_test.go | 4 +- .../adapter/yamlls/hover_integration_test.go | 2 +- internal/adapter/yamlls/initization.go | 2 - .../adapter/yamlls/integration_test_utils.go | 4 +- .../adapter/yamlls/symbol_integration_test.go | 2 +- internal/adapter/yamlls/yamlls.go | 4 +- internal/charts/chart_for_document.go | 19 ++++- internal/charts/chart_for_document_test.go | 30 +++++++ .../handler/template_handler/configure.go | 2 +- internal/handler/yaml_handler/configure.go | 2 +- internal/handler/yaml_handler/yaml_handler.go | 39 +-------- internal/json_schema/json_schema.go | 22 ------ 15 files changed, 140 insertions(+), 75 deletions(-) rename internal/adapter/yamlls/{custom_new_client.go => custom_schema_provider.go} (96%) create mode 100644 internal/adapter/yamlls/custom_schema_provider_integration_test.go diff --git a/internal/adapter/yamlls/completion_integration_test.go b/internal/adapter/yamlls/completion_integration_test.go index 3e3687b4..6db8b42c 100644 --- a/internal/adapter/yamlls/completion_integration_test.go +++ b/internal/adapter/yamlls/completion_integration_test.go @@ -68,7 +68,7 @@ func TestYamllsCompletionIntegration(t *testing.T) { tt := tt1 t.Run(tt.desc, func(t *testing.T) { t.Parallel() - yamllsConnector, documents, _ := getYamlLsConnector(t, config) + yamllsConnector, documents, _ := getYamlLsConnector(t, config, &DefaultCustomHandler) openFile(t, documents, tt.file, yamllsConnector) assert.EventuallyWithT(t, func(c *assert.CollectT) { diff --git a/internal/adapter/yamlls/custom_new_client.go b/internal/adapter/yamlls/custom_schema_provider.go similarity index 96% rename from internal/adapter/yamlls/custom_new_client.go rename to internal/adapter/yamlls/custom_schema_provider.go index 97146c00..b4aaad23 100644 --- a/internal/adapter/yamlls/custom_new_client.go +++ b/internal/adapter/yamlls/custom_schema_provider.go @@ -52,7 +52,7 @@ func NewCustomSchemaProviderHandler(provider CustomSchemaProvider) jsonrpc2.Hand return reply(ctx, nil, nil) } - logger.Println("YamlHandler: custom/schema/request", req.Params()) + logger.Println("YamlHandler: custom/schema/request", string(req.Params())) if len(params) == 0 { return reply(ctx, nil, nil) diff --git a/internal/adapter/yamlls/custom_schema_provider_integration_test.go b/internal/adapter/yamlls/custom_schema_provider_integration_test.go new file mode 100644 index 00000000..fa1361be --- /dev/null +++ b/internal/adapter/yamlls/custom_schema_provider_integration_test.go @@ -0,0 +1,79 @@ +//go:build integration + +package yamlls + +import ( + "context" + "os" + "path" + "testing" + "time" + + "github.com/mrjosh/helm-ls/internal/util" + "github.com/stretchr/testify/assert" + lsp "go.lsp.dev/protocol" + "go.lsp.dev/uri" +) + +var TEST_JSON_SCHEMA = ` +{ + "$id": "https://example.com/address.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "An address similar to http://microformats.org/wiki/h-card", + "type": "object", + "properties": { + "postOfficeBox": { + "type": "string" + }, + "countryName": { + "type": "string" + } + } +} +` + +func TestYamllsCustomSchemaProviderIntegration(t *testing.T) { + config := util.DefaultConfig.YamllsConfiguration + config.Path = "yamlls-debug.sh" + + // tempDir := t.TempDir() + tempDir := "/data/data/com.termux/files/usr/tmp/" + schemaFile := path.Join(tempDir, "schema.json") + // write schema + err := os.WriteFile(schemaFile, []byte(TEST_JSON_SCHEMA), 0o644) + assert.NoError(t, err) + + testFile := path.Join(tempDir, "test.yaml") + err = os.WriteFile(testFile, []byte("c"), 0o644) + assert.NoError(t, err) + + customHandler := NewCustomSchemaHandler( + NewCustomSchemaProviderHandler( + func(ctx context.Context, URI uri.URI) (uri.URI, error) { + t.Log("Calling Schema provider") + return "http://localhost:8000/schema.json", nil + })) + + yamllsConnector, documents, _ := getYamlLsConnector(t, config, customHandler) + openFile(t, documents, testFile, yamllsConnector) + + assert.EventuallyWithT(t, func(c *assert.CollectT) { + result, _ := yamllsConnector.CallCompletion(context.Background(), &lsp.CompletionParams{ + TextDocumentPositionParams: lsp.TextDocumentPositionParams{ + TextDocument: lsp.TextDocumentIdentifier{ + URI: uri.File(testFile), + }, + Position: lsp.Position{ + Line: 0, + Character: 1, + }, + }, + }) + assert.NotNil(c, result) + if result == nil { + t.Log("result is nil") + return + } + t.Log("reuslt is", result) + }, time.Second*20, time.Second*2) +} diff --git a/internal/adapter/yamlls/diagnostics_integration_test.go b/internal/adapter/yamlls/diagnostics_integration_test.go index 65237db0..8e9cc3c1 100644 --- a/internal/adapter/yamlls/diagnostics_integration_test.go +++ b/internal/adapter/yamlls/diagnostics_integration_test.go @@ -79,7 +79,7 @@ func TestYamllsDiagnosticsIntegration(t *testing.T) { Enable: false, } config.YamllsSettings = yamllsSettings - yamllsConnector, documents, diagnosticsChan := getYamlLsConnector(t, config) + yamllsConnector, documents, diagnosticsChan := getYamlLsConnector(t, config, &DefaultCustomHandler) didOpenChan := make(chan string) go readTestFiles(TEST_DATA_DIR, didOpenChan, doneReadingFilesChan) @@ -119,7 +119,7 @@ func TestYamllsDiagnosticsIntegrationWithSchema(t *testing.T) { diagnosticsChan := make(chan lsp.PublishDiagnosticsParams) config := util.DefaultConfig.YamllsConfiguration - yamllsConnector, documents, diagnosticsChan := getYamlLsConnector(t, config) + yamllsConnector, documents, diagnosticsChan := getYamlLsConnector(t, config, &DefaultCustomHandler) file := filepath.Join("..", "..", "..", "testdata", "example", "templates", "service.yaml") openFile(t, documents, file, yamllsConnector) diff --git a/internal/adapter/yamlls/hover_integration_test.go b/internal/adapter/yamlls/hover_integration_test.go index 2cc474e5..2ae04420 100644 --- a/internal/adapter/yamlls/hover_integration_test.go +++ b/internal/adapter/yamlls/hover_integration_test.go @@ -60,7 +60,7 @@ func TestYamllsHoverIntegration(t *testing.T) { tt := tt1 t.Run(tt.desc, func(t *testing.T) { t.Parallel() - yamllsConnector, documents, _ := getYamlLsConnector(t, config) + yamllsConnector, documents, _ := getYamlLsConnector(t, config, &DefaultCustomHandler) openFile(t, documents, tt.file, yamllsConnector) assert.Eventually(t, func() bool { diff --git a/internal/adapter/yamlls/initization.go b/internal/adapter/yamlls/initization.go index 23c1e8c8..db1afc7c 100644 --- a/internal/adapter/yamlls/initization.go +++ b/internal/adapter/yamlls/initization.go @@ -37,8 +37,6 @@ func (yamllsConnector Connector) CallInitialize(ctx context.Context, workspaceUR return err } - yamllsConnector.customHandler.PostInitialize(ctx, yamllsConnector.conn) - defer func() { yamllsConnector.customHandler.PostInitialize(ctx, yamllsConnector.conn) }() diff --git a/internal/adapter/yamlls/integration_test_utils.go b/internal/adapter/yamlls/integration_test_utils.go index fe677465..56c6ff83 100644 --- a/internal/adapter/yamlls/integration_test_utils.go +++ b/internal/adapter/yamlls/integration_test_utils.go @@ -47,7 +47,7 @@ func (proc readWriteCloseMock) Close() error { return nil } -func getYamlLsConnector(t *testing.T, config util.YamllsConfiguration) (*Connector, *document.DocumentStore, chan lsp.PublishDiagnosticsParams) { +func getYamlLsConnector(t *testing.T, config util.YamllsConfiguration, customHandler *CustomHandler) (*Connector, *document.DocumentStore, chan lsp.PublishDiagnosticsParams) { dir := t.TempDir() documents := document.NewDocumentStore() diagnosticsChan := make(chan lsp.PublishDiagnosticsParams) @@ -55,7 +55,7 @@ func getYamlLsConnector(t *testing.T, config util.YamllsConfiguration) (*Connect zapLogger, _ := zap.NewProduction() client := protocol.ClientDispatcher(con, zapLogger) - yamllsConnector := NewConnector(context.Background(), config, client, documents, DefaultCustomHandler) + yamllsConnector := NewConnector(context.Background(), config, client, documents, customHandler) if yamllsConnector.server == nil { t.Fatal("Could not connect to yaml-language-server") diff --git a/internal/adapter/yamlls/symbol_integration_test.go b/internal/adapter/yamlls/symbol_integration_test.go index ded8cd44..a6ee4a94 100644 --- a/internal/adapter/yamlls/symbol_integration_test.go +++ b/internal/adapter/yamlls/symbol_integration_test.go @@ -37,7 +37,7 @@ func TestYamllsDocumentSymoblIntegration(t *testing.T) { tt := tt1 t.Run(tt.file, func(t *testing.T) { t.Parallel() - yamllsConnector, documents, _ := getYamlLsConnector(t, config) + yamllsConnector, documents, _ := getYamlLsConnector(t, config, &DefaultCustomHandler) openFile(t, documents, tt.file, yamllsConnector) assert.EventuallyWithT(t, func(c *assert.CollectT) { diff --git a/internal/adapter/yamlls/yamlls.go b/internal/adapter/yamlls/yamlls.go index ff92042d..9fc21bf1 100644 --- a/internal/adapter/yamlls/yamlls.go +++ b/internal/adapter/yamlls/yamlls.go @@ -24,7 +24,7 @@ type Connector struct { conn jsonrpc2.Conn documents *document.DocumentStore client protocol.Client - customHandler CustomHandler + customHandler *CustomHandler EnabledForFilesGlobObject glob.Glob } @@ -32,7 +32,7 @@ func NewConnector(ctx context.Context, yamllsConfiguration util.YamllsConfiguration, client protocol.Client, documents *document.DocumentStore, - customHandler CustomHandler, + customHandler *CustomHandler, ) *Connector { yamllsCmd := exec.Command(yamllsConfiguration.Path, "--stdio") diff --git a/internal/charts/chart_for_document.go b/internal/charts/chart_for_document.go index 207ea6f1..544d5448 100644 --- a/internal/charts/chart_for_document.go +++ b/internal/charts/chart_for_document.go @@ -3,6 +3,7 @@ package charts import ( "fmt" "os" + "path" "path/filepath" "strings" @@ -17,7 +18,10 @@ func (s *ChartStore) GetChartForDoc(uri lsp.DocumentURI) (*Chart, error) { return chart, nil } - chart, err := s.getChartFromFilesystemForTemplates(uri.Filename()) + chart, err := s.getChartFromFilesystemForNonTemplates(uri.Filename()) + if err != nil { + chart, err = s.getChartFromFilesystemForTemplates(uri.Filename()) + } if err != nil { return chart, ErrChartNotFound{ URI: uri, @@ -46,13 +50,26 @@ func (s *ChartStore) GetChartOrParentForDoc(uri lsp.DocumentURI) (*Chart, error) func (s *ChartStore) getChartFromCache(uri lsp.DocumentURI) *Chart { for chartURI, chart := range s.Charts { + // template files if strings.HasPrefix(uri.Filename(), filepath.Join(chartURI.Filename(), "template")) { return chart } + // values.yaml files etc. + if path.Dir(uri.Filename()) == chartURI.Filename() { + return chart + } } return nil } +func (s *ChartStore) getChartFromFilesystemForNonTemplates(path string) (*Chart, error) { + directory := filepath.Dir(path) + if isChartDirectory(directory) { + return s.newChart(uri.File(directory), s.valuesFilesConfig), nil + } + return nil, ErrChartNotFound{} +} + func (s *ChartStore) getChartFromFilesystemForTemplates(path string) (*Chart, error) { directory := filepath.Dir(path) if filepath.Base(directory) == "templates" { diff --git a/internal/charts/chart_for_document_test.go b/internal/charts/chart_for_document_test.go index 0aa6f294..953713c7 100644 --- a/internal/charts/chart_for_document_test.go +++ b/internal/charts/chart_for_document_test.go @@ -155,3 +155,33 @@ func TestGetChartForDocumentWorksForChartWithDependencies(t *testing.T) { assert.NotNil(t, chartStore.Charts[uri.File(filepath.Join(rootDir, "charts", "subchartexample"))]) assert.NotNil(t, chartStore.Charts[uri.File(filepath.Join(rootDir, "charts", charts.DependencyCacheFolder, "common"))]) } + +func TestGetChartForDocumentWorksForValuesFile(t *testing.T) { + var ( + rootDir = "../../testdata/dependenciesExample/" + chartStore = charts.NewChartStore(uri.File(rootDir), charts.NewChart, addChartCallback) + ) + + result1, error := chartStore.GetChartForDoc(uri.File(filepath.Join(rootDir, "values.yaml"))) + assert.NoError(t, error) + + assert.Len(t, result1.HelmChart.Dependencies(), 2) + assert.Len(t, chartStore.Charts, 3) + + assert.NotNil(t, chartStore.Charts[uri.File(rootDir)]) +} + +func TestGetChartForDocumentWorksForValuesFileWithCache(t *testing.T) { + var ( + rootDir = "../../testdata/dependenciesExample/" + chartStore = charts.NewChartStore(uri.File(rootDir), charts.NewChart, addChartCallback) + ) + + result1, error := chartStore.GetChartForDoc(uri.File(filepath.Join(rootDir, "values.yaml"))) + assert.NoError(t, error) + assert.NotNil(t, chartStore.Charts[uri.File(rootDir)]) + + result2, error := chartStore.GetChartForDoc(uri.File(filepath.Join(rootDir, "values.yaml"))) + + assert.Same(t, result1, result2) +} diff --git a/internal/handler/template_handler/configure.go b/internal/handler/template_handler/configure.go index 665e0008..53aeb787 100644 --- a/internal/handler/template_handler/configure.go +++ b/internal/handler/template_handler/configure.go @@ -25,7 +25,7 @@ func (h *TemplateHandler) configureYamlls(ctx context.Context, helmlsConfig util config := helmlsConfig if config.YamllsConfiguration.Enabled { h.configureYamlsEnabledGlob(helmlsConfig) - h.setYamllsConnector(yamlls.NewConnector(ctx, config.YamllsConfiguration, h.client, h.documents, yamlls.DefaultCustomHandler)) + h.setYamllsConnector(yamlls.NewConnector(ctx, config.YamllsConfiguration, h.client, h.documents, &yamlls.DefaultCustomHandler)) err := h.yamllsConnector.CallInitialize(ctx, h.chartStore.RootURI) if err != nil { logger.Error("Error initializing yamlls", err) diff --git a/internal/handler/yaml_handler/configure.go b/internal/handler/yaml_handler/configure.go index 67dec0ab..4b3be8ba 100644 --- a/internal/handler/yaml_handler/configure.go +++ b/internal/handler/yaml_handler/configure.go @@ -18,7 +18,7 @@ func (h *YamlHandler) configureYamlls(ctx context.Context, helmlsConfig util.Hel config.YamllsConfiguration, h.client, h.documents, - *yamlls.NewCustomSchemaHandler( + yamlls.NewCustomSchemaHandler( yamlls.NewCustomSchemaProviderHandler(h.CustomSchemaProvider), ), ) diff --git a/internal/handler/yaml_handler/yaml_handler.go b/internal/handler/yaml_handler/yaml_handler.go index a0bb2df8..cad6130f 100644 --- a/internal/handler/yaml_handler/yaml_handler.go +++ b/internal/handler/yaml_handler/yaml_handler.go @@ -56,6 +56,7 @@ func (h *YamlHandler) CustomSchemaProvider(ctx context.Context, URI uri.URI) (ur chart, err := h.chartStore.GetChartForDoc(URI) if err != nil { logger.Error(err) + // we can ignore the error, providing a wrong schema is still useful } schemaFilePath, err := jsonschema.CreateJsonSchemaForChart(chart) if err != nil { @@ -64,41 +65,3 @@ func (h *YamlHandler) CustomSchemaProvider(ctx context.Context, URI uri.URI) (ur } return uri.File(schemaFilePath), nil } - -func (h *YamlHandler) CustomHandler(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2.Request) error { - switch req.Method() { - case "custom/schema/request": - - params := []string{} - jsonBytes, err := req.Params().MarshalJSON() - if err != nil { - logger.Error(err) - return reply(ctx, nil, nil) - } - - err = json.Unmarshal(jsonBytes, ¶ms) - if err != nil { - logger.Error(err) - return reply(ctx, nil, nil) - } - - logger.Println("YamlHandler: custom/schema/request", req.Params()) - - if len(params) == 0 { - return reply(ctx, nil, nil) - } - chart, err := h.chartStore.GetChartForDoc(uri.New(params[0])) - if err != nil { - logger.Error(err) - } - schemaFilePath, err := jsonschema.CreateJsonSchemaForChart(chart) - if err != nil { - logger.Error(err) - return reply(ctx, nil, nil) - } - - return reply(ctx, uri.New(schemaFilePath), nil) - } - - return jsonrpc2.MethodNotFoundHandler(ctx, reply, req) -} diff --git a/internal/json_schema/json_schema.go b/internal/json_schema/json_schema.go index ab1ec98f..6113eda1 100644 --- a/internal/json_schema/json_schema.go +++ b/internal/json_schema/json_schema.go @@ -13,11 +13,6 @@ import ( var logger = log.GetLogger() func CreateJsonSchemaForChart(chart *charts.Chart) (string, error) { - // reflector := jsonschema.Reflector{ - // ExpandedStruct: true, - // AllowAdditionalProperties: true, - // } - schema, err := GenerateJSONSchema(chart.ValuesFiles.MainValuesFile.Values) bytes, err := json.Marshal(schema) @@ -26,8 +21,6 @@ func CreateJsonSchemaForChart(chart *charts.Chart) (string, error) { return "", err } - // create a tmp file and write the schema - file, err := os.CreateTemp("", base64.StdEncoding.EncodeToString([]byte(chart.RootURI.Filename()))) if err != nil { logger.Error(err) @@ -42,18 +35,3 @@ func CreateJsonSchemaForChart(chart *charts.Chart) (string, error) { return file.Name(), nil } - -// func GenerateSchemaFromData(data interface{}) error { -// jsonBytes, err := json.Marshal(data) -// if err != nil { -// return nil, err -// } -// -// documentLoader := gojsonschema.NewStringLoader(string(jsonBytes)) -// schema, err := gojsonschema.NewSchema(documentLoader) -// if err != nil { -// return nil, err -// } -// -// return schema.Root(), nil -// }