Skip to content

Commit aa5fa0d

Browse files
authored
settings: break down indexing options (#1010)
1 parent 922d187 commit aa5fa0d

File tree

6 files changed

+81
-37
lines changed

6 files changed

+81
-37
lines changed

docs/SETTINGS.md

+26-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Settings
22

3+
## Data Structures
4+
5+
We use (JSON) objects to group some config options. Where applicable and necessary, we refer to nested fields using the `.` as a separator. i.e. A hypothetical `bar` option under `{"foo": { "bar": "..." } }` would be referred to as `foo.bar`.
6+
7+
Clients which expose these config options to the end-user are advised to match the option names and, if possible data structures. Some clients (VS Code extension) may however use flat structure, such as `{"foo.bar": "..."}` if using objects is not possible or practical.
8+
39
## Supported Options
410

511
The language server supports the following configuration options:
@@ -35,9 +41,11 @@ you can just add that folder to the workspace and it will be indexed as usual.
3541

3642
## **DEPRECATED**: `excludeModulePaths` (`[]string`)
3743

38-
Deprecated in favour of `ignorePaths`
44+
Deprecated in favour of `indexing.ignorePaths`
3945

40-
## `indexing.ignorePaths` (`[]string`)
46+
## `indexing` (object `{}`)
47+
48+
### `ignorePaths` (`[]string`)
4149

4250
Paths to ignore when indexing the workspace on initialization. This can serve
4351
as an escape hatch in large workspaces. Key side effect of ignoring a path
@@ -52,6 +60,22 @@ of the target platform (e.g. `\` on Windows, or `/` on Unix),
5260
symlinks are followed, trailing slashes automatically removed,
5361
and `~` is replaced with your home directory.
5462

63+
## `ignoreDirectoryNames` (`[]string`)
64+
65+
This allows excluding directories from being indexed upon initialization by passing a list of directory names.
66+
67+
The following list of directories will always be ignored:
68+
69+
- `.git`
70+
- `.idea`
71+
- `.vscode`
72+
- `terraform.tfstate.d`
73+
- `.terragrunt-cache`
74+
75+
## **DEPRECATED**: `ignoreDirectoryNames` (`[]string`)
76+
77+
Deprecated in favour of `indexing.ignoreDirectoryNames`
78+
5579
## `commandPrefix`
5680

5781
Some clients such as VS Code keep a global registry of commands published by language
@@ -72,22 +96,6 @@ Or if left empty
7296
This setting should be deprecated once the language server supports multiple workspaces,
7397
as this arises in VS code because a server instance is started per VS Code workspace.
7498

75-
## **DEPRECATED**: `ignoreDirectoryNames` (`[]string`)
76-
77-
Deprecated in favour of `indexing.ignoreDirectoryNames`
78-
79-
## `indexing.ignoreDirectoryNames` (`[]string`)
80-
81-
This allows excluding directories from being indexed upon initialization by passing a list of directory names.
82-
83-
The following list of directories will always be ignored:
84-
85-
- `.git`
86-
- `.idea`
87-
- `.vscode`
88-
- `terraform.tfstate.d`
89-
- `.terragrunt-cache`
90-
9199
## `ignoreSingleFileWarning` (`bool`)
92100

93101
This setting controls whether terraform-ls sends a warning about opening up a single Terraform file instead of a Terraform folder. Setting this to `true` will prevent the message being sent. The default value is `false`.

docs/language-clients.md

+21
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,27 @@ Clients specifically should **not** send `*.tf.json`, `*.tfvars.json` nor
1616
Packer HCL config nor any other HCL config files as the server is not
1717
equipped to handle these file types.
1818

19+
## Configuration
20+
21+
Unless the client allows the end-user to pass arbitrary config options (e.g.
22+
generic Sublime Text LSP package without Terraform LSP package), the client
23+
should expose configuration as per [SETTINGS.md](./SETTINGS.md).
24+
25+
Client should match the option names exactly, and if possible match the
26+
underlying data structures too. i.e. if a field is documented as `ignoreDirectoryNames`,
27+
it should be exposed as `ignoreDirectoryNames`, **not** ~`IgnoreDirectoryNames`~,
28+
or ~`ignore_directory_names`~. This is to avoid user confusion when the server
29+
refers to any config option in informative, warning, or error messages.
30+
31+
Client may use a flat structure using the `.` (single dot) as a separator between
32+
the object name and option nested under it, such as `{ "foo.bar": "..." }` instead
33+
of `{ "foo": { "bar": "..." } }`. This is acceptable in situations when using
34+
objects is not possible or practical (e.g. VS Code wouldn't display objects
35+
in the Settings UI).
36+
37+
The server will generally refer to options using the `.` address, for simplicity
38+
and avoidance of doubts.
39+
1940
## Watched Files
2041

2142
The server (`>= 0.28.0`) supports `workspace/didChangeWatchedFiles` notifications.

internal/langserver/handlers/initialize.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ func getTelemetryProperties(out *settings.DecodedOptions) map[string]interface{}
174174
"options.rootModulePaths": false,
175175
"options.excludeModulePaths": false,
176176
"options.commandPrefix": false,
177-
"options.ignoreDirectoryNames": false,
177+
"options.indexing.ignoreDirectoryNames": false,
178+
"options.indexing.ignorePaths": false,
178179
"options.experimentalFeatures.validateOnSave": false,
179180
"options.terraformExecPath": false,
180181
"options.terraformExecTimeout": "",
@@ -186,8 +187,8 @@ func getTelemetryProperties(out *settings.DecodedOptions) map[string]interface{}
186187
properties["options.rootModulePaths"] = len(out.Options.XLegacyModulePaths) > 0
187188
properties["options.excludeModulePaths"] = len(out.Options.XLegacyExcludeModulePaths) > 0
188189
properties["options.commandPrefix"] = len(out.Options.CommandPrefix) > 0
189-
properties["options.indexing.ignoreDirectoryNames"] = len(out.Options.IgnoreDirectoryNames) > 0
190-
properties["options.indexing.ignorePaths"] = len(out.Options.IgnorePaths) > 0
190+
properties["options.indexing.ignoreDirectoryNames"] = len(out.Options.Indexing.IgnoreDirectoryNames) > 0
191+
properties["options.indexing.ignorePaths"] = len(out.Options.Indexing.IgnorePaths) > 0
191192
properties["options.experimentalFeatures.prefillRequiredFields"] = out.Options.ExperimentalFeatures.PrefillRequiredFields
192193
properties["options.experimentalFeatures.validateOnSave"] = out.Options.ExperimentalFeatures.ValidateOnSave
193194
properties["options.ignoreSingleFileWarning"] = out.Options.IgnoreSingleFileWarning
@@ -271,7 +272,7 @@ func (svc *service) setupWalker(ctx context.Context, params lsp.InitializeParams
271272
}
272273

273274
var ignoredPaths []string
274-
for _, rawPath := range options.IgnorePaths {
275+
for _, rawPath := range options.Indexing.IgnorePaths {
275276
modPath, err := resolvePath(root.Path(), rawPath)
276277
if err != nil {
277278
jrpc2.ServerFromContext(ctx).Notify(ctx, "window/showMessage", &lsp.ShowMessageParams{
@@ -314,9 +315,9 @@ func (svc *service) setupWalker(ctx context.Context, params lsp.InitializeParams
314315
}
315316
}
316317

317-
svc.closedDirWalker.SetIgnoredDirectoryNames(options.IgnoreDirectoryNames)
318+
svc.closedDirWalker.SetIgnoredDirectoryNames(options.Indexing.IgnoreDirectoryNames)
318319
svc.closedDirWalker.SetIgnoredPaths(ignoredPaths)
319-
svc.openDirWalker.SetIgnoredDirectoryNames(options.IgnoreDirectoryNames)
320+
svc.openDirWalker.SetIgnoredDirectoryNames(options.Indexing.IgnoreDirectoryNames)
320321
svc.openDirWalker.SetIgnoredPaths(ignoredPaths)
321322

322323
return nil

internal/langserver/handlers/initialize_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,9 @@ func TestInitialize_ignoreDirectoryNames(t *testing.T) {
196196
"rootUri": %q,
197197
"processId": 12345,
198198
"initializationOptions": {
199-
"indexing.ignoreDirectoryNames": [%q]
199+
"indexing": {
200+
"ignoreDirectoryNames": [%q]
201+
}
200202
}
201203
}`, tmpDir.URI, "ignore")})
202204
waitForWalkerPath(t, ss, wc, tmpDir)

internal/settings/settings.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ type ExperimentalFeatures struct {
1515
PrefillRequiredFields bool `mapstructure:"prefillRequiredFields"`
1616
}
1717

18+
type Indexing struct {
19+
IgnoreDirectoryNames []string `mapstructure:"ignoreDirectoryNames"`
20+
IgnorePaths []string `mapstructure:"ignorePaths"`
21+
}
22+
1823
type Options struct {
19-
CommandPrefix string `mapstructure:"commandPrefix"`
20-
IgnoreDirectoryNames []string `mapstructure:"indexing.ignoreDirectoryNames"`
21-
IgnorePaths []string `mapstructure:"indexing.ignorePaths"`
24+
CommandPrefix string `mapstructure:"commandPrefix"`
25+
Indexing Indexing `mapstructure:"indexing"`
2226

2327
// ExperimentalFeatures encapsulates experimental features users can opt into.
2428
ExperimentalFeatures ExperimentalFeatures `mapstructure:"experimentalFeatures"`
@@ -49,8 +53,8 @@ func (o *Options) Validate() error {
4953
}
5054
}
5155

52-
if len(o.IgnoreDirectoryNames) > 0 {
53-
for _, directory := range o.IgnoreDirectoryNames {
56+
if len(o.Indexing.IgnoreDirectoryNames) > 0 {
57+
for _, directory := range o.Indexing.IgnoreDirectoryNames {
5458
if directory == datadir.DataDirName {
5559
return fmt.Errorf("cannot ignore directory %q", datadir.DataDirName)
5660
}

internal/settings/settings_test.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@ func TestDecodeOptions_nil(t *testing.T) {
1616
}
1717
opts := out.Options
1818

19-
if opts.IgnoreDirectoryNames != nil {
20-
t.Fatalf("expected no options for nil, %#v given", opts.IgnoreDirectoryNames)
19+
if opts.Indexing.IgnoreDirectoryNames != nil {
20+
t.Fatalf("expected no options for nil, %#v given", opts.Indexing.IgnoreDirectoryNames)
2121
}
2222
}
2323

2424
func TestDecodeOptions_wrongType(t *testing.T) {
2525
_, err := DecodeOptions(map[string]interface{}{
26-
"indexing.ignorePaths": "/random/path",
26+
"indexing": map[string]interface{}{
27+
"ignorePaths": "/random/path",
28+
},
2729
})
2830
if err == nil {
2931
t.Fatal("expected decoding of wrong type to result in error")
@@ -32,14 +34,16 @@ func TestDecodeOptions_wrongType(t *testing.T) {
3234

3335
func TestDecodeOptions_success(t *testing.T) {
3436
out, err := DecodeOptions(map[string]interface{}{
35-
"indexing.ignorePaths": []string{"/random/path"},
37+
"indexing": map[string]interface{}{
38+
"ignorePaths": []string{"/random/path"},
39+
},
3640
})
3741
if err != nil {
3842
t.Fatal(err)
3943
}
4044
opts := out.Options
4145
expectedPaths := []string{"/random/path"}
42-
if diff := cmp.Diff(expectedPaths, opts.IgnorePaths); diff != "" {
46+
if diff := cmp.Diff(expectedPaths, opts.Indexing.IgnorePaths); diff != "" {
4347
t.Fatalf("options mismatch: %s", diff)
4448
}
4549
}
@@ -55,7 +59,9 @@ func TestValidate_IgnoreDirectoryNames_error(t *testing.T) {
5559

5660
for _, table := range tables {
5761
out, err := DecodeOptions(map[string]interface{}{
58-
"indexing.ignoreDirectoryNames": []string{table.input},
62+
"indexing": map[string]interface{}{
63+
"ignoreDirectoryNames": []string{table.input},
64+
},
5965
})
6066
if err != nil {
6167
t.Fatal(err)
@@ -69,7 +75,9 @@ func TestValidate_IgnoreDirectoryNames_error(t *testing.T) {
6975
}
7076
func TestValidate_IgnoreDirectoryNames_success(t *testing.T) {
7177
out, err := DecodeOptions(map[string]interface{}{
72-
"indexing.ignoreDirectoryNames": []string{"directory"},
78+
"indexing": map[string]interface{}{
79+
"ignoreDirectoryNames": []string{"directory"},
80+
},
7381
})
7482
if err != nil {
7583
t.Fatal(err)

0 commit comments

Comments
 (0)