From 23b57ac15f8e9d363226347f27617f1e2a826829 Mon Sep 17 00:00:00 2001 From: njucz Date: Fri, 31 Jul 2020 15:48:34 +0800 Subject: [PATCH 1/3] add settings for excluding paths in root module discovery --- docs/SETTINGS.md | 34 ++++++++++++++++++++++++- internal/settings/settings.go | 7 ++++- internal/terraform/rootmodule/path.go | 5 ++++ internal/terraform/rootmodule/walker.go | 31 +++++++++++++++++----- langserver/handlers/initialize.go | 23 ++++++++++++----- 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/docs/SETTINGS.md b/docs/SETTINGS.md index 1ef256735..cbe199aba 100644 --- a/docs/SETTINGS.md +++ b/docs/SETTINGS.md @@ -8,7 +8,20 @@ The language server supports the following configuration options: This allows overriding automatic root module discovery by passing a static list of absolute or relative paths to root modules (i.e. folders with `*.tf` files -which have been `terraform init`-ed). +which have been `terraform init`-ed). Conflicts with `ExcludeModulePaths` option. + +Relative paths are resolved relative to the directory opened in the editor. + +Path separators are converted automatically to the match separators +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. + +## `ExcludeModulePaths` (`[]string`) + +This allows exclude root module path when automatic root module discovery by passing a static list +of absolute or relative paths to root modules (i.e. folders with `*.tf` files +which have been `terraform init`-ed). Conflicts with `rootModulePaths` option. Relative paths are resolved relative to the directory opened in the editor. @@ -37,6 +50,18 @@ Use `initializationOptions` key under the `clients.terraform` section, e.g. } } ``` +or +```json +{ + "clients": { + "terraform": { + "initializationOptions": { + "excludeModulePaths": ["/any/path"] + }, + } + } +} +``` ### VS Code @@ -49,3 +74,10 @@ Use `terraform-ls`, e.g. } } ``` +or +```json +{ + "terraform-ls": { + "excludeRootModules": ["/any/path"] + } +} diff --git a/internal/settings/settings.go b/internal/settings/settings.go index 20b884c79..68662ed11 100644 --- a/internal/settings/settings.go +++ b/internal/settings/settings.go @@ -1,12 +1,14 @@ package settings import ( + "fmt" "github.com/mitchellh/mapstructure" ) type Options struct { // RootModulePaths describes a list of absolute paths to root modules - RootModulePaths []string `mapstructure:"rootModulePaths"` + RootModulePaths []string `mapstructure:"rootModulePaths"` + ExcludeModulePaths []string `mapstructure:"excludeModulePaths"` // TODO: Need to check for conflict with CLI flags // TerraformExecPath string @@ -15,6 +17,9 @@ type Options struct { } func (o *Options) Validate() error { + if len(o.RootModulePaths) != 0 && len(o.ExcludeModulePaths) != 0 { + return fmt.Errorf("at most one of `rootModulePaths` and `excludeModulePaths` could be set") + } return nil } diff --git a/internal/terraform/rootmodule/path.go b/internal/terraform/rootmodule/path.go index dcba40d18..eeba6f259 100644 --- a/internal/terraform/rootmodule/path.go +++ b/internal/terraform/rootmodule/path.go @@ -10,3 +10,8 @@ func pathEquals(path1, path2 string) bool { volume2 := filepath.VolumeName(path2) return strings.EqualFold(volume1, volume2) && path1[len(volume1):] == path2[len(volume2):] } + +func ToLowerVolumePath(path string) string { + volume := filepath.VolumeName(path) + return strings.ToLower(volume) + path[len(volume):] +} diff --git a/internal/terraform/rootmodule/walker.go b/internal/terraform/rootmodule/walker.go index 2487d7a59..d77ecead9 100644 --- a/internal/terraform/rootmodule/walker.go +++ b/internal/terraform/rootmodule/walker.go @@ -31,6 +31,8 @@ type Walker struct { walkingMu *sync.RWMutex cancelFunc context.CancelFunc doneCh <-chan struct{} + + excludeModulePaths []string } func NewWalker() *Walker { @@ -45,6 +47,10 @@ func (w *Walker) SetLogger(logger *log.Logger) { w.logger = logger } +func (w *Walker) SetExcludeModulePaths(excludeModulePaths []string) { + w.excludeModulePaths = excludeModulePaths +} + type WalkFunc func(ctx context.Context, rootModulePath string) error func (w *Walker) Stop() { @@ -105,6 +111,12 @@ func (w *Walker) IsWalking() bool { func (w *Walker) walk(ctx context.Context, rootPath string, wf WalkFunc) error { defer w.Stop() + + excludePathMap := make(map[string]bool) + for _, path := range w.excludeModulePaths { + excludePathMap[path] = true + } + err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error { select { case <-w.doneCh: @@ -118,14 +130,19 @@ func (w *Walker) walk(ctx context.Context, rootPath string, wf WalkFunc) error { return nil } - if info.Name() == ".terraform" { - rootDir, err := filepath.Abs(filepath.Dir(path)) - if err != nil { - return err - } + dir, err := filepath.Abs(filepath.Dir(path)) + if err != nil { + return err + } + + if _, ok := excludePathMap[dir]; ok { + w.logger.Printf("successfully exclude root_module: %s", dir) + return filepath.SkipDir + } - w.logger.Printf("found root module %s", rootDir) - return wf(ctx, rootDir) + if info.Name() == ".terraform" { + w.logger.Printf("found root module %s", dir) + return wf(ctx, dir) } if !info.IsDir() { diff --git a/langserver/handlers/initialize.go b/langserver/handlers/initialize.go index e2fea4bad..4fd47b9bd 100644 --- a/langserver/handlers/initialize.go +++ b/langserver/handlers/initialize.go @@ -9,6 +9,7 @@ import ( lsctx "github.com/hashicorp/terraform-ls/internal/context" ilsp "github.com/hashicorp/terraform-ls/internal/lsp" "github.com/hashicorp/terraform-ls/internal/settings" + "github.com/hashicorp/terraform-ls/internal/terraform/rootmodule" "github.com/mitchellh/go-homedir" lsp "github.com/sourcegraph/go-lsp" ) @@ -108,13 +109,23 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam return serverCaps, nil } + var excludeModulePaths []string + for _, rawPath := range cfgOpts.ExcludeModulePaths { + rmPath, err := resolvePath(rootDir, rawPath) + if err != nil { + lh.logger.Printf("Ignoring exclude root module path %s: %s", rawPath, err) + continue + } + excludeModulePaths = append(excludeModulePaths, rmPath) + } + walker, err := lsctx.RootModuleWalker(ctx) if err != nil { return serverCaps, err } walker.SetLogger(lh.logger) - + walker.SetExcludeModulePaths(excludeModulePaths) // Walker runs asynchronously so we're intentionally *not* // passing the request context here bCtx := context.Background() @@ -139,15 +150,15 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam } func resolvePath(rootDir, rawPath string) (string, error) { - rawPath, err := homedir.Expand(rawPath) + path, err := homedir.Expand(rawPath) if err != nil { return "", err } - if filepath.IsAbs(rawPath) { - return filepath.EvalSymlinks(rawPath) + if !filepath.IsAbs(path) { + path = filepath.Join(rootDir, rawPath) } - path := filepath.Join(rootDir, rawPath) - return filepath.EvalSymlinks(path) + absPath, err := filepath.EvalSymlinks(path) + return rootmodule.ToLowerVolumePath(absPath), err } From 22c402d6f3315dde335e8cd9d306ac71fdded7a8 Mon Sep 17 00:00:00 2001 From: njucz <740360112@qq.com> Date: Wed, 5 Aug 2020 11:35:36 +0800 Subject: [PATCH 2/3] update --- internal/terraform/rootmodule/walker.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/terraform/rootmodule/walker.go b/internal/terraform/rootmodule/walker.go index d77ecead9..83db1193c 100644 --- a/internal/terraform/rootmodule/walker.go +++ b/internal/terraform/rootmodule/walker.go @@ -32,7 +32,7 @@ type Walker struct { cancelFunc context.CancelFunc doneCh <-chan struct{} - excludeModulePaths []string + excludeModulePaths map[string]bool } func NewWalker() *Walker { @@ -48,7 +48,10 @@ func (w *Walker) SetLogger(logger *log.Logger) { } func (w *Walker) SetExcludeModulePaths(excludeModulePaths []string) { - w.excludeModulePaths = excludeModulePaths + w.excludeModulePaths = make(map[string]bool) + for _, path := range excludeModulePaths { + w.excludeModulePaths[path] = true + } } type WalkFunc func(ctx context.Context, rootModulePath string) error @@ -112,11 +115,6 @@ func (w *Walker) IsWalking() bool { func (w *Walker) walk(ctx context.Context, rootPath string, wf WalkFunc) error { defer w.Stop() - excludePathMap := make(map[string]bool) - for _, path := range w.excludeModulePaths { - excludePathMap[path] = true - } - err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error { select { case <-w.doneCh: @@ -135,7 +133,7 @@ func (w *Walker) walk(ctx context.Context, rootPath string, wf WalkFunc) error { return err } - if _, ok := excludePathMap[dir]; ok { + if _, ok := w.excludeModulePaths[dir]; ok { w.logger.Printf("successfully exclude root_module: %s", dir) return filepath.SkipDir } From fa118e3606cd80e837a255561531c86a641522eb Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Wed, 5 Aug 2020 08:27:02 +0200 Subject: [PATCH 3/3] move & unexport ToLowerVolumePath --- internal/terraform/rootmodule/path.go | 5 ----- langserver/handlers/initialize.go | 9 +++++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/terraform/rootmodule/path.go b/internal/terraform/rootmodule/path.go index eeba6f259..dcba40d18 100644 --- a/internal/terraform/rootmodule/path.go +++ b/internal/terraform/rootmodule/path.go @@ -10,8 +10,3 @@ func pathEquals(path1, path2 string) bool { volume2 := filepath.VolumeName(path2) return strings.EqualFold(volume1, volume2) && path1[len(volume1):] == path2[len(volume2):] } - -func ToLowerVolumePath(path string) string { - volume := filepath.VolumeName(path) - return strings.ToLower(volume) + path[len(volume):] -} diff --git a/langserver/handlers/initialize.go b/langserver/handlers/initialize.go index 4fd47b9bd..3824510d9 100644 --- a/langserver/handlers/initialize.go +++ b/langserver/handlers/initialize.go @@ -4,12 +4,12 @@ import ( "context" "fmt" "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/settings" - "github.com/hashicorp/terraform-ls/internal/terraform/rootmodule" "github.com/mitchellh/go-homedir" lsp "github.com/sourcegraph/go-lsp" ) @@ -160,5 +160,10 @@ func resolvePath(rootDir, rawPath string) (string, error) { } absPath, err := filepath.EvalSymlinks(path) - return rootmodule.ToLowerVolumePath(absPath), err + return toLowerVolumePath(absPath), err +} + +func toLowerVolumePath(path string) string { + volume := filepath.VolumeName(path) + return strings.ToLower(volume) + path[len(volume):] }