diff --git a/internal/terraform/exec/exec.go b/internal/terraform/exec/exec.go index 40ade90e2..aa5155758 100644 --- a/internal/terraform/exec/exec.go +++ b/internal/terraform/exec/exec.go @@ -256,6 +256,11 @@ func writeAndClose(w io.WriteCloser, input []byte) (int, error) { return n, nil } +func (e *Executor) Init(ctx context.Context) error { + _, err := e.run(ctx, "init") + return err +} + func (e *Executor) Version(ctx context.Context) (string, error) { out, err := e.run(ctx, "version") if err != nil { diff --git a/internal/terraform/rootmodule/root_module.go b/internal/terraform/rootmodule/root_module.go index e5144dc55..68f3da715 100644 --- a/internal/terraform/rootmodule/root_module.go +++ b/internal/terraform/rootmodule/root_module.go @@ -278,6 +278,17 @@ func (rm *rootModule) discoverTerraformExecutor(ctx context.Context) error { return nil } +func (rm *rootModule) ExecuteTerraformInit(ctx context.Context) error { + if err := rm.discoverTerraformExecutor(ctx); err != nil { + return err + } + if rm.tfExec == nil { + return errors.New("no terraform executor - unable to init workspace") + } + + return rm.tfExec.Init(ctx) +} + func (rm *rootModule) discoverTerraformVersion(ctx context.Context) error { if rm.tfExec == nil { return errors.New("no terraform executor - unable to read version") diff --git a/internal/terraform/rootmodule/root_module_manager.go b/internal/terraform/rootmodule/root_module_manager.go index 89e0c0a17..e08041d68 100644 --- a/internal/terraform/rootmodule/root_module_manager.go +++ b/internal/terraform/rootmodule/root_module_manager.go @@ -100,6 +100,10 @@ func (rmm *rootModuleManager) SetLogger(logger *log.Logger) { rmm.logger = logger } +func (rmm *rootModuleManager) NewPotentialRootModule(dir string) (RootModule, error) { + return rmm.newRootModule(context.Background(), filepath.Clean(dir)) +} + func (rmm *rootModuleManager) AddAndStartLoadingRootModule(ctx context.Context, dir string) (RootModule, error) { dir = filepath.Clean(dir) diff --git a/internal/terraform/rootmodule/types.go b/internal/terraform/rootmodule/types.go index fd4f3159e..0a0f7a409 100644 --- a/internal/terraform/rootmodule/types.go +++ b/internal/terraform/rootmodule/types.go @@ -42,6 +42,7 @@ type RootModuleManager interface { SetTerraformExecLogPath(logPath string) SetTerraformExecTimeout(timeout time.Duration) + NewPotentialRootModule(dir string) (RootModule, error) AddAndStartLoadingRootModule(ctx context.Context, dir string) (RootModule, error) WorkerPoolSize() int WorkerQueueSize() int @@ -78,6 +79,7 @@ type RootModule interface { IsParserLoaded() bool TerraformFormatter() (exec.Formatter, error) IsTerraformLoaded() bool + ExecuteTerraformInit(ctx context.Context) error Modules() []ModuleRecord } diff --git a/langserver/handlers/did_open.go b/langserver/handlers/did_open.go index d7fd4029a..dc528ca12 100644 --- a/langserver/handlers/did_open.go +++ b/langserver/handlers/did_open.go @@ -50,10 +50,34 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe // because we don't gather "init-able folders" in any way " You may need to run terraform init"+ " and reload your editor.", readableDir) - return jrpc2.PushNotify(ctx, "window/showMessage", lsp.ShowMessageParams{ + resp, _ := jrpc2.PushCall(ctx, "window/showMessageRequest", lsp.ShowMessageRequestParams{ Type: lsp.MTWarning, Message: msg, + Actions: []lsp.MessageActionItem{ + { + Title: "run `terraform init`", + }, + }, }) + var action lsp.MessageActionItem + if err := resp.UnmarshalResult(&action); err != nil { + return err + } + if action.Title == "run `terraform init`" { + rmm, err := lsctx.RootModuleManager(ctx) + if err != nil { + return err + } + rm, err := rmm.NewPotentialRootModule(f.Dir()) + if err != nil { + return err + } + go func() { + if err := rm.ExecuteTerraformInit(ctx); err != nil { + lh.logger.Printf("failed to execute `terraform init`: %+v", err) + } + }() + } } if len(candidates) > 1 { candidateDir := humanReadablePath(rootDir, candidates[0].Path()) diff --git a/langserver/handlers/service.go b/langserver/handlers/service.go index 8ef9600aa..84c7b10b9 100644 --- a/langserver/handlers/service.go +++ b/langserver/handlers/service.go @@ -181,6 +181,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) { ctx = lsctx.WithDocumentStorage(ctx, fs) ctx = lsctx.WithRootDirectory(ctx, &rootDir) ctx = lsctx.WithRootModuleCandidateFinder(ctx, svc.modMgr) + ctx = lsctx.WithRootModuleManager(ctx, svc.modMgr) ctx = lsctx.WithRootModuleWalker(ctx, svc.walker) return handle(ctx, req, lh.TextDocumentDidOpen) },