From 0f5e46eb903f78237aa49c6c47d11b911f03933a Mon Sep 17 00:00:00 2001 From: James Pogran Date: Tue, 3 May 2022 09:23:59 -0400 Subject: [PATCH] Subscribe to updates of module.providers data (#902) Adds support for a client to register a command that will refresh clide side data based on changes the server has detected in the workspace. This specifically adds a new command to refresh the module providers shown client side. The existing Module hook system is used to detect changes in the workspace and notify the client that data has changed. --- CHANGELOG.md | 1 + internal/langserver/handlers/hooks_module.go | 9 +++++++++ internal/langserver/handlers/initialize.go | 6 ++++++ internal/langserver/handlers/service.go | 5 +++++ internal/protocol/experimental.go | 10 ++++++++++ 5 files changed, 31 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b955f881a..7719da9b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ENHANCEMENTS: - Link to documentation from module source for registry modules (via [#874](https://github.com/hashicorp/terraform-ls/pull/874)) + - Automatically refresh Terraform Providers View when providers change in open document ([#902](https://github.com/hashicorp/terraform-ls/pull/902)) INTERNAL: - build(deps): bump github.com/mitchellh/cli from 1.1.2 to 1.1.3 ([#886](https://github.com/hashicorp/terraform-ls/pull/886)) diff --git a/internal/langserver/handlers/hooks_module.go b/internal/langserver/handlers/hooks_module.go index 4f2fc32fe..95b341b6e 100644 --- a/internal/langserver/handlers/hooks_module.go +++ b/internal/langserver/handlers/hooks_module.go @@ -153,6 +153,15 @@ func updateDiagnostics(ctx context.Context, notifier *diagnostics.Notifier) stat } } +func refreshModuleProviders(ctx context.Context, clientRequester session.ClientCaller, logger *log.Logger, commandId string) state.ModuleChangeHook { + return func(oldMod, newMod *state.Module) { + _, err := clientRequester.Callback(ctx, commandId, nil) + if err != nil { + logger.Printf("Error refreshing %s: %s", newMod.Path, err) + } + } +} + func refreshCodeLens(ctx context.Context, clientRequester session.ClientCaller) state.ModuleChangeHook { return func(oldMod, newMod *state.Module) { oldOrigins, oldTargets := 0, 0 diff --git a/internal/langserver/handlers/initialize.go b/internal/langserver/handlers/initialize.go index e53bd09b0..c312cc070 100644 --- a/internal/langserver/handlers/initialize.go +++ b/internal/langserver/handlers/initialize.go @@ -52,6 +52,12 @@ func (svc *service) Initialize(ctx context.Context, params lsp.InitializeParams) } properties["experimentalCapabilities.referenceCountCodeLens"] = true } + if _, ok := expClientCaps.RefreshModuleProvidersCommandId(); ok { + serverCaps.Capabilities.Experimental = lsp.ExperimentalServerCapabilities{ + RefreshModuleProviders: true, + } + properties["experimentalCapabilities.refreshModuleProviders"] = true + } err = ilsp.SetClientCapabilities(ctx, &clientCaps) if err != nil { diff --git a/internal/langserver/handlers/service.go b/internal/langserver/handlers/service.go index d7d620552..1faff807f 100644 --- a/internal/langserver/handlers/service.go +++ b/internal/langserver/handlers/service.go @@ -442,6 +442,11 @@ func (svc *service) configureSessionDependencies(ctx context.Context, cfgOpts *s refreshCodeLens(svc.sessCtx, svc.server)) } + if commandId, ok := lsp.ExperimentalClientCapabilities(cc.Experimental).RefreshModuleProvidersCommandId(); ok { + svc.stateStore.Modules.ChangeHooks = append(svc.stateStore.Modules.ChangeHooks, + refreshModuleProviders(svc.sessCtx, svc.server, svc.logger, commandId)) + } + if cc.Workspace.SemanticTokens.RefreshSupport { svc.stateStore.Modules.ChangeHooks = append(svc.stateStore.Modules.ChangeHooks, refreshSemanticTokens(ctx, svc.srvCtx, svc.logger)) diff --git a/internal/protocol/experimental.go b/internal/protocol/experimental.go index b89410301..84fd06d06 100644 --- a/internal/protocol/experimental.go +++ b/internal/protocol/experimental.go @@ -2,6 +2,7 @@ package protocol type ExperimentalServerCapabilities struct { ReferenceCountCodeLens bool `json:"referenceCountCodeLens"` + RefreshModuleProviders bool `json:"refreshModuleProviders"` } type ExpClientCapabilities map[string]interface{} @@ -22,6 +23,15 @@ func (cc ExpClientCapabilities) ShowReferencesCommandId() (string, bool) { return cmdId, ok } +func (cc ExpClientCapabilities) RefreshModuleProvidersCommandId() (string, bool) { + if cc == nil { + return "", false + } + + cmdId, ok := cc["refereshModuleProvidersCommandId"].(string) + return cmdId, ok +} + func (cc ExpClientCapabilities) TelemetryVersion() (int, bool) { if cc == nil { return 0, false