Skip to content

Commit

Permalink
Introduce go-to-variable from tfvars files (hashicorp#727)
Browse files Browse the repository at this point in the history
* collect origins for tfvars files

* add new state.Module fields for vars

* use new module fields for tfvars

* removed unused target refs from vars decoder

* move vars reference decoding into new module operation

* add test for new module state functions

* review feedback for test
  • Loading branch information
dbanck authored Jan 13, 2022
1 parent 5c4e9ea commit 46820bd
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 10 deletions.
9 changes: 2 additions & 7 deletions internal/decoder/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,14 @@ func varsPathContext(mod *state.Module) (*decoder.PathContext, error) {
Schema: schema,
ReferenceOrigins: make(reference.Origins, 0),
ReferenceTargets: make(reference.Targets, 0),
Files: make(map[string]*hcl.File, 0),
Files: make(map[string]*hcl.File),
}

for _, origin := range mod.RefOrigins {
for _, origin := range mod.VarsRefOrigins {
if ast.IsVarsFilename(origin.OriginRange().Filename) {
pathCtx.ReferenceOrigins = append(pathCtx.ReferenceOrigins, origin)
}
}
for _, target := range mod.RefTargets {
if target.RangePtr != nil && ast.IsVarsFilename(target.RangePtr.Filename) {
pathCtx.ReferenceTargets = append(pathCtx.ReferenceTargets, target)
}
}

for name, f := range mod.ParsedVarsFiles {
pathCtx.Files[name.String()] = f
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 @@ -79,6 +79,10 @@ func TextDocumentDidChange(ctx context.Context, params lsp.DidChangeTextDocument
if err != nil {
return err
}
err = modMgr.EnqueueModuleOp(mod.Path, op.OpTypeDecodeVarsReferences, nil)
if err != nil {
return err
}

return nil
}
1 change: 1 addition & 0 deletions internal/langserver/handlers/did_open.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeLoadModuleMetadata, nil)
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeDecodeReferenceTargets, nil)
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeDecodeReferenceOrigins, nil)
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeDecodeVarsReferences, nil)

if mod.TerraformVersionState == op.OpStateUnknown {
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeGetTerraformVersion, nil)
Expand Down
51 changes: 51 additions & 0 deletions internal/state/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ type Module struct {
RefOriginsErr error
RefOriginsState op.OpState

VarsRefOrigins reference.Origins
VarsRefOriginsErr error
VarsRefOriginsState op.OpState

ParsedModuleFiles ast.ModFiles
ParsedVarsFiles ast.VarsFiles
ModuleParsingErr error
Expand Down Expand Up @@ -135,6 +139,10 @@ func (m *Module) Copy() *Module {
RefOriginsErr: m.RefOriginsErr,
RefOriginsState: m.RefOriginsState,

VarsRefOrigins: m.VarsRefOrigins.Copy(),
VarsRefOriginsErr: m.VarsRefOriginsErr,
VarsRefOriginsState: m.VarsRefOriginsState,

ModuleParsingErr: m.ModuleParsingErr,
VarsParsingErr: m.VarsParsingErr,
ModuleParsingState: m.ModuleParsingState,
Expand Down Expand Up @@ -830,3 +838,46 @@ func (s *ModuleStore) UpdateReferenceOrigins(path string, origins reference.Orig
txn.Commit()
return nil
}

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

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

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

txn.Commit()
return nil
}

func (s *ModuleStore) UpdateVarsReferenceOrigins(path string, origins reference.Origins, roErr error) error {
txn := s.db.Txn(true)
txn.Defer(func() {
s.SetVarsReferenceOriginsState(path, op.OpStateLoaded)
})
defer txn.Abort()

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

mod.VarsRefOrigins = origins
mod.VarsRefOriginsErr = roErr

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

txn.Commit()
return nil
}
85 changes: 85 additions & 0 deletions internal/state/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (

"github.com/google/go-cmp/cmp"
"github.com/hashicorp/go-version"
"github.com/hashicorp/hcl-lang/lang"
"github.com/hashicorp/hcl-lang/reference"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclparse"
"github.com/hashicorp/hcl/v2/hclsyntax"
Expand All @@ -15,6 +17,7 @@ import (
"github.com/hashicorp/terraform-ls/internal/terraform/module/operation"
tfaddr "github.com/hashicorp/terraform-registry-address"
tfmod "github.com/hashicorp/terraform-schema/module"
"github.com/zclconf/go-cty/cty"
)

func TestModuleStore_Add_duplicate(t *testing.T) {
Expand Down Expand Up @@ -508,6 +511,88 @@ dev = {
}
}

func TestModuleStore_SetVarsReferenceOriginsState(t *testing.T) {
s, err := NewStateStore()
if err != nil {
t.Fatal(err)
}

tmpDir := t.TempDir()
err = s.Modules.Add(tmpDir)
if err != nil {
t.Fatal(err)
}

s.Modules.SetVarsReferenceOriginsState(tmpDir, operation.OpStateQueued)

mod, err := s.Modules.ModuleByPath(tmpDir)
if err != nil {
t.Fatal(err)
}

if diff := cmp.Diff(mod.VarsRefOriginsState, operation.OpStateQueued, cmpOpts); diff != "" {
t.Fatalf("unexpected module vars ref origins state: %s", diff)
}
}

func TestModuleStore_UpdateVarsReferenceOrigins(t *testing.T) {
s, err := NewStateStore()
if err != nil {
t.Fatal(err)
}

tmpDir := t.TempDir()
err = s.Modules.Add(tmpDir)
if err != nil {
t.Fatal(err)
}

origins := reference.Origins{
reference.PathOrigin{
Range: hcl.Range{
Filename: "terraform.tfvars",
Start: hcl.Pos{
Line: 1,
Column: 1,
Byte: 0,
},
End: hcl.Pos{
Line: 1,
Column: 5,
Byte: 4,
},
},
TargetAddr: lang.Address{
lang.RootStep{Name: "var"},
lang.AttrStep{Name: "name"},
},
TargetPath: lang.Path{
Path: tmpDir,
LanguageID: "terraform",
},
Constraints: reference.OriginConstraints{
reference.OriginConstraint{
OfScopeId: "variable",
OfType: cty.String,
},
},
},
}
s.Modules.UpdateVarsReferenceOrigins(tmpDir, origins, nil)

mod, err := s.Modules.ModuleByPath(tmpDir)
if err != nil {
t.Fatal(err)
}

if diff := cmp.Diff(mod.VarsRefOrigins, origins, cmpOpts); diff != "" {
t.Fatalf("unexpected module vars ref origins: %s", diff)
}
if diff := cmp.Diff(mod.VarsRefOriginsState, operation.OpStateLoaded, cmpOpts); diff != "" {
t.Fatalf("unexpected module vars ref origins state: %s", diff)
}
}

func BenchmarkModuleByPath(b *testing.B) {
s, err := NewStateStore()
if err != nil {
Expand Down
9 changes: 9 additions & 0 deletions internal/terraform/module/module_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ func (ml *moduleLoader) executeModuleOp(ctx context.Context, modOp ModuleOperati
if opErr != nil {
ml.logger.Printf("failed to decode reference origins: %s", opErr)
}
case op.OpTypeDecodeVarsReferences:
opErr = DecodeVarsReferences(ctx, ml.modStore, ml.schemaStore, modOp.ModulePath)
if opErr != nil {
ml.logger.Printf("failed to decode vars references: %s", opErr)
}
default:
ml.logger.Printf("%s: unknown operation (%#v) for module operation",
modOp.ModulePath, modOp.Type)
Expand Down Expand Up @@ -207,6 +212,8 @@ func (ml *moduleLoader) EnqueueModuleOp(modOp ModuleOperation) error {
ml.modStore.SetReferenceTargetsState(modOp.ModulePath, op.OpStateQueued)
case op.OpTypeDecodeReferenceOrigins:
ml.modStore.SetReferenceOriginsState(modOp.ModulePath, op.OpStateQueued)
case op.OpTypeDecodeVarsReferences:
ml.modStore.SetVarsReferenceOriginsState(modOp.ModulePath, op.OpStateQueued)
}

ml.queue.PushOp(modOp)
Expand All @@ -233,6 +240,8 @@ func operationState(mod *state.Module, opType op.OpType) op.OpState {
return mod.RefTargetsState
case op.OpTypeDecodeReferenceOrigins:
return mod.RefOriginsState
case op.OpTypeDecodeVarsReferences:
return mod.VarsRefOriginsState
}
return op.OpStateUnknown
}
Expand Down
37 changes: 34 additions & 3 deletions internal/terraform/module/module_ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,20 @@ func DecodeReferenceOrigins(ctx context.Context, modStore *state.ModuleStore, sc
return err
}

d, err := decoder.NewDecoder(ctx, &decoder.PathReader{
d := decoder.NewDecoder(ctx, &decoder.PathReader{
ModuleReader: modStore,
SchemaReader: schemaReader,
}).Path(lang.Path{
})

moduleDecoder, err := d.Path(lang.Path{
Path: modPath,
LanguageID: ilsp.Terraform.String(),
})
if err != nil {
return err
}
origins, rErr := d.CollectReferenceOrigins()

origins, rErr := moduleDecoder.CollectReferenceOrigins()

sErr := modStore.UpdateReferenceOrigins(modPath, origins, rErr)
if sErr != nil {
Expand All @@ -318,3 +321,31 @@ func DecodeReferenceOrigins(ctx context.Context, modStore *state.ModuleStore, sc

return rErr
}

func DecodeVarsReferences(ctx context.Context, modStore *state.ModuleStore, schemaReader state.SchemaReader, modPath string) error {
err := modStore.SetVarsReferenceOriginsState(modPath, op.OpStateLoading)
if err != nil {
return err
}

d := decoder.NewDecoder(ctx, &decoder.PathReader{
ModuleReader: modStore,
SchemaReader: schemaReader,
})

varsDecoder, err := d.Path(lang.Path{
Path: modPath,
LanguageID: ilsp.Tfvars.String(),
})
if err != nil {
return err
}

origins, rErr := varsDecoder.CollectReferenceOrigins()
sErr := modStore.UpdateVarsReferenceOrigins(modPath, origins, rErr)
if sErr != nil {
return sErr
}

return rErr
}
1 change: 1 addition & 0 deletions internal/terraform/module/operation/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ const (
OpTypeLoadModuleMetadata
OpTypeDecodeReferenceTargets
OpTypeDecodeReferenceOrigins
OpTypeDecodeVarsReferences
)
4 changes: 4 additions & 0 deletions internal/terraform/module/walker.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ func (w *Walker) walk(ctx context.Context, rootPath string) error {
if err != nil {
return err
}
err = w.modMgr.EnqueueModuleOp(dir, op.OpTypeDecodeVarsReferences, nil)
if err != nil {
return err
}
}

if dataDir.PluginLockFilePath != "" {
Expand Down
2 changes: 2 additions & 0 deletions internal/terraform/module/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ func decodeCalledModulesFunc(modMgr ModuleManager, w Watcher, modPath string) De
modMgr.EnqueueModuleOp(mc.Path, op.OpTypeParseVariables, nil)
modMgr.EnqueueModuleOp(mc.Path, op.OpTypeDecodeReferenceTargets, nil)
modMgr.EnqueueModuleOp(mc.Path, op.OpTypeDecodeReferenceOrigins, nil)
modMgr.EnqueueModuleOp(mc.Path, op.OpTypeDecodeVarsReferences, nil)

if w != nil {
w.AddModule(mc.Path)
Expand All @@ -258,6 +259,7 @@ func decodeCalledModulesFunc(modMgr ModuleManager, w Watcher, modPath string) De

modMgr.EnqueueModuleOp(modPath, op.OpTypeDecodeReferenceTargets, nil)
modMgr.EnqueueModuleOp(modPath, op.OpTypeDecodeReferenceOrigins, nil)
modMgr.EnqueueModuleOp(modPath, op.OpTypeDecodeVarsReferences, nil)
}
}

Expand Down

0 comments on commit 46820bd

Please sign in to comment.