Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for tfvars (variable files) #540

Merged
merged 1 commit into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/hashicorp/terraform-ls
go 1.13

require (
github.com/agext/levenshtein v1.2.2 // indirect
github.com/apparentlymart/go-textseg v1.0.0
github.com/creachadair/jrpc2 v0.17.0
github.com/fsnotify/fsnotify v1.4.9
Expand All @@ -16,7 +17,8 @@ require (
github.com/hashicorp/terraform-exec v0.13.3
github.com/hashicorp/terraform-json v0.11.0
github.com/hashicorp/terraform-registry-address v0.0.0-20210412075316-9b2996cce896
github.com/hashicorp/terraform-schema v0.0.0-20210522075401-0f5e258f5e97
github.com/hashicorp/terraform-schema v0.0.0-20210601142728-f0b01c296a30
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mh-cbon/go-fmt-fail v0.0.0-20160815164508-67765b3fbcb5
github.com/mitchellh/cli v1.1.2
github.com/mitchellh/go-homedir v1.1.0
Expand Down
11 changes: 3 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -186,29 +186,25 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl-lang v0.0.0-20210522074354-f7480edf31b5 h1:lgywSdFExtTcqjaenkU2xhnbmtYLJIW+Ch3qQW0z6Jg=
github.com/hashicorp/hcl-lang v0.0.0-20210522074354-f7480edf31b5/go.mod h1:yPc3ggegh0njWLfIBPbmTk6a5T/vJVsMm4z6IuEgePU=
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
github.com/hashicorp/hcl/v2 v2.10.0 h1:1S1UnuhDGlv3gRFV4+0EdwB+znNP5HmcGbIqwnSCByg=
github.com/hashicorp/hcl/v2 v2.10.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/terraform-config-inspect v0.0.0-20210318070130-9a80970d6b34 h1:y4kOB9aYVSsJWVqewwUZmHxPSNjkDbOeW7eb9yFIc3Q=
github.com/hashicorp/terraform-config-inspect v0.0.0-20210318070130-9a80970d6b34/go.mod h1:Z0Nnk4+3Cy89smEbrq+sl1bxc9198gIP4I7wcQF6Kqs=
github.com/hashicorp/terraform-exec v0.13.3 h1:R6L2mNpDGSEqtLrSONN8Xth0xYwNrnEVzDz6LF/oJPk=
github.com/hashicorp/terraform-exec v0.13.3/go.mod h1:SSg6lbUsVB3DmFyCPjBPklqf6EYGX0TlQ6QTxOlikDU=
github.com/hashicorp/terraform-json v0.10.0/go.mod h1:3defM4kkMfttwiE7VakJDwCd4R+umhSQnvJwORXbprE=
github.com/hashicorp/terraform-json v0.11.0 h1:4zDqqW2F3kOysORIaYKFGgWDYIRA3hwqx3XHeHkbBQ0=
github.com/hashicorp/terraform-json v0.11.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI=
github.com/hashicorp/terraform-registry-address v0.0.0-20210412075316-9b2996cce896 h1:1FGtlkJw87UsTMg5s8jrekrHmUPUJaMcu6ELiVhQrNw=
github.com/hashicorp/terraform-registry-address v0.0.0-20210412075316-9b2996cce896/go.mod h1:bzBPnUIkI0RxauU8Dqo+2KrZZ28Cf48s8V6IHt3p4co=
github.com/hashicorp/terraform-schema v0.0.0-20210522075401-0f5e258f5e97 h1:ajIMzYZuMyoTVuUvfeXR9pNCJ52Wk6W9ukxYPwtaV3c=
github.com/hashicorp/terraform-schema v0.0.0-20210522075401-0f5e258f5e97/go.mod h1:hXxoH61q0kSvc4vlCxHEmV47u9Gp/1mXnuI7Yhz7jsQ=
github.com/hashicorp/terraform-schema v0.0.0-20210601142728-f0b01c296a30 h1:gASv/NUeM0zNrg6hvV50Fb3+Pe/fQQDTHiagiC31GQw=
github.com/hashicorp/terraform-schema v0.0.0-20210601142728-f0b01c296a30/go.mod h1:8Zx/D3N5rNnk4SrNXQgdxq8+hkRdQtu67OT8Kxr8U60=
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0=
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
Expand Down Expand Up @@ -273,9 +269,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
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/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
Expand Down
3 changes: 2 additions & 1 deletion internal/cmd/completion_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ func (c *CompletionCommand) Run(args []string) int {
return 1
}

schema, err := modMgr.SchemaForModule(fh.Dir())
schema, err := modMgr.SchemaForModule(file.Dir())

if err != nil {
c.Ui.Error(fmt.Sprintf("failed to find schema: %s", err.Error()))
return 1
Expand Down
8 changes: 6 additions & 2 deletions internal/cmd/inspect_module_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,12 @@ func (c *InspectModuleCommand) inspect(rootPath string) error {
multierror.Append(errs, mod.ModManifestErr)
}

if mod.ParsingErr != nil {
multierror.Append(errs, mod.ParsingErr)
if mod.ModuleParsingErr != nil {
multierror.Append(errs, mod.ModuleParsingErr)
}

if mod.VarsParsingErr != nil {
multierror.Append(errs, mod.VarsParsingErr)
}

errs.ErrorFormat = formatErrors
Expand Down
33 changes: 29 additions & 4 deletions internal/decoder/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/hashicorp/hcl-lang/decoder"
"github.com/hashicorp/hcl-lang/lang"
"github.com/hashicorp/hcl/v2"
lsctx "github.com/hashicorp/terraform-ls/internal/context"
"github.com/hashicorp/terraform-ls/internal/terraform/module"
)
Expand All @@ -25,12 +26,36 @@ func DecoderForModule(ctx context.Context, mod module.Module) (*decoder.Decoder,
d.SetUtmMedium(clientName)
}

for name, f := range mod.ParsedFiles {
err := loadFiles(d, mod.ParsedModuleFiles)
if err != nil {
return nil, err
}

return d, nil
}

func DecoderForVariables(mod module.Module) (*decoder.Decoder, error) {
d := decoder.NewDecoder()

err := loadFiles(d, mod.ParsedModuleFiles)
if err != nil {
return nil, err
}

err = loadFiles(d, mod.ParsedVarsFiles)
if err != nil {
return nil, err
}
radeksimko marked this conversation as resolved.
Show resolved Hide resolved

return d, nil
}

func loadFiles(d *decoder.Decoder, files map[string]*hcl.File) error {
for name, f := range files {
err := d.LoadFile(name, f)
if err != nil {
return nil, fmt.Errorf("failed to load a file: %w", err)
return fmt.Errorf("failed to load a file: %w", err)
}
}

return d, nil
return nil
}
5 changes: 2 additions & 3 deletions internal/langserver/handlers/complete.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"

lsctx "github.com/hashicorp/terraform-ls/internal/context"
"github.com/hashicorp/terraform-ls/internal/decoder"
ilsp "github.com/hashicorp/terraform-ls/internal/lsp"
lsp "github.com/hashicorp/terraform-ls/internal/protocol"
)
Expand Down Expand Up @@ -37,12 +36,12 @@ func (h *logHandler) TextDocumentComplete(ctx context.Context, params lsp.Comple
return list, err
}

schema, err := mf.SchemaForModule(file.Dir())
schema, err := schemaForDocument(mf, file)
if err != nil {
return list, err
}

d, err := decoder.DecoderForModule(ctx, mod)
d, err := decoderForDocument(ctx, mod, file.LanguageID())
if err != nil {
return list, err
}
Expand Down
124 changes: 118 additions & 6 deletions internal/langserver/handlers/complete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/mock"
)

func TestCompletion_withoutInitialization(t *testing.T) {
func TestModuleCompletion_withoutInitialization(t *testing.T) {
ls := langserver.NewLangServerMock(t, NewMockSession(nil))
stop := ls.Start(t)
defer stop()
Expand All @@ -31,12 +31,12 @@ func TestCompletion_withoutInitialization(t *testing.T) {
}`, TempDir(t).URI())}, session.SessionNotInitialized.Err())
}

func TestCompletion_withValidData(t *testing.T) {
func TestModuleCompletion_withValidData(t *testing.T) {
tmpDir := TempDir(t)
InitPluginCache(t, tmpDir.Dir())

var testSchema tfjson.ProviderSchemas
err := json.Unmarshal([]byte(testSchemaOutput), &testSchema)
err := json.Unmarshal([]byte(testModuleSchemaOutput), &testSchema)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -224,12 +224,12 @@ func TestCompletion_withValidData(t *testing.T) {
}`)
}

func TestCompletion_withValidDataAndSnippets(t *testing.T) {
func TestModuleCompletion_withValidDataAndSnippets(t *testing.T) {
tmpDir := TempDir(t)
InitPluginCache(t, tmpDir.Dir())

var testSchema tfjson.ProviderSchemas
err := json.Unmarshal([]byte(testSchemaOutput), &testSchema)
err := json.Unmarshal([]byte(testModuleSchemaOutput), &testSchema)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -437,7 +437,7 @@ func TestCompletion_withValidDataAndSnippets(t *testing.T) {
}`)
}

var testSchemaOutput = `{
var testModuleSchemaOutput = `{
"format_version": "0.1",
"provider_schemas": {
"test/test": {
Expand Down Expand Up @@ -483,3 +483,115 @@ var testSchemaOutput = `{
}
}
}`

func TestVarsCompletion_withValidData(t *testing.T) {
tmpDir := TempDir(t)
InitPluginCache(t, tmpDir.Dir())

var testSchema tfjson.ProviderSchemas
err := json.Unmarshal([]byte(testModuleSchemaOutput), &testSchema)
if err != nil {
t.Fatal(err)
}

ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{
TerraformCalls: &exec.TerraformMockCalls{
PerWorkDir: map[string][]*mock.Call{
tmpDir.Dir(): {
{
Method: "Version",
Repeatability: 1,
Arguments: []interface{}{
mock.AnythingOfType(""),
},
ReturnArguments: []interface{}{
version.Must(version.NewVersion("0.12.0")),
nil,
nil,
},
},
{
Method: "GetExecPath",
Repeatability: 1,
ReturnArguments: []interface{}{
"",
},
},
{
Method: "ProviderSchemas",
Repeatability: 1,
Arguments: []interface{}{
mock.AnythingOfType(""),
},
ReturnArguments: []interface{}{
&testSchema,
nil,
},
},
},
},
}}))
stop := ls.Start(t)
defer stop()

ls.Call(t, &langserver.CallRequest{
Method: "initialize",
ReqParams: fmt.Sprintf(`{
"capabilities": {},
"rootUri": %q,
"processId": 12345
}`, tmpDir.URI())})
ls.Notify(t, &langserver.CallRequest{
Method: "initialized",
ReqParams: "{}",
})
ls.Call(t, &langserver.CallRequest{
Method: "textDocument/didOpen",
ReqParams: fmt.Sprintf(`{
"textDocument": {
"version": 0,
"languageId": "terraform",
"text": "variable \"test\" {\n type=string\n}\n",
"uri": "%s/variables.tf"
}
}`, tmpDir.URI())})
ls.Call(t, &langserver.CallRequest{
Method: "textDocument/didOpen",
ReqParams: fmt.Sprintf(`{
"textDocument": {
"version": 0,
"languageId": "terraform-vars",
"uri": "%s/terraform.tfvars"
}
}`, tmpDir.URI())})

ls.CallAndExpectResponse(t, &langserver.CallRequest{
Method: "textDocument/completion",
ReqParams: fmt.Sprintf(`{
"textDocument": {
"uri": "%s/terraform.tfvars"
},
"position": {
"character": 0,
"line": 0
}
}`, tmpDir.URI())}, `{
"jsonrpc": "2.0",
"id": 4,
"result": {
"isIncomplete": false,
"items": [
{
"label": "test",
"kind": 10,
"detail": "string",
"insertTextFormat":1,
"textEdit": {
"range": {"start":{"line":0,"character":0}, "end":{"line":0,"character":0}},
"newText":"test"
}
}
]
}
}`)
}
10 changes: 8 additions & 2 deletions internal/langserver/handlers/did_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ func TextDocumentDidChange(ctx context.Context, params lsp.DidChangeTextDocument
return err
}

err = modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeParseConfiguration)
err = modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeParseModuleConfiguration)
if err != nil {
return err
}
err = modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeParseVariables)
if err != nil {
return err
}
Expand All @@ -82,7 +86,9 @@ func TextDocumentDidChange(ctx context.Context, params lsp.DidChangeTextDocument
if err != nil {
return err
}
diags.PublishHCLDiags(ctx, mod.Path, mod.Diagnostics, "HCL")

mergedDiags := mergeDiagnostics(mod.ModuleDiagnostics, mod.VarsDiagnostics)
diags.PublishHCLDiags(ctx, mod.Path, mergedDiags, "HCL")

return nil
}
6 changes: 4 additions & 2 deletions internal/langserver/handlers/did_open.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe
// We reparse because the file being opened may not match
// (originally parsed) content on the disk
// TODO: Do this only if we can verify the file differs?
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeParseConfiguration)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeParseModuleConfiguration)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeParseVariables)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeLoadModuleMetadata)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeDecodeReferences)

Expand All @@ -70,7 +71,8 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe
if err != nil {
return err
}
diags.PublishHCLDiags(ctx, mod.Path, mod.Diagnostics, "HCL")
mergedDiags := mergeDiagnostics(mod.ModuleDiagnostics, mod.VarsDiagnostics)
diags.PublishHCLDiags(ctx, mod.Path, mergedDiags, "HCL")

return nil
}
4 changes: 4 additions & 0 deletions internal/langserver/handlers/document_link.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func (h *logHandler) TextDocumentLink(ctx context.Context, params lsp.DocumentLi
return nil, err
}

if file.LanguageID() != ilsp.Terraform.String() {
return nil, nil
}

mod, err := mf.ModuleByPath(file.Dir())
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion internal/langserver/handlers/document_link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestDocumentLink_withValidData(t *testing.T) {
InitPluginCache(t, tmpDir.Dir())

var testSchema tfjson.ProviderSchemas
err := json.Unmarshal([]byte(testSchemaOutput), &testSchema)
err := json.Unmarshal([]byte(testModuleSchemaOutput), &testSchema)
if err != nil {
t.Fatal(err)
}
Expand Down
Loading