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 traversals/references #485

Merged
merged 1 commit into from
May 18, 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: 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-20210514214009-15d3afdead68
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-20210514214427-b947185f165d
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-20210514214009-15d3afdead68 h1:Y5HxVHg9bKiS8Q4Q3dHOdETtF4DEmKNVdBh93o5K1L0=
github.com/hashicorp/hcl-lang v0.0.0-20210514214009-15d3afdead68/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-20210514214427-b947185f165d h1:XFxb7PJ76yRdoo/IINuh2ASgujNL8jlhaeulXVbDVUA=
github.com/hashicorp/terraform-schema v0.0.0-20210514214427-b947185f165d/go.mod h1:qzSjebjYVlcz56pBd2It3XmkOywXHNjnC/420WHSdaU=
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 {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably something that should've been done some time ago. We do not include the = in the simplified TextEdits and so triggering suggest in that case is kind of pointless.

It is not a big deal for most clients today which probably do support snippets anyway, but it also helps reducing the amount of test data where in test we opt into snippet support only where we need it.

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