Skip to content

Commit

Permalink
Add support for traversals/references
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed May 12, 2021
1 parent dd44a50 commit 4e9a443
Show file tree
Hide file tree
Showing 15 changed files with 401 additions and 15 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ require (
github.com/hashicorp/go-memdb v1.3.2
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-version v1.3.0
github.com/hashicorp/hcl-lang v0.0.0-20210419185146-8556dd730bc7
github.com/hashicorp/hcl-lang v0.0.0-20210512121258-36c95c16ab9b
github.com/hashicorp/hcl/v2 v2.10.0
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-20210428174709-ad0461b43827
github.com/hashicorp/terraform-schema v0.0.0-20210512121524-beeef55dfd93
github.com/mh-cbon/go-fmt-fail v0.0.0-20160815164508-67765b3fbcb5
github.com/mitchellh/cli v1.1.2
github.com/mitchellh/copystructure v1.2.0
Expand Down
12 changes: 4 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,9 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
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-20210419185146-8556dd730bc7 h1:6ajS9kFs/7UnRcy3dHThUnmicqU7VjGUn0RLOT6Ewq0=
github.com/hashicorp/hcl-lang v0.0.0-20210419185146-8556dd730bc7/go.mod h1:VRVfqufUmJSpWsoWDtYV/BejqCV+NNyS9V9vR0dcivs=
github.com/hashicorp/hcl-lang v0.0.0-20210512121258-36c95c16ab9b h1:fzQJzvomUtXs+1x3zkb+vs0xisnXgV3sbNeBPfquMRQ=
github.com/hashicorp/hcl-lang v0.0.0-20210512121258-36c95c16ab9b/go.mod h1:7BtIzYAy75UR501SFkNjL98xMZbvn5Vc7bj+dOgcH70=
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
github.com/hashicorp/hcl/v2 v2.9.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
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=
Expand All @@ -207,8 +206,8 @@ github.com/hashicorp/terraform-json v0.11.0 h1:4zDqqW2F3kOysORIaYKFGgWDYIRA3hwqx
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-20210428174709-ad0461b43827 h1:wf2hrzKEi5WOZkp5U0GGLKsslbFrGob2GJ35rjwMiO0=
github.com/hashicorp/terraform-schema v0.0.0-20210428174709-ad0461b43827/go.mod h1:K3XjJOEolIgMNwNb/cVbSSO8nBxvO/JLDAuTOLbT7XQ=
github.com/hashicorp/terraform-schema v0.0.0-20210512121524-beeef55dfd93 h1:dQjPK03k0aP7K5AZQGfBr9GaKWyT+lXtyglhSTogofE=
github.com/hashicorp/terraform-schema v0.0.0-20210512121524-beeef55dfd93/go.mod h1:sX/cGqS5LiX0vpMaSjHfDwl5IbFcCpeeztFrv7MXo+s=
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 @@ -266,7 +265,6 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT
github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=
github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.1.2/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
Expand All @@ -284,7 +282,6 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down Expand Up @@ -383,7 +380,6 @@ github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLE
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty v1.8.2/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty v1.8.3 h1:48gwZXrdSADU2UW9eZKHprxAI7APZGW9XmExpJpSjT0=
github.com/zclconf/go-cty v1.8.3/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
Expand Down
6 changes: 6 additions & 0 deletions internal/decoder/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ import (
"fmt"

"github.com/hashicorp/hcl-lang/decoder"
"github.com/hashicorp/hcl-lang/lang"
lsctx "github.com/hashicorp/terraform-ls/internal/context"
"github.com/hashicorp/terraform-ls/internal/terraform/module"
)

func DecoderForModule(ctx context.Context, mod module.Module) (*decoder.Decoder, error) {
d := decoder.NewDecoder()

d.SetReferenceReader(func() lang.References {
return mod.References
})

d.SetUtmSource("terraform-ls")
d.UseUtmContent(true)

Expand Down
215 changes: 214 additions & 1 deletion internal/langserver/handlers/complete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestCompletion_withValidData(t *testing.T) {
ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{
TerraformCalls: &exec.TerraformMockCalls{
PerWorkDir: map[string][]*mock.Call{
tmpDir.Dir(): []*mock.Call{
tmpDir.Dir(): {
{
Method: "Version",
Repeatability: 1,
Expand Down Expand Up @@ -224,6 +224,219 @@ func TestCompletion_withValidData(t *testing.T) {
}`)
}

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

var testSchema tfjson.ProviderSchemas
err := json.Unmarshal([]byte(testSchemaOutput), &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": {
"textDocument": {
"completion": {
"completionItem": {
"snippetSupport": true
}
}
}
},
"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": "provider \"test\" {\n\n}\n",
"uri": "%s/main.tf"
}
}`, tmpDir.URI())})

ls.CallAndExpectResponse(t, &langserver.CallRequest{
Method: "textDocument/completion",
ReqParams: fmt.Sprintf(`{
"textDocument": {
"uri": "%s/main.tf"
},
"position": {
"character": 0,
"line": 1
}
}`, tmpDir.URI())}, `{
"jsonrpc": "2.0",
"id": 3,
"result": {
"isIncomplete": false,
"items": [
{
"label": "alias",
"kind": 10,
"detail": "Optional, string",
"documentation": "Alias for using the same provider with different configurations for different resources, e.g. eu-west",
"insertTextFormat": 2,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
},
"newText": "alias = \"${1:value}\""
}
},
{
"label": "anonymous",
"kind": 10,
"detail": "Optional, number",
"documentation": "Desc 1",
"insertTextFormat": 2,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
},
"newText": "anonymous = "
},
"command": {
"title": "Suggest",
"command": "editor.action.triggerSuggest"
}
},
{
"label": "base_url",
"kind": 10,
"detail": "Optional, string",
"documentation": "Desc 2",
"insertTextFormat": 2,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
},
"newText": "base_url = "
},
"command": {
"title": "Suggest",
"command": "editor.action.triggerSuggest"
}
},
{
"label": "individual",
"kind": 10,
"detail": "Optional, bool",
"documentation": "Desc 3",
"insertTextFormat": 2,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
},
"newText": "individual = "
},
"command": {
"title": "Suggest",
"command": "editor.action.triggerSuggest"
}
},
{
"label": "version",
"kind": 10,
"detail": "Optional, string",
"documentation": "Specifies a version constraint for the provider, e.g. ~\u003e 1.0",
"insertTextFormat": 2,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
},
"newText": "version = \"${1:value}\""
}
}
]
}
}`)
}

var testSchemaOutput = `{
"format_version": "0.1",
"provider_schemas": {
Expand Down
4 changes: 4 additions & 0 deletions internal/langserver/handlers/did_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func TextDocumentDidChange(ctx context.Context, params lsp.DidChangeTextDocument
if err != nil {
return err
}
err = modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeDecodeReferences)
if err != nil {
return err
}

diags, err := lsctx.Diagnostics(ctx)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/langserver/handlers/did_open.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe
// TODO: Do this only if we can verify the file differs?
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeParseConfiguration)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeLoadModuleMetadata)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeDecodeReferences)

if mod.TerraformVersionState == op.OpStateUnknown {
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeGetTerraformVersion)
Expand Down
4 changes: 3 additions & 1 deletion internal/lsp/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,14 @@ func toCompletionItem(candidate lang.Candidate, caps lsp.CompletionClientCapabil
kind = lsp.EnumCompletion
case lang.MapCandidateKind, lang.ObjectCandidateKind:
kind = lsp.StructCompletion
case lang.TraversalCandidateKind:
kind = lsp.VariableCompletion
}

// TODO: Omit item which uses kind unsupported by the client

var cmd *lsp.Command
if candidate.TriggerSuggest {
if candidate.TriggerSuggest && snippetSupport {
cmd = &lsp.Command{
Command: "editor.action.triggerSuggest",
Title: "Suggest",
Expand Down
4 changes: 4 additions & 0 deletions internal/lsp/token_encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func (te *TokenEncoder) encodeTokenOfIndex(i int) []float64 {
tokenType = TokenTypeParameter
case lang.TokenMapKey:
tokenType = TokenTypeParameter
case lang.TokenKeyword:
tokenType = TokenTypeVariable
case lang.TokenTraversalStep:
tokenType = TokenTypeVariable

default:
return []float64{}
Expand Down
1 change: 1 addition & 0 deletions internal/lsp/token_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ var (
TokenTypeKeyword,
TokenTypeNumber,
TokenTypeParameter,
TokenTypeVariable,
}
serverTokenModifiers = TokenModifiers{
TokenModifierDeprecated,
Expand Down
Loading

0 comments on commit 4e9a443

Please sign in to comment.