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 8a7bb79
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 54 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-20210512111541-102ac67216b9
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-20210512111618-5c20c7ab2df3
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-20210512111541-102ac67216b9 h1:hNUJeCGZSe3lB79pKcanxItpukbjiQ47HBfKhDlMPkg=
github.com/hashicorp/hcl-lang v0.0.0-20210512111541-102ac67216b9/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-20210512111618-5c20c7ab2df3 h1:1FLawNTRHVoasrYlIQXcwFWI1v+t97BA99diSKf4470=
github.com/hashicorp/terraform-schema v0.0.0-20210512111618-5c20c7ab2df3/go.mod h1:x9bL0iUl55qobaaZU0k3OaIriyqjYtHzZLUz4ZbyzAc=
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
72 changes: 31 additions & 41 deletions 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 @@ -127,16 +127,14 @@ func TestCompletion_withValidData(t *testing.T) {
"insertTextFormat": 1,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
"start": {"line": 1, "character": 0},
"end": {"line": 1, "character": 0}
},
"newText": "alias"
},
"command": {
"title": "Suggest",
"command": "editor.action.triggerSuggest"
}
},
{
Expand All @@ -147,16 +145,14 @@ func TestCompletion_withValidData(t *testing.T) {
"insertTextFormat": 1,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
"start": {"line": 1, "character": 0},
"end": {"line": 1, "character": 0}
},
"newText": "anonymous"
},
"command": {
"title": "Suggest",
"command": "editor.action.triggerSuggest"
}
},
{
Expand All @@ -167,16 +163,14 @@ func TestCompletion_withValidData(t *testing.T) {
"insertTextFormat": 1,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
"start": {"line": 1, "character": 0},
"end": {"line": 1, "character": 0}
},
"newText": "base_url"
},
"command": {
"title": "Suggest",
"command": "editor.action.triggerSuggest"
}
},
{
Expand All @@ -187,16 +181,14 @@ func TestCompletion_withValidData(t *testing.T) {
"insertTextFormat": 1,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
"start": {"line": 1, "character": 0},
"end": {"line": 1, "character": 0}
},
"newText": "individual"
},
"command": {
"title": "Suggest",
"command": "editor.action.triggerSuggest"
}
},
{
Expand All @@ -207,16 +199,14 @@ func TestCompletion_withValidData(t *testing.T) {
"insertTextFormat": 1,
"textEdit": {
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 1,
"character": 0
}
"start": {"line": 1, "character": 0},
"end": {"line": 1, "character": 0}
},
"newText": "version"
},
"command": {
"title": "Suggest",
"command": "editor.action.triggerSuggest"
}
}
]
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
2 changes: 2 additions & 0 deletions internal/lsp/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ 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
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
49 changes: 49 additions & 0 deletions internal/state/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package state
import (
"github.com/hashicorp/go-memdb"
"github.com/hashicorp/go-version"
"github.com/hashicorp/hcl-lang/lang"
"github.com/hashicorp/hcl/v2"
tfaddr "github.com/hashicorp/terraform-registry-address"
tfmod "github.com/hashicorp/terraform-schema/module"
Expand Down Expand Up @@ -32,6 +33,10 @@ type Module struct {
ProviderSchemaErr error
ProviderSchemaState op.OpState

References lang.References
ReferencesErr error
ReferencesState op.OpState

ParsedFiles map[string]*hcl.File
ParsingErr error
ParsingState op.OpState
Expand All @@ -49,6 +54,7 @@ func newModule(modPath string) *Module {
ModManifestState: op.OpStateUnknown,
TerraformVersionState: op.OpStateUnknown,
ProviderSchemaState: op.OpStateUnknown,
ReferencesState: op.OpStateUnknown,
ParsingState: op.OpStateUnknown,
MetaState: op.OpStateUnknown,
}
Expand Down Expand Up @@ -400,3 +406,46 @@ func (s *ModuleStore) UpdateDiagnostics(path string, diags map[string]hcl.Diagno
txn.Commit()
return nil
}

func (s *ModuleStore) SetReferencesState(path string, state op.OpState) error {
txn := s.db.Txn(true)
defer txn.Abort()

mod, err := moduleByPath(txn, path)
if err != nil {
return err
}

mod.ReferencesState = state
err = txn.Insert(s.tableName, mod)
if err != nil {
return err
}

txn.Commit()
return nil
}

func (s *ModuleStore) UpdateReferences(path string, refs lang.References, rErr error) error {
txn := s.db.Txn(true)
txn.Defer(func() {
s.SetReferencesState(path, op.OpStateLoaded)
})
defer txn.Abort()

mod, err := moduleByPath(txn, path)
if err != nil {
return err
}

mod.References = refs
mod.ReferencesErr = rErr

err = txn.Insert(s.tableName, mod)
if err != nil {
return err
}

txn.Commit()
return nil
}
12 changes: 12 additions & 0 deletions internal/terraform/module/module_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ func (ml *moduleLoader) executeModuleOp(ctx context.Context, modOp ModuleOperati
ml.logger.Printf("failed to load module metadata: %s", err)
}
return
case op.OpTypeDecodeReferences:
err := DecodeReferences(ml.modStore, ml.schemaStore, modOp.ModulePath)
if err != nil {
ml.logger.Printf("failed to decode references: %s", err)
}
return
}

ml.logger.Printf("%s: unknown operation (%#v) for module operation",
Expand Down Expand Up @@ -226,6 +232,12 @@ func (ml *moduleLoader) EnqueueModuleOp(modOp ModuleOperation) error {
return nil
}
ml.modStore.SetMetaState(modOp.ModulePath, op.OpStateQueued)
case op.OpTypeDecodeReferences:
if mod.MetaState == op.OpStateQueued {
// avoid enqueuing duplicate operation
return nil
}
ml.modStore.SetReferencesState(modOp.ModulePath, op.OpStateQueued)
}

ml.queue.PushOp(modOp)
Expand Down
6 changes: 5 additions & 1 deletion internal/terraform/module/module_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ func (mm *moduleManager) SchemaForModule(modPath string) (*schema.BodySchema, er
return nil, err
}

return schemaForModule(mod, mm.schemaStore)
}

func schemaForModule(mod *state.Module, schemaReader state.SchemaReader) (*schema.BodySchema, error) {
var coreSchema *schema.BodySchema
coreRequirements := make(version.Constraints, 0)
if mod.TerraformVersion != nil {
Expand All @@ -120,7 +124,7 @@ func (mm *moduleManager) SchemaForModule(modPath string) (*schema.BodySchema, er
}

sm := tfschema.NewSchemaMerger(coreSchema)
sm.SetSchemaReader(mm.schemaStore)
sm.SetSchemaReader(schemaReader)

meta := &tfmodule.Meta{
Path: mod.Path,
Expand Down
Loading

0 comments on commit 8a7bb79

Please sign in to comment.