Skip to content

Commit

Permalink
settings: Make root modules configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Jul 7, 2020
1 parent aa04dcc commit 8bd954d
Show file tree
Hide file tree
Showing 16 changed files with 2,003 additions and 2 deletions.
44 changes: 44 additions & 0 deletions docs/SETTINGS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Settings

## Supported Options

The language server supports the following configuration options:

## `rootModulePaths` (`[]string`)

This allows overriding automatic root module discovery by passing a static list
of absolute paths to root modules (i.e. folders with `*.tf` files
which have been `terraform init`-ed).

## How to pass settings

The server expects static settings to be passed as part of LSP `initialize` call,
but how settings are requested from on the UI side depends on the client.

### Sublime Text

Use `initializationOptions` key under the `clients.terraform` section, e.g.

```json
{
"clients": {
"terraform": {
"initializationOptions": {
"rootModulePaths": ["/any/path"]
},
}
}
}
```

### VS Code

Use `terraform-ls.options`, e.g.

```json
{
"terraform-ls.options": {
"rootModulePaths": ["/any/path"]
}
}
```
5 changes: 4 additions & 1 deletion docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ in the [README.md](../README.md) if that is applicable to your client
(i.e. if the client doesn't download the server itself).

Instructions for popular IDEs are below and pull requests
for updates or addition of more IDEs are welcomed.
for updates or addition of more IDEs are welcomed.

See also [settings](./SETTINGS.md) to understand
how you may configure the settings.

## Emacs

Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ require (
github.com/creachadair/jrpc2 v0.8.1
github.com/fsnotify/fsnotify v1.4.9
github.com/google/go-cmp v0.4.0
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.0
github.com/hashicorp/go-version v1.2.0
github.com/hashicorp/hcl/v2 v2.5.2-0.20200528183353-fa7c453538de
github.com/hashicorp/terraform-json v0.5.0
github.com/mh-cbon/go-fmt-fail v0.0.0-20160815164508-67765b3fbcb5
github.com/mitchellh/cli v1.0.0
github.com/mitchellh/mapstructure v1.3.2
github.com/pmezard/go-difflib v1.0.0
github.com/sourcegraph/go-lsp v0.0.0-20200117082640-b19bb38222e2
github.com/zclconf/go-cty v1.2.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
Expand Down
59 changes: 59 additions & 0 deletions internal/settings/settings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package settings

import (
"fmt"
"path/filepath"

"github.com/hashicorp/go-multierror"
"github.com/mitchellh/mapstructure"
)

type Options struct {
// RootModulePaths describes a list of absolute paths to root modules
RootModulePaths []string `mapstructure:"rootModulePaths"`

// TODO: Need to check for conflict with CLI flags
// TerraformExecPath string
// TerraformExecTimeout time.Duration
// TerraformLogFilePath string
}

func (o *Options) Validate() error {
var result *multierror.Error

for _, p := range o.RootModulePaths {
if !filepath.IsAbs(p) {
result = multierror.Append(result, fmt.Errorf("%q is not an absolute path", p))
}
}

return result.ErrorOrNil()
}

type DecodedOptions struct {
Options *Options
UnusedKeys []string
}

func DecodeOptions(input interface{}) (*DecodedOptions, error) {
var md mapstructure.Metadata
var options Options

config := &mapstructure.DecoderConfig{
Metadata: &md,
Result: &options,
}
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
panic(err)
}

if err := decoder.Decode(input); err != nil {
return nil, err
}

return &DecodedOptions{
Options: &options,
UnusedKeys: md.Unused,
}, nil
}
54 changes: 54 additions & 0 deletions internal/settings/settings_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package settings

import (
"testing"

"github.com/google/go-cmp/cmp"
)

func TestDecodeOptions_nil(t *testing.T) {
out, err := DecodeOptions(nil)
if err != nil {
t.Fatal(err)
}
opts := out.Options

if opts.RootModulePaths != nil {
t.Fatalf("expected no options for nil, %#v given", opts.RootModulePaths)
}
}

func TestDecodeOptions_wrongType(t *testing.T) {
_, err := DecodeOptions(map[string]interface{}{
"rootModulePaths": "/random/path",
})
if err == nil {
t.Fatal("expected decoding of wrong type to result in error")
}
}

func TestDecodeOptions_success(t *testing.T) {
out, err := DecodeOptions(map[string]interface{}{
"rootModulePaths": []string{"/random/path"},
})
if err != nil {
t.Fatal(err)
}
opts := out.Options
expectedPaths := []string{"/random/path"}
if diff := cmp.Diff(expectedPaths, opts.RootModulePaths); diff != "" {
t.Fatalf("options mismatch: %s", diff)
}
}

func TestDecodedOptions_Validate(t *testing.T) {
opts := &Options{
RootModulePaths: []string{
"./relative/path",
},
}
err := opts.Validate()
if err == nil {
t.Fatal("expected relative path to fail validation")
}
}
37 changes: 37 additions & 0 deletions langserver/handlers/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"context"
"fmt"

"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"
lsp "github.com/sourcegraph/go-lsp"
)

Expand Down Expand Up @@ -54,6 +56,41 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam
return serverCaps, err
}

out, err := settings.DecodeOptions(params.InitializationOptions)
if err != nil {
return serverCaps, err
}
err = out.Options.Validate()
if err != nil {
return serverCaps, err
}
if len(out.UnusedKeys) > 0 {
jrpc2.ServerPush(ctx, "window/showMessage", &lsp.ShowMessageParams{
Type: lsp.MTWarning,
Message: fmt.Sprintf("Unknown configuration options: %q", out.UnusedKeys),
})
}
cfgOpts := out.Options

if len(cfgOpts.RootModulePaths) > 0 {
lh.logger.Printf("Attempting to add %d static root module paths", len(cfgOpts.RootModulePaths))
for _, rmPath := range cfgOpts.RootModulePaths {
rm, err := rmm.AddRootModule(rmPath)
if err != nil {
return serverCaps, err
}

paths := rm.PathsToWatch()
lh.logger.Printf("Adding %d paths of root module for watching (%s)", len(paths), rmPath)
err = w.AddPaths(paths)
if err != nil {
return serverCaps, err
}
}

return serverCaps, nil
}

walker, err := lsctx.RootModuleWalker(ctx)
if err != nil {
return serverCaps, err
Expand Down
9 changes: 9 additions & 0 deletions vendor/github.com/mitchellh/mapstructure/.travis.yml

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

57 changes: 57 additions & 0 deletions vendor/github.com/mitchellh/mapstructure/CHANGELOG.md

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

21 changes: 21 additions & 0 deletions vendor/github.com/mitchellh/mapstructure/LICENSE

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

46 changes: 46 additions & 0 deletions vendor/github.com/mitchellh/mapstructure/README.md

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

Loading

0 comments on commit 8bd954d

Please sign in to comment.