Skip to content

Commit

Permalink
ask for init if current folder is not an initialized root module
Browse files Browse the repository at this point in the history
  • Loading branch information
njuCZ committed Nov 13, 2020
1 parent 8bfea75 commit 4e4489c
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 10 deletions.
11 changes: 11 additions & 0 deletions internal/terraform/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ func (e *Executor) setLogPath(method string) error {
return e.tf.SetLogPath(logPath)
}

func (e *Executor) Init(ctx context.Context) error {
ctx, cancel := e.withTimeout(ctx)
defer cancel()
err := e.setLogPath("Init")
if err != nil {
return err
}

return e.contextfulError(ctx, "Init", e.tf.Init(ctx))
}

func (e *Executor) Format(ctx context.Context, input []byte) ([]byte, error) {
ctx, cancel := e.withTimeout(ctx)
defer cancel()
Expand Down
14 changes: 14 additions & 0 deletions internal/terraform/exec/mock/executor.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions internal/terraform/exec/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type TerraformExecutor interface {
SetExecLogPath(path string) error
SetTimeout(duration time.Duration)
GetExecPath() string
Init(ctx context.Context) error
Format(ctx context.Context, input []byte) ([]byte, error)
Version(ctx context.Context) (*version.Version, error)
ProviderSchemas(ctx context.Context) (*tfjson.ProviderSchemas, error)
Expand Down
10 changes: 10 additions & 0 deletions internal/terraform/rootmodule/root_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,16 @@ func (rm *rootModule) discoverTerraformExecutor(ctx context.Context) error {
return nil
}

func (rm *rootModule) ExecuteTerraformInit(ctx context.Context) error {
if !rm.IsTerraformAvailable() {
if err := rm.discoverTerraformExecutor(ctx); err != nil {
return err
}
}

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")
Expand Down
15 changes: 15 additions & 0 deletions internal/terraform/rootmodule/root_module_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ func (rmm *rootModuleManager) SetLogger(logger *log.Logger) {
rmm.logger = logger
}

func (rmm *rootModuleManager) InitAndUpdateRootModule(ctx context.Context, dir string) (RootModule, error) {
rm, err := rmm.RootModuleByPath(dir)
if err != nil {
return nil, fmt.Errorf("failed to get root module: %+v", err)
}

if err := rm.ExecuteTerraformInit(ctx); err != nil {
return nil, fmt.Errorf("failed to init root module: %+v", err)
}

rootModule := rm.(*rootModule)
rootModule.discoverCaches(ctx, dir)
return rm, rootModule.UpdateProviderSchemaCache(ctx, rootModule.pluginLockFile)
}

func (rmm *rootModuleManager) AddAndStartLoadingRootModule(ctx context.Context, dir string) (RootModule, error) {
dir = filepath.Clean(dir)

Expand Down
2 changes: 2 additions & 0 deletions internal/terraform/rootmodule/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type RootModuleManager interface {
SetTerraformExecLogPath(logPath string)
SetTerraformExecTimeout(timeout time.Duration)

InitAndUpdateRootModule(ctx context.Context, dir string) (RootModule, error)
AddAndStartLoadingRootModule(ctx context.Context, dir string) (RootModule, error)
WorkerPoolSize() int
WorkerQueueSize() int
Expand Down Expand Up @@ -81,6 +82,7 @@ type RootModule interface {
TerraformFormatter() (exec.Formatter, error)
HasTerraformDiscoveryFinished() bool
IsTerraformAvailable() bool
ExecuteTerraformInit(ctx context.Context) error
Modules() []ModuleRecord
}

Expand Down
68 changes: 58 additions & 10 deletions langserver/handlers/did_open.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package handlers
import (
"context"
"fmt"
"log"
"path/filepath"
"strings"

"github.com/creachadair/jrpc2"
lsctx "github.com/hashicorp/terraform-ls/internal/context"
ilsp "github.com/hashicorp/terraform-ls/internal/lsp"
"github.com/hashicorp/terraform-ls/internal/terraform/rootmodule"
"github.com/hashicorp/terraform-ls/internal/watcher"
lsp "github.com/sourcegraph/go-lsp"
)

Expand Down Expand Up @@ -42,6 +44,11 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe
return err
}

w, err := lsctx.Watcher(ctx)
if err != nil {
return err
}

rootDir, _ := lsctx.RootDirectory(ctx)
readableDir := humanReadablePath(rootDir, f.Dir())

Expand Down Expand Up @@ -78,16 +85,10 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe
lh.logger.Printf("walker has not finished walking yet, data may be inaccurate for %s", f.FullPath())
} else if len(candidates) == 0 {
// TODO: Only notify once per f.Dir() per session
msg := fmt.Sprintf("No root module found for %q."+
" Functionality may be limited."+
// Unfortunately we can't be any more specific wrt where
// 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{
Type: lsp.MTWarning,
Message: msg,
})
// TODO: if there is any change for the provider/module, ask for init. The did change handler should also implement this
if !rm.ParsedDiagnostics().HasErrors() && len(f.Text()) != 0 {
go askInitForEmptyRootModule(ctx, lh.logger, w, rootDir, f.Dir())
}
}

if len(candidates) > 1 {
Expand Down Expand Up @@ -134,3 +135,50 @@ func humanReadablePath(rootDir, path string) string {

return relDir
}

func askInitForEmptyRootModule(ctx context.Context, logger *log.Logger, w watcher.Watcher, rootDir, dir string) {
msg := fmt.Sprintf("No root module found for %q."+
" Functionality may be limited."+
// Unfortunately we can't be any more specific wrt where
// because we don't gather "init-able folders" in any way
" You may need to run terraform init.", humanReadablePath(rootDir, dir))
title := "run `terraform init`"
resp, err := jrpc2.PushCall(ctx, "window/showMessageRequest", lsp.ShowMessageRequestParams{
Type: lsp.MTWarning,
Message: msg,
Actions: []lsp.MessageActionItem{
{
Title: title,
},
},
})
if err != nil {
logger.Printf("%+v", err)
return
}
var action lsp.MessageActionItem
if err := resp.UnmarshalResult(&action); err != nil {
logger.Printf("unmarshal MessageActionItem: %+v", err)
return
}
if action.Title == title {
rmm, err := lsctx.RootModuleManager(ctx)
if err != nil {
logger.Printf("%+v", err)
return
}

rm, err := rmm.InitAndUpdateRootModule(ctx, dir)
if err != nil {
logger.Printf("failed to init root module %+v", err)
return
}

paths := rm.PathsToWatch()
logger.Printf("Adding %d paths of root module for watching (%s)", len(paths), dir)
err = w.AddPaths(paths)
if err != nil {
logger.Printf("failed to add watch for dir (%s): %+v", dir, err)
}
}
}
1 change: 1 addition & 0 deletions langserver/handlers/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) {
ctx = lsctx.WithRootDirectory(ctx, &rootDir)
ctx = lsctx.WithRootModuleManager(ctx, svc.modMgr)
ctx = lsctx.WithRootModuleWalker(ctx, svc.walker)
ctx = lsctx.WithWatcher(ctx, ww)
return handle(ctx, req, lh.TextDocumentDidOpen)
},
"textDocument/didClose": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
Expand Down

0 comments on commit 4e4489c

Please sign in to comment.