From d54ab99795a8a21a9523e829960d1691d263d21f Mon Sep 17 00:00:00 2001 From: Alex Pilon <apilon@hashicorp.com> Date: Thu, 22 Oct 2020 21:07:47 -0400 Subject: [PATCH 01/10] Ensure command names are unique to avoid language protocol collisions --- langserver/handlers/execute_command.go | 18 +++++-- .../execute_command_rootmodules_test.go | 14 +++--- langserver/handlers/handlers_test.go | 50 ++++++++++++------- langserver/handlers/initialize.go | 2 +- 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/langserver/handlers/execute_command.go b/langserver/handlers/execute_command.go index 76eb2d47..505f5c90 100644 --- a/langserver/handlers/execute_command.go +++ b/langserver/handlers/execute_command.go @@ -7,9 +7,13 @@ import ( "strings" "github.com/creachadair/jrpc2/code" + lsctx "github.com/hashicorp/terraform-ls/internal/context" + ilsp "github.com/hashicorp/terraform-ls/internal/lsp" lsp "github.com/sourcegraph/go-lsp" ) +const commandPrefix = "terraform-ls." + type executeCommandHandler func(context.Context, commandArgs) (interface{}, error) type executeCommandHandlers map[string]executeCommandHandler @@ -17,16 +21,20 @@ var handlers = executeCommandHandlers{ "rootmodules": executeCommandRootModulesHandler, } -func (h executeCommandHandlers) Names() []string { - var names []string +func (h executeCommandHandlers) Names(suffix string) []string { + var fullnames []string for name := range h { - names = append(names, name) + fullnames = append(fullnames, commandPrefix+name+suffix) } - return names + return fullnames } func (lh *logHandler) WorkspaceExecuteCommand(ctx context.Context, params lsp.ExecuteCommandParams) (interface{}, error) { - handler, ok := handlers[params.Command] + rootDir, _ := lsctx.RootDirectory(ctx) + fh := ilsp.FileHandlerFromDirPath(rootDir) + name := strings.TrimPrefix(params.Command, commandPrefix) + name = strings.TrimSuffix(name, "."+fh.URI()) + handler, ok := handlers[name] if !ok { return nil, fmt.Errorf("%w: command handler not found for %q", code.MethodNotFound.Err(), params.Command) } diff --git a/langserver/handlers/execute_command_rootmodules_test.go b/langserver/handlers/execute_command_rootmodules_test.go index 42926db7..48c4bdf8 100644 --- a/langserver/handlers/execute_command_rootmodules_test.go +++ b/langserver/handlers/execute_command_rootmodules_test.go @@ -50,9 +50,9 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_argumentError(t *testing ls.CallAndExpectError(t, &langserver.CallRequest{ Method: "workspace/executeCommand", - ReqParams: `{ - "command": "rootmodules" - }`}, code.InvalidParams.Err()) + ReqParams: fmt.Sprintf(`{ + "command": "terraform-ls.rootmodules.%s" + }`, tmpDir.URI())}, code.InvalidParams.Err()) } func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { @@ -95,9 +95,9 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ - "command": "rootmodules", + "command": "terraform-ls.rootmodules.%s", "arguments": ["uri=%s"] - }`, testFileURI)}, fmt.Sprintf(`{ + }`, tmpDir.URI(), testFileURI)}, fmt.Sprintf(`{ "jsonrpc": "2.0", "id": 3, "result": { @@ -158,9 +158,9 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_multiple(t *testing.T) { ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ - "command": "rootmodules", + "command": "terraform-ls.rootmodules.%s", "arguments": ["uri=%s"] - }`, module.URI())}, fmt.Sprintf(`{ + }`, root.URI(), module.URI())}, fmt.Sprintf(`{ "jsonrpc": "2.0", "id": 2, "result": { diff --git a/langserver/handlers/handlers_test.go b/langserver/handlers/handlers_test.go index 8900420e..973566ac 100644 --- a/langserver/handlers/handlers_test.go +++ b/langserver/handlers/handlers_test.go @@ -1,6 +1,7 @@ package handlers import ( + "encoding/json" "fmt" "os" "path/filepath" @@ -16,29 +17,38 @@ import ( "github.com/stretchr/testify/mock" ) -const initializeResponse = `{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "capabilities": { - "textDocumentSync": { - "openClose": true, - "change": 2 - }, - "completionProvider": {}, - "documentSymbolProvider":true, - "documentFormattingProvider":true, - "executeCommandProvider": { - "commands": ["rootmodules"] +func initializeResponse(t *testing.T, rootUri string) string { + jsonArray, err := json.Marshal(handlers.Names("." + rootUri)) + if err != nil { + t.Fatal(err) + } + + return fmt.Sprintf(`{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "capabilities": { + "textDocumentSync": { + "openClose": true, + "change": 2 + }, + "completionProvider": {}, + "documentSymbolProvider":true, + "documentFormattingProvider":true, + "executeCommandProvider": { + "commands": %s + } } } - } -}` + }`, string(jsonArray)) +} func TestInitalizeAndShutdown(t *testing.T) { + tmpDir := TempDir(t) + ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{ RootModules: map[string]*rootmodule.RootModuleMock{ - TempDir(t).Dir(): {TfExecFactory: validTfMockCalls()}, + tmpDir.Dir(): {TfExecFactory: validTfMockCalls()}, }})) stop := ls.Start(t) defer stop() @@ -49,7 +59,7 @@ func TestInitalizeAndShutdown(t *testing.T) { "capabilities": {}, "rootUri": %q, "processId": 12345 - }`, TempDir(t).URI())}, initializeResponse) + }`, tmpDir.URI())}, initializeResponse(t, tmpDir.URI())) ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "shutdown", ReqParams: `{}`}, `{ @@ -60,6 +70,8 @@ func TestInitalizeAndShutdown(t *testing.T) { } func TestEOF(t *testing.T) { + tmpDir := TempDir(t) + ms := newMockSession(&MockSessionInput{ RootModules: map[string]*rootmodule.RootModuleMock{ TempDir(t).Dir(): {TfExecFactory: validTfMockCalls()}, @@ -74,7 +86,7 @@ func TestEOF(t *testing.T) { "capabilities": {}, "rootUri": %q, "processId": 12345 - }`, TempDir(t).URI())}, initializeResponse) + }`, tmpDir.URI())}, initializeResponse(t, tmpDir.URI())) ls.CloseClientStdout(t) diff --git a/langserver/handlers/initialize.go b/langserver/handlers/initialize.go index 5a812b28..88ae7224 100644 --- a/langserver/handlers/initialize.go +++ b/langserver/handlers/initialize.go @@ -29,7 +29,7 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam DocumentFormattingProvider: true, DocumentSymbolProvider: true, ExecuteCommandProvider: &lsp.ExecuteCommandOptions{ - Commands: handlers.Names(), + Commands: handlers.Names("." + string(params.RootURI)), }, }, } From d76e60926dcc7cd914b192893708275e897476c3 Mon Sep 17 00:00:00 2001 From: Alex Pilon <apilon@hashicorp.com> Date: Tue, 27 Oct 2020 20:23:29 -0400 Subject: [PATCH 02/10] Refactor codebase to support server ID --- internal/context/context.go | 23 ++++++++++++++++ internal/settings/settings.go | 2 ++ langserver/handlers/execute_command.go | 9 ++++--- .../execute_command_rootmodules_test.go | 27 ++++++++++++------- langserver/handlers/handlers_test.go | 18 ++++++++----- langserver/handlers/initialize.go | 13 ++++++--- langserver/handlers/service.go | 4 ++- 7 files changed, 73 insertions(+), 23 deletions(-) diff --git a/internal/context/context.go b/internal/context/context.go index 8e08f864..06ae1095 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -35,6 +35,7 @@ var ( ctxRootModuleLoader = &contextKey{"root module loader"} ctxRootDir = &contextKey{"root directory"} ctxDiags = &contextKey{"diagnostics"} + ctxServerID = &contextKey{"servier id"} ) func missingContextErr(ctxKey *contextKey) *MissingContextErr { @@ -190,6 +191,28 @@ func RootDirectory(ctx context.Context) (string, bool) { return *rootDir, true } +func WithServerID(ctx context.Context, id *string) context.Context { + return context.WithValue(ctx, ctxServerID, id) +} + +func SetServerID(ctx context.Context, id string) error { + serverID, ok := ctx.Value(ctxServerID).(*string) + if !ok { + return missingContextErr(ctxServerID) + } + + *serverID = id + return nil +} + +func ServerID(ctx context.Context) (string, bool) { + serverID, ok := ctx.Value(ctxServerID).(*string) + if !ok { + return "", false + } + return *serverID, true +} + func WithRootModuleWalker(ctx context.Context, w *rootmodule.Walker) context.Context { return context.WithValue(ctx, ctxRootModuleWalker, w) } diff --git a/internal/settings/settings.go b/internal/settings/settings.go index 68662ed1..a5304402 100644 --- a/internal/settings/settings.go +++ b/internal/settings/settings.go @@ -2,6 +2,7 @@ package settings import ( "fmt" + "github.com/mitchellh/mapstructure" ) @@ -9,6 +10,7 @@ type Options struct { // RootModulePaths describes a list of absolute paths to root modules RootModulePaths []string `mapstructure:"rootModulePaths"` ExcludeModulePaths []string `mapstructure:"excludeModulePaths"` + ID string `mapstructure:"id"` // TODO: Need to check for conflict with CLI flags // TerraformExecPath string diff --git a/langserver/handlers/execute_command.go b/langserver/handlers/execute_command.go index 505f5c90..e0d3cdb8 100644 --- a/langserver/handlers/execute_command.go +++ b/langserver/handlers/execute_command.go @@ -8,7 +8,6 @@ import ( "github.com/creachadair/jrpc2/code" lsctx "github.com/hashicorp/terraform-ls/internal/context" - ilsp "github.com/hashicorp/terraform-ls/internal/lsp" lsp "github.com/sourcegraph/go-lsp" ) @@ -22,6 +21,9 @@ var handlers = executeCommandHandlers{ } func (h executeCommandHandlers) Names(suffix string) []string { + if suffix != "" && !strings.HasPrefix(suffix, ".") { + suffix = "." + suffix + } var fullnames []string for name := range h { fullnames = append(fullnames, commandPrefix+name+suffix) @@ -30,10 +32,9 @@ func (h executeCommandHandlers) Names(suffix string) []string { } func (lh *logHandler) WorkspaceExecuteCommand(ctx context.Context, params lsp.ExecuteCommandParams) (interface{}, error) { - rootDir, _ := lsctx.RootDirectory(ctx) - fh := ilsp.FileHandlerFromDirPath(rootDir) + serverID, _ := lsctx.ServerID(ctx) name := strings.TrimPrefix(params.Command, commandPrefix) - name = strings.TrimSuffix(name, "."+fh.URI()) + name = strings.TrimSuffix(name, "."+serverID) handler, ok := handlers[name] if !ok { return nil, fmt.Errorf("%w: command handler not found for %q", code.MethodNotFound.Err(), params.Command) diff --git a/langserver/handlers/execute_command_rootmodules_test.go b/langserver/handlers/execute_command_rootmodules_test.go index 48c4bdf8..baeb96b5 100644 --- a/langserver/handlers/execute_command_rootmodules_test.go +++ b/langserver/handlers/execute_command_rootmodules_test.go @@ -31,7 +31,10 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_argumentError(t *testing ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345 + "processId": 12345, + "initializationOptions": { + "id": "1" + } }`, tmpDir.URI())}) ls.Notify(t, &langserver.CallRequest{ Method: "initialized", @@ -51,8 +54,8 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_argumentError(t *testing ls.CallAndExpectError(t, &langserver.CallRequest{ Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ - "command": "terraform-ls.rootmodules.%s" - }`, tmpDir.URI())}, code.InvalidParams.Err()) + "command": "terraform-ls.rootmodules.1" + }`)}, code.InvalidParams.Err()) } func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { @@ -75,7 +78,10 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345 + "processId": 12345, + "initializationOptions": { + "id": "1" + } }`, tmpDir.URI())}) ls.Notify(t, &langserver.CallRequest{ Method: "initialized", @@ -95,9 +101,9 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ - "command": "terraform-ls.rootmodules.%s", + "command": "terraform-ls.rootmodules.1", "arguments": ["uri=%s"] - }`, tmpDir.URI(), testFileURI)}, fmt.Sprintf(`{ + }`, testFileURI)}, fmt.Sprintf(`{ "jsonrpc": "2.0", "id": 3, "result": { @@ -146,7 +152,10 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_multiple(t *testing.T) { ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345 + "processId": 12345, + "initializationOptions": { + "id": "1" + } }`, root.URI())}) ls.Notify(t, &langserver.CallRequest{ Method: "initialized", @@ -158,9 +167,9 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_multiple(t *testing.T) { ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ - "command": "terraform-ls.rootmodules.%s", + "command": "terraform-ls.rootmodules.1", "arguments": ["uri=%s"] - }`, root.URI(), module.URI())}, fmt.Sprintf(`{ + }`, module.URI())}, fmt.Sprintf(`{ "jsonrpc": "2.0", "id": 2, "result": { diff --git a/langserver/handlers/handlers_test.go b/langserver/handlers/handlers_test.go index 973566ac..05720f3b 100644 --- a/langserver/handlers/handlers_test.go +++ b/langserver/handlers/handlers_test.go @@ -17,8 +17,8 @@ import ( "github.com/stretchr/testify/mock" ) -func initializeResponse(t *testing.T, rootUri string) string { - jsonArray, err := json.Marshal(handlers.Names("." + rootUri)) +func initializeResponse(t *testing.T, commandSuffix string) string { + jsonArray, err := json.Marshal(handlers.Names("." + commandSuffix)) if err != nil { t.Fatal(err) } @@ -58,8 +58,11 @@ func TestInitalizeAndShutdown(t *testing.T) { ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345 - }`, tmpDir.URI())}, initializeResponse(t, tmpDir.URI())) + "processId": 12345, + "initializationOptions": { + "id": "1" + } + }`, tmpDir.URI())}, initializeResponse(t, "1")) ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "shutdown", ReqParams: `{}`}, `{ @@ -85,8 +88,11 @@ func TestEOF(t *testing.T) { ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345 - }`, tmpDir.URI())}, initializeResponse(t, tmpDir.URI())) + "processId": 12345, + "initializationOptions": { + "id": "1" + } + }`, tmpDir.URI())}, initializeResponse(t, "1")) ls.CloseClientStdout(t) diff --git a/langserver/handlers/initialize.go b/langserver/handlers/initialize.go index 88ae7224..24b7688e 100644 --- a/langserver/handlers/initialize.go +++ b/langserver/handlers/initialize.go @@ -28,9 +28,6 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam }, DocumentFormattingProvider: true, DocumentSymbolProvider: true, - ExecuteCommandProvider: &lsp.ExecuteCommandOptions{ - Commands: handlers.Names("." + string(params.RootURI)), - }, }, } @@ -77,6 +74,16 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam if err != nil { return serverCaps, err } + + // set server ID + err = lsctx.SetServerID(ctx, out.Options.ID) + if err != nil { + return serverCaps, err + } + // apply suffix to executeCommand handler names + serverCaps.Capabilities.ExecuteCommandProvider = &lsp.ExecuteCommandOptions{ + Commands: handlers.Names(out.Options.ID), + } if len(out.UnusedKeys) > 0 { jrpc2.PushNotify(ctx, "window/showMessage", &lsp.ShowMessageParams{ Type: lsp.MTWarning, diff --git a/langserver/handlers/service.go b/langserver/handlers/service.go index 8d0fcb79..3b65fd74 100644 --- a/langserver/handlers/service.go +++ b/langserver/handlers/service.go @@ -145,6 +145,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { diags := diagnostics.NewNotifier(svc.sessCtx, svc.logger) rootDir := "" + serverID := "" m := map[string]rpch.Func{ "initialize": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) { @@ -157,6 +158,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { ctx = lsctx.WithWatcher(ctx, ww) ctx = lsctx.WithRootModuleWalker(ctx, svc.walker) ctx = lsctx.WithRootDirectory(ctx, &rootDir) + ctx = lsctx.WithServerID(ctx, &serverID) ctx = lsctx.WithRootModuleManager(ctx, svc.modMgr) ctx = lsctx.WithRootModuleLoader(ctx, rmLoader) @@ -240,7 +242,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { return nil, err } - ctx = lsctx.WithRootDirectory(ctx, &rootDir) + ctx = lsctx.WithServerID(ctx, &serverID) ctx = lsctx.WithRootModuleCandidateFinder(ctx, svc.modMgr) ctx = lsctx.WithRootModuleWalker(ctx, svc.walker) From 646ed62e760c44570e9fc4cec4e69efa05365d9b Mon Sep 17 00:00:00 2001 From: appilon <apilon@hashicorp.com> Date: Tue, 27 Oct 2020 20:31:25 -0400 Subject: [PATCH 03/10] Update internal/context/context.go Co-authored-by: Audrey Eschright <audrey@hashicorp.com> --- internal/context/context.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/context/context.go b/internal/context/context.go index 06ae1095..85e3e39f 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -35,7 +35,7 @@ var ( ctxRootModuleLoader = &contextKey{"root module loader"} ctxRootDir = &contextKey{"root directory"} ctxDiags = &contextKey{"diagnostics"} - ctxServerID = &contextKey{"servier id"} + ctxServerID = &contextKey{"server id"} ) func missingContextErr(ctxKey *contextKey) *MissingContextErr { From d121e3aa4f3e6161b46e78b4262d41b965d09ba7 Mon Sep 17 00:00:00 2001 From: Alex Pilon <apilon@hashicorp.com> Date: Thu, 29 Oct 2020 20:07:34 -0400 Subject: [PATCH 04/10] Refactor command prefix and handler init --- internal/context/context.go | 24 ++---------- internal/settings/settings.go | 2 +- langserver/handlers/execute_command.go | 37 +++++++++++-------- .../execute_command_rootmodules_test.go | 27 +++++--------- langserver/handlers/handlers_test.go | 18 +++------ langserver/handlers/initialize.go | 9 +---- langserver/handlers/service.go | 3 -- 7 files changed, 43 insertions(+), 77 deletions(-) diff --git a/internal/context/context.go b/internal/context/context.go index 85e3e39f..d72846e8 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -35,7 +35,7 @@ var ( ctxRootModuleLoader = &contextKey{"root module loader"} ctxRootDir = &contextKey{"root directory"} ctxDiags = &contextKey{"diagnostics"} - ctxServerID = &contextKey{"server id"} + ctxCommandPrefix = &contextKey{"command prefix"} ) func missingContextErr(ctxKey *contextKey) *MissingContextErr { @@ -191,26 +191,8 @@ func RootDirectory(ctx context.Context) (string, bool) { return *rootDir, true } -func WithServerID(ctx context.Context, id *string) context.Context { - return context.WithValue(ctx, ctxServerID, id) -} - -func SetServerID(ctx context.Context, id string) error { - serverID, ok := ctx.Value(ctxServerID).(*string) - if !ok { - return missingContextErr(ctxServerID) - } - - *serverID = id - return nil -} - -func ServerID(ctx context.Context) (string, bool) { - serverID, ok := ctx.Value(ctxServerID).(*string) - if !ok { - return "", false - } - return *serverID, true +func WithCommandPrefix(ctx context.Context, prefix *string) context.Context { + return context.WithValue(ctx, ctxCommandPrefix, prefix) } func WithRootModuleWalker(ctx context.Context, w *rootmodule.Walker) context.Context { diff --git a/internal/settings/settings.go b/internal/settings/settings.go index a5304402..85e43c82 100644 --- a/internal/settings/settings.go +++ b/internal/settings/settings.go @@ -10,7 +10,7 @@ type Options struct { // RootModulePaths describes a list of absolute paths to root modules RootModulePaths []string `mapstructure:"rootModulePaths"` ExcludeModulePaths []string `mapstructure:"excludeModulePaths"` - ID string `mapstructure:"id"` + CommandPrefix string `mapstructure:"commandPrefix"` // TODO: Need to check for conflict with CLI flags // TerraformExecPath string diff --git a/langserver/handlers/execute_command.go b/langserver/handlers/execute_command.go index e0d3cdb8..6538fed8 100644 --- a/langserver/handlers/execute_command.go +++ b/langserver/handlers/execute_command.go @@ -7,35 +7,42 @@ import ( "strings" "github.com/creachadair/jrpc2/code" - lsctx "github.com/hashicorp/terraform-ls/internal/context" lsp "github.com/sourcegraph/go-lsp" ) -const commandPrefix = "terraform-ls." - type executeCommandHandler func(context.Context, commandArgs) (interface{}, error) type executeCommandHandlers map[string]executeCommandHandler -var handlers = executeCommandHandlers{ - "rootmodules": executeCommandRootModulesHandler, +const langServerPrefix = "terraform-ls." + +var commandPrefix string +var handlers = make(executeCommandHandlers) + +func prefix(name string) string { + prefix := langServerPrefix + if commandPrefix != "" { + prefix = commandPrefix + "." + langServerPrefix + } + return prefix + name } -func (h executeCommandHandlers) Names(suffix string) []string { - if suffix != "" && !strings.HasPrefix(suffix, ".") { - suffix = "." + suffix +func (h executeCommandHandlers) Init(p string) executeCommandHandlers { + if len(h) == 0 { + commandPrefix = p + h[prefix("rootmodules")] = executeCommandRootModulesHandler } - var fullnames []string + return h +} + +func (h executeCommandHandlers) Names() (names []string) { for name := range h { - fullnames = append(fullnames, commandPrefix+name+suffix) + names = append(names, name) } - return fullnames + return names } func (lh *logHandler) WorkspaceExecuteCommand(ctx context.Context, params lsp.ExecuteCommandParams) (interface{}, error) { - serverID, _ := lsctx.ServerID(ctx) - name := strings.TrimPrefix(params.Command, commandPrefix) - name = strings.TrimSuffix(name, "."+serverID) - handler, ok := handlers[name] + handler, ok := handlers[params.Command] if !ok { return nil, fmt.Errorf("%w: command handler not found for %q", code.MethodNotFound.Err(), params.Command) } diff --git a/langserver/handlers/execute_command_rootmodules_test.go b/langserver/handlers/execute_command_rootmodules_test.go index baeb96b5..5382b91e 100644 --- a/langserver/handlers/execute_command_rootmodules_test.go +++ b/langserver/handlers/execute_command_rootmodules_test.go @@ -31,10 +31,7 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_argumentError(t *testing ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345, - "initializationOptions": { - "id": "1" - } + "processId": 12345 }`, tmpDir.URI())}) ls.Notify(t, &langserver.CallRequest{ Method: "initialized", @@ -54,8 +51,8 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_argumentError(t *testing ls.CallAndExpectError(t, &langserver.CallRequest{ Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ - "command": "terraform-ls.rootmodules.1" - }`)}, code.InvalidParams.Err()) + "command": %q + }`, prefix("rootmodules"))}, code.InvalidParams.Err()) } func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { @@ -78,10 +75,7 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345, - "initializationOptions": { - "id": "1" - } + "processId": 12345 }`, tmpDir.URI())}) ls.Notify(t, &langserver.CallRequest{ Method: "initialized", @@ -101,9 +95,9 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ - "command": "terraform-ls.rootmodules.1", + "command": %q, "arguments": ["uri=%s"] - }`, testFileURI)}, fmt.Sprintf(`{ + }`, prefix("rootmodules"), testFileURI)}, fmt.Sprintf(`{ "jsonrpc": "2.0", "id": 3, "result": { @@ -152,10 +146,7 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_multiple(t *testing.T) { ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345, - "initializationOptions": { - "id": "1" - } + "processId": 12345 }`, root.URI())}) ls.Notify(t, &langserver.CallRequest{ Method: "initialized", @@ -167,9 +158,9 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_multiple(t *testing.T) { ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ - "command": "terraform-ls.rootmodules.1", + "command": %q, "arguments": ["uri=%s"] - }`, module.URI())}, fmt.Sprintf(`{ + }`, prefix("rootmodules"), module.URI())}, fmt.Sprintf(`{ "jsonrpc": "2.0", "id": 2, "result": { diff --git a/langserver/handlers/handlers_test.go b/langserver/handlers/handlers_test.go index 05720f3b..1cf0677f 100644 --- a/langserver/handlers/handlers_test.go +++ b/langserver/handlers/handlers_test.go @@ -17,8 +17,8 @@ import ( "github.com/stretchr/testify/mock" ) -func initializeResponse(t *testing.T, commandSuffix string) string { - jsonArray, err := json.Marshal(handlers.Names("." + commandSuffix)) +func initializeResponse(t *testing.T, prefix string) string { + jsonArray, err := json.Marshal(handlers.Init(prefix).Names()) if err != nil { t.Fatal(err) } @@ -58,11 +58,8 @@ func TestInitalizeAndShutdown(t *testing.T) { ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345, - "initializationOptions": { - "id": "1" - } - }`, tmpDir.URI())}, initializeResponse(t, "1")) + "processId": 12345 + }`, tmpDir.URI())}, initializeResponse(t, "")) ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "shutdown", ReqParams: `{}`}, `{ @@ -88,11 +85,8 @@ func TestEOF(t *testing.T) { ReqParams: fmt.Sprintf(`{ "capabilities": {}, "rootUri": %q, - "processId": 12345, - "initializationOptions": { - "id": "1" - } - }`, tmpDir.URI())}, initializeResponse(t, "1")) + "processId": 12345 + }`, tmpDir.URI())}, initializeResponse(t, "")) ls.CloseClientStdout(t) diff --git a/langserver/handlers/initialize.go b/langserver/handlers/initialize.go index 24b7688e..4dc71650 100644 --- a/langserver/handlers/initialize.go +++ b/langserver/handlers/initialize.go @@ -75,14 +75,9 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam return serverCaps, err } - // set server ID - err = lsctx.SetServerID(ctx, out.Options.ID) - if err != nil { - return serverCaps, err - } - // apply suffix to executeCommand handler names + // apply prefix to executeCommand handler names serverCaps.Capabilities.ExecuteCommandProvider = &lsp.ExecuteCommandOptions{ - Commands: handlers.Names(out.Options.ID), + Commands: handlers.Init(out.Options.CommandPrefix).Names(), } if len(out.UnusedKeys) > 0 { jrpc2.PushNotify(ctx, "window/showMessage", &lsp.ShowMessageParams{ diff --git a/langserver/handlers/service.go b/langserver/handlers/service.go index 3b65fd74..f192c5c1 100644 --- a/langserver/handlers/service.go +++ b/langserver/handlers/service.go @@ -145,7 +145,6 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { diags := diagnostics.NewNotifier(svc.sessCtx, svc.logger) rootDir := "" - serverID := "" m := map[string]rpch.Func{ "initialize": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) { @@ -158,7 +157,6 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { ctx = lsctx.WithWatcher(ctx, ww) ctx = lsctx.WithRootModuleWalker(ctx, svc.walker) ctx = lsctx.WithRootDirectory(ctx, &rootDir) - ctx = lsctx.WithServerID(ctx, &serverID) ctx = lsctx.WithRootModuleManager(ctx, svc.modMgr) ctx = lsctx.WithRootModuleLoader(ctx, rmLoader) @@ -242,7 +240,6 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { return nil, err } - ctx = lsctx.WithServerID(ctx, &serverID) ctx = lsctx.WithRootModuleCandidateFinder(ctx, svc.modMgr) ctx = lsctx.WithRootModuleWalker(ctx, svc.walker) From e1fd836cc5844f65a081b88f779b7cefaa9b179e Mon Sep 17 00:00:00 2001 From: Alex Pilon <apilon@hashicorp.com> Date: Thu, 29 Oct 2020 20:36:08 -0400 Subject: [PATCH 05/10] Fix tests to not use commanPrefix Add explicit test with commandPrefix Add doc on new setting --- docs/SETTINGS.md | 20 ++++++++++++++++++++ langserver/handlers/handlers_test.go | 22 ++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/docs/SETTINGS.md b/docs/SETTINGS.md index 53409f18..453b2d55 100644 --- a/docs/SETTINGS.md +++ b/docs/SETTINGS.md @@ -30,6 +30,26 @@ of the target platform (e.g. `\` on Windows, or `/` on Unix), symlinks are followed, trailing slashes automatically removed, and `~` is replaced with your home directory. +## `commandPrefix` + +Some clients such as VS code keep a global registry of commands published by language +servers, and the names must be unique, even between terraform-ls instances. Setting +this allows multiple servers to run side by side, albeit the client is now responsible +for routing commands to the correct server. Users should not need to worry about +this, the frontend client extension should manage it. + +The prefix will be applied to the front of the command name, which already contains +a `terraform-ls` prefix. + +`commandPrefix.terraform-ls.commandName` + +Or if left empty + +`terraform-ls.commandName` + +This setting should be deprecated once the language server supports multiple workspaces, +as this arises in VS code because a server instance is started per VS code workspace. + ## How to pass settings The server expects static settings to be passed as part of LSP `initialize` call, diff --git a/langserver/handlers/handlers_test.go b/langserver/handlers/handlers_test.go index 1cf0677f..3ae43821 100644 --- a/langserver/handlers/handlers_test.go +++ b/langserver/handlers/handlers_test.go @@ -69,6 +69,28 @@ func TestInitalizeAndShutdown(t *testing.T) { }`) } +func TestInitalizeWithCommandPrefix(t *testing.T) { + tmpDir := TempDir(t) + + ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{ + RootModules: map[string]*rootmodule.RootModuleMock{ + tmpDir.Dir(): {TfExecFactory: validTfMockCalls()}, + }})) + stop := ls.Start(t) + defer stop() + + ls.CallAndExpectResponse(t, &langserver.CallRequest{ + Method: "initialize", + ReqParams: fmt.Sprintf(`{ + "capabilities": {}, + "rootUri": %q, + "processId": 12345, + "initializationOptions": { + "commandPrefix": "1" + } + }`, tmpDir.URI())}, initializeResponse(t, "1")) +} + func TestEOF(t *testing.T) { tmpDir := TempDir(t) From 44daa5ec6f846eae6ca139b218680ed56928e35c Mon Sep 17 00:00:00 2001 From: Alex Pilon <apilon@hashicorp.com> Date: Thu, 29 Oct 2020 20:39:14 -0400 Subject: [PATCH 06/10] Remove context commandPrefix --- internal/context/context.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/internal/context/context.go b/internal/context/context.go index d72846e8..8e08f864 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -35,7 +35,6 @@ var ( ctxRootModuleLoader = &contextKey{"root module loader"} ctxRootDir = &contextKey{"root directory"} ctxDiags = &contextKey{"diagnostics"} - ctxCommandPrefix = &contextKey{"command prefix"} ) func missingContextErr(ctxKey *contextKey) *MissingContextErr { @@ -191,10 +190,6 @@ func RootDirectory(ctx context.Context) (string, bool) { return *rootDir, true } -func WithCommandPrefix(ctx context.Context, prefix *string) context.Context { - return context.WithValue(ctx, ctxCommandPrefix, prefix) -} - func WithRootModuleWalker(ctx context.Context, w *rootmodule.Walker) context.Context { return context.WithValue(ctx, ctxRootModuleWalker, w) } From 04d2c218a015988f0bad248c68ce5db2346598bf Mon Sep 17 00:00:00 2001 From: Alex Pilon <apilon@hashicorp.com> Date: Thu, 29 Oct 2020 21:10:45 -0400 Subject: [PATCH 07/10] Fix clearing of global map between tests --- langserver/handlers/execute_command.go | 6 ++---- langserver/handlers/handlers_test.go | 16 +++++++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/langserver/handlers/execute_command.go b/langserver/handlers/execute_command.go index 6538fed8..e18e3299 100644 --- a/langserver/handlers/execute_command.go +++ b/langserver/handlers/execute_command.go @@ -27,10 +27,8 @@ func prefix(name string) string { } func (h executeCommandHandlers) Init(p string) executeCommandHandlers { - if len(h) == 0 { - commandPrefix = p - h[prefix("rootmodules")] = executeCommandRootModulesHandler - } + commandPrefix = p + h[prefix("rootmodules")] = executeCommandRootModulesHandler return h } diff --git a/langserver/handlers/handlers_test.go b/langserver/handlers/handlers_test.go index 3ae43821..0f8cd4e6 100644 --- a/langserver/handlers/handlers_test.go +++ b/langserver/handlers/handlers_test.go @@ -17,8 +17,8 @@ import ( "github.com/stretchr/testify/mock" ) -func initializeResponse(t *testing.T, prefix string) string { - jsonArray, err := json.Marshal(handlers.Init(prefix).Names()) +func initializeResponse(t *testing.T) string { + jsonArray, err := json.Marshal(handlers.Names()) if err != nil { t.Fatal(err) } @@ -44,6 +44,8 @@ func initializeResponse(t *testing.T, prefix string) string { } func TestInitalizeAndShutdown(t *testing.T) { + handlers = make(executeCommandHandlers) + handlers.Init("") tmpDir := TempDir(t) ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{ @@ -59,7 +61,7 @@ func TestInitalizeAndShutdown(t *testing.T) { "capabilities": {}, "rootUri": %q, "processId": 12345 - }`, tmpDir.URI())}, initializeResponse(t, "")) + }`, tmpDir.URI())}, initializeResponse(t)) ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "shutdown", ReqParams: `{}`}, `{ @@ -70,6 +72,8 @@ func TestInitalizeAndShutdown(t *testing.T) { } func TestInitalizeWithCommandPrefix(t *testing.T) { + handlers = make(executeCommandHandlers) + handlers.Init("1") tmpDir := TempDir(t) ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{ @@ -88,10 +92,12 @@ func TestInitalizeWithCommandPrefix(t *testing.T) { "initializationOptions": { "commandPrefix": "1" } - }`, tmpDir.URI())}, initializeResponse(t, "1")) + }`, tmpDir.URI())}, initializeResponse(t)) } func TestEOF(t *testing.T) { + handlers = make(executeCommandHandlers) + handlers.Init("") tmpDir := TempDir(t) ms := newMockSession(&MockSessionInput{ @@ -108,7 +114,7 @@ func TestEOF(t *testing.T) { "capabilities": {}, "rootUri": %q, "processId": 12345 - }`, tmpDir.URI())}, initializeResponse(t, "")) + }`, tmpDir.URI())}, initializeResponse(t)) ls.CloseClientStdout(t) From 44b927359602fc6fd43a224be685d42dc4c7dd55 Mon Sep 17 00:00:00 2001 From: appilon <apilon@hashicorp.com> Date: Fri, 30 Oct 2020 10:04:54 -0400 Subject: [PATCH 08/10] Apply suggestions from code review Co-authored-by: Radek Simko <radek.simko@gmail.com> --- docs/SETTINGS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/SETTINGS.md b/docs/SETTINGS.md index 453b2d55..064daeff 100644 --- a/docs/SETTINGS.md +++ b/docs/SETTINGS.md @@ -32,7 +32,7 @@ and `~` is replaced with your home directory. ## `commandPrefix` -Some clients such as VS code keep a global registry of commands published by language +Some clients such as VS Code keep a global registry of commands published by language servers, and the names must be unique, even between terraform-ls instances. Setting this allows multiple servers to run side by side, albeit the client is now responsible for routing commands to the correct server. Users should not need to worry about @@ -48,7 +48,7 @@ Or if left empty `terraform-ls.commandName` This setting should be deprecated once the language server supports multiple workspaces, -as this arises in VS code because a server instance is started per VS code workspace. +as this arises in VS code because a server instance is started per VS Code workspace. ## How to pass settings From 2d3eaa49832db5537f18178cc57924b9bfbc333a Mon Sep 17 00:00:00 2001 From: Alex Pilon <apilon@hashicorp.com> Date: Fri, 30 Oct 2020 11:52:33 -0400 Subject: [PATCH 09/10] Make session safe command prefix --- internal/context/context.go | 23 ++++++++++++++++ langserver/handlers/execute_command.go | 37 +++++++++++++++----------- langserver/handlers/handlers_test.go | 16 ++++------- langserver/handlers/initialize.go | 5 +++- langserver/handlers/service.go | 3 +++ 5 files changed, 56 insertions(+), 28 deletions(-) diff --git a/internal/context/context.go b/internal/context/context.go index 8e08f864..35eab216 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -34,6 +34,7 @@ var ( ctxRootModuleWalker = &contextKey{"root module walker"} ctxRootModuleLoader = &contextKey{"root module loader"} ctxRootDir = &contextKey{"root directory"} + ctxCommandPrefix = &contextKey{"command prefix"} ctxDiags = &contextKey{"diagnostics"} ) @@ -190,6 +191,28 @@ func RootDirectory(ctx context.Context) (string, bool) { return *rootDir, true } +func WithCommandPrefix(ctx context.Context, prefix *string) context.Context { + return context.WithValue(ctx, ctxCommandPrefix, prefix) +} + +func SetCommandPrefix(ctx context.Context, prefix string) error { + commandPrefix, ok := ctx.Value(ctxCommandPrefix).(*string) + if !ok { + return missingContextErr(ctxCommandPrefix) + } + + *commandPrefix = prefix + return nil +} + +func CommandPrefix(ctx context.Context) (string, bool) { + commandPrefix, ok := ctx.Value(ctxCommandPrefix).(*string) + if !ok { + return "", false + } + return *commandPrefix, true +} + func WithRootModuleWalker(ctx context.Context, w *rootmodule.Walker) context.Context { return context.WithValue(ctx, ctxRootModuleWalker, w) } diff --git a/langserver/handlers/execute_command.go b/langserver/handlers/execute_command.go index e18e3299..fb61b046 100644 --- a/langserver/handlers/execute_command.go +++ b/langserver/handlers/execute_command.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/creachadair/jrpc2/code" + lsctx "github.com/hashicorp/terraform-ls/internal/context" lsp "github.com/sourcegraph/go-lsp" ) @@ -15,32 +16,36 @@ type executeCommandHandlers map[string]executeCommandHandler const langServerPrefix = "terraform-ls." -var commandPrefix string -var handlers = make(executeCommandHandlers) - -func prefix(name string) string { - prefix := langServerPrefix - if commandPrefix != "" { - prefix = commandPrefix + "." + langServerPrefix - } - return prefix + name +var handlers = executeCommandHandlers{ + prefix("rootmodules"): executeCommandRootModulesHandler, } -func (h executeCommandHandlers) Init(p string) executeCommandHandlers { - commandPrefix = p - h[prefix("rootmodules")] = executeCommandRootModulesHandler - return h +func prefix(name string) string { + return langServerPrefix + name } -func (h executeCommandHandlers) Names() (names []string) { +func (h executeCommandHandlers) Names(commandPrefix string) (names []string) { + if commandPrefix != "" { + commandPrefix += "." + } for name := range h { - names = append(names, name) + names = append(names, commandPrefix+name) } return names } +func (h executeCommandHandlers) Get(name, commandPrefix string) (executeCommandHandler, bool) { + if commandPrefix != "" { + commandPrefix += "." + } + name = strings.TrimPrefix(name, commandPrefix) + handler, ok := h[name] + return handler, ok +} + func (lh *logHandler) WorkspaceExecuteCommand(ctx context.Context, params lsp.ExecuteCommandParams) (interface{}, error) { - handler, ok := handlers[params.Command] + commandPrefix, _ := lsctx.CommandPrefix(ctx) + handler, ok := handlers.Get(params.Command, commandPrefix) if !ok { return nil, fmt.Errorf("%w: command handler not found for %q", code.MethodNotFound.Err(), params.Command) } diff --git a/langserver/handlers/handlers_test.go b/langserver/handlers/handlers_test.go index 0f8cd4e6..71c3ced2 100644 --- a/langserver/handlers/handlers_test.go +++ b/langserver/handlers/handlers_test.go @@ -17,8 +17,8 @@ import ( "github.com/stretchr/testify/mock" ) -func initializeResponse(t *testing.T) string { - jsonArray, err := json.Marshal(handlers.Names()) +func initializeResponse(t *testing.T, commandPrefix string) string { + jsonArray, err := json.Marshal(handlers.Names(commandPrefix)) if err != nil { t.Fatal(err) } @@ -44,8 +44,6 @@ func initializeResponse(t *testing.T) string { } func TestInitalizeAndShutdown(t *testing.T) { - handlers = make(executeCommandHandlers) - handlers.Init("") tmpDir := TempDir(t) ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{ @@ -61,7 +59,7 @@ func TestInitalizeAndShutdown(t *testing.T) { "capabilities": {}, "rootUri": %q, "processId": 12345 - }`, tmpDir.URI())}, initializeResponse(t)) + }`, tmpDir.URI())}, initializeResponse(t, "")) ls.CallAndExpectResponse(t, &langserver.CallRequest{ Method: "shutdown", ReqParams: `{}`}, `{ @@ -72,8 +70,6 @@ func TestInitalizeAndShutdown(t *testing.T) { } func TestInitalizeWithCommandPrefix(t *testing.T) { - handlers = make(executeCommandHandlers) - handlers.Init("1") tmpDir := TempDir(t) ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{ @@ -92,12 +88,10 @@ func TestInitalizeWithCommandPrefix(t *testing.T) { "initializationOptions": { "commandPrefix": "1" } - }`, tmpDir.URI())}, initializeResponse(t)) + }`, tmpDir.URI())}, initializeResponse(t, "1")) } func TestEOF(t *testing.T) { - handlers = make(executeCommandHandlers) - handlers.Init("") tmpDir := TempDir(t) ms := newMockSession(&MockSessionInput{ @@ -114,7 +108,7 @@ func TestEOF(t *testing.T) { "capabilities": {}, "rootUri": %q, "processId": 12345 - }`, tmpDir.URI())}, initializeResponse(t)) + }`, tmpDir.URI())}, initializeResponse(t, "")) ls.CloseClientStdout(t) diff --git a/langserver/handlers/initialize.go b/langserver/handlers/initialize.go index 4dc71650..84c6efab 100644 --- a/langserver/handlers/initialize.go +++ b/langserver/handlers/initialize.go @@ -75,10 +75,13 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam return serverCaps, err } + // set commandPrefix for session + lsctx.SetCommandPrefix(ctx, out.Options.CommandPrefix) // apply prefix to executeCommand handler names serverCaps.Capabilities.ExecuteCommandProvider = &lsp.ExecuteCommandOptions{ - Commands: handlers.Init(out.Options.CommandPrefix).Names(), + Commands: handlers.Names(out.Options.CommandPrefix), } + if len(out.UnusedKeys) > 0 { jrpc2.PushNotify(ctx, "window/showMessage", &lsp.ShowMessageParams{ Type: lsp.MTWarning, diff --git a/langserver/handlers/service.go b/langserver/handlers/service.go index f192c5c1..f77c78a5 100644 --- a/langserver/handlers/service.go +++ b/langserver/handlers/service.go @@ -145,6 +145,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { diags := diagnostics.NewNotifier(svc.sessCtx, svc.logger) rootDir := "" + commandPrefix := "" m := map[string]rpch.Func{ "initialize": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) { @@ -157,6 +158,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { ctx = lsctx.WithWatcher(ctx, ww) ctx = lsctx.WithRootModuleWalker(ctx, svc.walker) ctx = lsctx.WithRootDirectory(ctx, &rootDir) + ctx = lsctx.WithCommandPrefix(ctx, &commandPrefix) ctx = lsctx.WithRootModuleManager(ctx, svc.modMgr) ctx = lsctx.WithRootModuleLoader(ctx, rmLoader) @@ -240,6 +242,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { return nil, err } + ctx = lsctx.WithCommandPrefix(ctx, &commandPrefix) ctx = lsctx.WithRootModuleCandidateFinder(ctx, svc.modMgr) ctx = lsctx.WithRootModuleWalker(ctx, svc.walker) From ed25c1b24fc107f67879c71fd8fff0daf132ed61 Mon Sep 17 00:00:00 2001 From: Alex Pilon <apilon@hashicorp.com> Date: Fri, 30 Oct 2020 12:25:56 -0400 Subject: [PATCH 10/10] adjust func name --- langserver/handlers/execute_command.go | 4 ++-- langserver/handlers/execute_command_rootmodules_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/langserver/handlers/execute_command.go b/langserver/handlers/execute_command.go index fb61b046..a11c00ca 100644 --- a/langserver/handlers/execute_command.go +++ b/langserver/handlers/execute_command.go @@ -17,10 +17,10 @@ type executeCommandHandlers map[string]executeCommandHandler const langServerPrefix = "terraform-ls." var handlers = executeCommandHandlers{ - prefix("rootmodules"): executeCommandRootModulesHandler, + prefixCommandName("rootmodules"): executeCommandRootModulesHandler, } -func prefix(name string) string { +func prefixCommandName(name string) string { return langServerPrefix + name } diff --git a/langserver/handlers/execute_command_rootmodules_test.go b/langserver/handlers/execute_command_rootmodules_test.go index 5382b91e..6d96c907 100644 --- a/langserver/handlers/execute_command_rootmodules_test.go +++ b/langserver/handlers/execute_command_rootmodules_test.go @@ -52,7 +52,7 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_argumentError(t *testing Method: "workspace/executeCommand", ReqParams: fmt.Sprintf(`{ "command": %q - }`, prefix("rootmodules"))}, code.InvalidParams.Err()) + }`, prefixCommandName("rootmodules"))}, code.InvalidParams.Err()) } func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { @@ -97,7 +97,7 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_basic(t *testing.T) { ReqParams: fmt.Sprintf(`{ "command": %q, "arguments": ["uri=%s"] - }`, prefix("rootmodules"), testFileURI)}, fmt.Sprintf(`{ + }`, prefixCommandName("rootmodules"), testFileURI)}, fmt.Sprintf(`{ "jsonrpc": "2.0", "id": 3, "result": { @@ -160,7 +160,7 @@ func TestLangServer_workspaceExecuteCommand_rootmodules_multiple(t *testing.T) { ReqParams: fmt.Sprintf(`{ "command": %q, "arguments": ["uri=%s"] - }`, prefix("rootmodules"), module.URI())}, fmt.Sprintf(`{ + }`, prefixCommandName("rootmodules"), module.URI())}, fmt.Sprintf(`{ "jsonrpc": "2.0", "id": 2, "result": {