Skip to content

Commit 46820bd

Browse files
authored
Introduce go-to-variable from tfvars files (#727)
* 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
1 parent 5c4e9ea commit 46820bd

File tree

10 files changed

+193
-10
lines changed

10 files changed

+193
-10
lines changed

internal/decoder/decoder.go

+2-7
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,14 @@ func varsPathContext(mod *state.Module) (*decoder.PathContext, error) {
6363
Schema: schema,
6464
ReferenceOrigins: make(reference.Origins, 0),
6565
ReferenceTargets: make(reference.Targets, 0),
66-
Files: make(map[string]*hcl.File, 0),
66+
Files: make(map[string]*hcl.File),
6767
}
6868

69-
for _, origin := range mod.RefOrigins {
69+
for _, origin := range mod.VarsRefOrigins {
7070
if ast.IsVarsFilename(origin.OriginRange().Filename) {
7171
pathCtx.ReferenceOrigins = append(pathCtx.ReferenceOrigins, origin)
7272
}
7373
}
74-
for _, target := range mod.RefTargets {
75-
if target.RangePtr != nil && ast.IsVarsFilename(target.RangePtr.Filename) {
76-
pathCtx.ReferenceTargets = append(pathCtx.ReferenceTargets, target)
77-
}
78-
}
7974

8075
for name, f := range mod.ParsedVarsFiles {
8176
pathCtx.Files[name.String()] = f

internal/langserver/handlers/did_change.go

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ func TextDocumentDidChange(ctx context.Context, params lsp.DidChangeTextDocument
7979
if err != nil {
8080
return err
8181
}
82+
err = modMgr.EnqueueModuleOp(mod.Path, op.OpTypeDecodeVarsReferences, nil)
83+
if err != nil {
84+
return err
85+
}
8286

8387
return nil
8488
}

internal/langserver/handlers/did_open.go

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe
5151
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeLoadModuleMetadata, nil)
5252
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeDecodeReferenceTargets, nil)
5353
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeDecodeReferenceOrigins, nil)
54+
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeDecodeVarsReferences, nil)
5455

5556
if mod.TerraformVersionState == op.OpStateUnknown {
5657
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeGetTerraformVersion, nil)

internal/state/module.go

+51
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ type Module struct {
9393
RefOriginsErr error
9494
RefOriginsState op.OpState
9595

96+
VarsRefOrigins reference.Origins
97+
VarsRefOriginsErr error
98+
VarsRefOriginsState op.OpState
99+
96100
ParsedModuleFiles ast.ModFiles
97101
ParsedVarsFiles ast.VarsFiles
98102
ModuleParsingErr error
@@ -135,6 +139,10 @@ func (m *Module) Copy() *Module {
135139
RefOriginsErr: m.RefOriginsErr,
136140
RefOriginsState: m.RefOriginsState,
137141

142+
VarsRefOrigins: m.VarsRefOrigins.Copy(),
143+
VarsRefOriginsErr: m.VarsRefOriginsErr,
144+
VarsRefOriginsState: m.VarsRefOriginsState,
145+
138146
ModuleParsingErr: m.ModuleParsingErr,
139147
VarsParsingErr: m.VarsParsingErr,
140148
ModuleParsingState: m.ModuleParsingState,
@@ -830,3 +838,46 @@ func (s *ModuleStore) UpdateReferenceOrigins(path string, origins reference.Orig
830838
txn.Commit()
831839
return nil
832840
}
841+
842+
func (s *ModuleStore) SetVarsReferenceOriginsState(path string, state op.OpState) error {
843+
txn := s.db.Txn(true)
844+
defer txn.Abort()
845+
846+
mod, err := moduleCopyByPath(txn, path)
847+
if err != nil {
848+
return err
849+
}
850+
851+
mod.VarsRefOriginsState = state
852+
err = txn.Insert(s.tableName, mod)
853+
if err != nil {
854+
return err
855+
}
856+
857+
txn.Commit()
858+
return nil
859+
}
860+
861+
func (s *ModuleStore) UpdateVarsReferenceOrigins(path string, origins reference.Origins, roErr error) error {
862+
txn := s.db.Txn(true)
863+
txn.Defer(func() {
864+
s.SetVarsReferenceOriginsState(path, op.OpStateLoaded)
865+
})
866+
defer txn.Abort()
867+
868+
mod, err := moduleCopyByPath(txn, path)
869+
if err != nil {
870+
return err
871+
}
872+
873+
mod.VarsRefOrigins = origins
874+
mod.VarsRefOriginsErr = roErr
875+
876+
err = txn.Insert(s.tableName, mod)
877+
if err != nil {
878+
return err
879+
}
880+
881+
txn.Commit()
882+
return nil
883+
}

internal/state/module_test.go

+85
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77

88
"github.com/google/go-cmp/cmp"
99
"github.com/hashicorp/go-version"
10+
"github.com/hashicorp/hcl-lang/lang"
11+
"github.com/hashicorp/hcl-lang/reference"
1012
"github.com/hashicorp/hcl/v2"
1113
"github.com/hashicorp/hcl/v2/hclparse"
1214
"github.com/hashicorp/hcl/v2/hclsyntax"
@@ -15,6 +17,7 @@ import (
1517
"github.com/hashicorp/terraform-ls/internal/terraform/module/operation"
1618
tfaddr "github.com/hashicorp/terraform-registry-address"
1719
tfmod "github.com/hashicorp/terraform-schema/module"
20+
"github.com/zclconf/go-cty/cty"
1821
)
1922

2023
func TestModuleStore_Add_duplicate(t *testing.T) {
@@ -508,6 +511,88 @@ dev = {
508511
}
509512
}
510513

514+
func TestModuleStore_SetVarsReferenceOriginsState(t *testing.T) {
515+
s, err := NewStateStore()
516+
if err != nil {
517+
t.Fatal(err)
518+
}
519+
520+
tmpDir := t.TempDir()
521+
err = s.Modules.Add(tmpDir)
522+
if err != nil {
523+
t.Fatal(err)
524+
}
525+
526+
s.Modules.SetVarsReferenceOriginsState(tmpDir, operation.OpStateQueued)
527+
528+
mod, err := s.Modules.ModuleByPath(tmpDir)
529+
if err != nil {
530+
t.Fatal(err)
531+
}
532+
533+
if diff := cmp.Diff(mod.VarsRefOriginsState, operation.OpStateQueued, cmpOpts); diff != "" {
534+
t.Fatalf("unexpected module vars ref origins state: %s", diff)
535+
}
536+
}
537+
538+
func TestModuleStore_UpdateVarsReferenceOrigins(t *testing.T) {
539+
s, err := NewStateStore()
540+
if err != nil {
541+
t.Fatal(err)
542+
}
543+
544+
tmpDir := t.TempDir()
545+
err = s.Modules.Add(tmpDir)
546+
if err != nil {
547+
t.Fatal(err)
548+
}
549+
550+
origins := reference.Origins{
551+
reference.PathOrigin{
552+
Range: hcl.Range{
553+
Filename: "terraform.tfvars",
554+
Start: hcl.Pos{
555+
Line: 1,
556+
Column: 1,
557+
Byte: 0,
558+
},
559+
End: hcl.Pos{
560+
Line: 1,
561+
Column: 5,
562+
Byte: 4,
563+
},
564+
},
565+
TargetAddr: lang.Address{
566+
lang.RootStep{Name: "var"},
567+
lang.AttrStep{Name: "name"},
568+
},
569+
TargetPath: lang.Path{
570+
Path: tmpDir,
571+
LanguageID: "terraform",
572+
},
573+
Constraints: reference.OriginConstraints{
574+
reference.OriginConstraint{
575+
OfScopeId: "variable",
576+
OfType: cty.String,
577+
},
578+
},
579+
},
580+
}
581+
s.Modules.UpdateVarsReferenceOrigins(tmpDir, origins, nil)
582+
583+
mod, err := s.Modules.ModuleByPath(tmpDir)
584+
if err != nil {
585+
t.Fatal(err)
586+
}
587+
588+
if diff := cmp.Diff(mod.VarsRefOrigins, origins, cmpOpts); diff != "" {
589+
t.Fatalf("unexpected module vars ref origins: %s", diff)
590+
}
591+
if diff := cmp.Diff(mod.VarsRefOriginsState, operation.OpStateLoaded, cmpOpts); diff != "" {
592+
t.Fatalf("unexpected module vars ref origins state: %s", diff)
593+
}
594+
}
595+
511596
func BenchmarkModuleByPath(b *testing.B) {
512597
s, err := NewStateStore()
513598
if err != nil {

internal/terraform/module/module_loader.go

+9
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ func (ml *moduleLoader) executeModuleOp(ctx context.Context, modOp ModuleOperati
164164
if opErr != nil {
165165
ml.logger.Printf("failed to decode reference origins: %s", opErr)
166166
}
167+
case op.OpTypeDecodeVarsReferences:
168+
opErr = DecodeVarsReferences(ctx, ml.modStore, ml.schemaStore, modOp.ModulePath)
169+
if opErr != nil {
170+
ml.logger.Printf("failed to decode vars references: %s", opErr)
171+
}
167172
default:
168173
ml.logger.Printf("%s: unknown operation (%#v) for module operation",
169174
modOp.ModulePath, modOp.Type)
@@ -207,6 +212,8 @@ func (ml *moduleLoader) EnqueueModuleOp(modOp ModuleOperation) error {
207212
ml.modStore.SetReferenceTargetsState(modOp.ModulePath, op.OpStateQueued)
208213
case op.OpTypeDecodeReferenceOrigins:
209214
ml.modStore.SetReferenceOriginsState(modOp.ModulePath, op.OpStateQueued)
215+
case op.OpTypeDecodeVarsReferences:
216+
ml.modStore.SetVarsReferenceOriginsState(modOp.ModulePath, op.OpStateQueued)
210217
}
211218

212219
ml.queue.PushOp(modOp)
@@ -233,6 +240,8 @@ func operationState(mod *state.Module, opType op.OpType) op.OpState {
233240
return mod.RefTargetsState
234241
case op.OpTypeDecodeReferenceOrigins:
235242
return mod.RefOriginsState
243+
case op.OpTypeDecodeVarsReferences:
244+
return mod.VarsRefOriginsState
236245
}
237246
return op.OpStateUnknown
238247
}

internal/terraform/module/module_ops.go

+34-3
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,20 @@ func DecodeReferenceOrigins(ctx context.Context, modStore *state.ModuleStore, sc
299299
return err
300300
}
301301

302-
d, err := decoder.NewDecoder(ctx, &decoder.PathReader{
302+
d := decoder.NewDecoder(ctx, &decoder.PathReader{
303303
ModuleReader: modStore,
304304
SchemaReader: schemaReader,
305-
}).Path(lang.Path{
305+
})
306+
307+
moduleDecoder, err := d.Path(lang.Path{
306308
Path: modPath,
307309
LanguageID: ilsp.Terraform.String(),
308310
})
309311
if err != nil {
310312
return err
311313
}
312-
origins, rErr := d.CollectReferenceOrigins()
314+
315+
origins, rErr := moduleDecoder.CollectReferenceOrigins()
313316

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

319322
return rErr
320323
}
324+
325+
func DecodeVarsReferences(ctx context.Context, modStore *state.ModuleStore, schemaReader state.SchemaReader, modPath string) error {
326+
err := modStore.SetVarsReferenceOriginsState(modPath, op.OpStateLoading)
327+
if err != nil {
328+
return err
329+
}
330+
331+
d := decoder.NewDecoder(ctx, &decoder.PathReader{
332+
ModuleReader: modStore,
333+
SchemaReader: schemaReader,
334+
})
335+
336+
varsDecoder, err := d.Path(lang.Path{
337+
Path: modPath,
338+
LanguageID: ilsp.Tfvars.String(),
339+
})
340+
if err != nil {
341+
return err
342+
}
343+
344+
origins, rErr := varsDecoder.CollectReferenceOrigins()
345+
sErr := modStore.UpdateVarsReferenceOrigins(modPath, origins, rErr)
346+
if sErr != nil {
347+
return sErr
348+
}
349+
350+
return rErr
351+
}

internal/terraform/module/operation/operation.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ const (
2323
OpTypeLoadModuleMetadata
2424
OpTypeDecodeReferenceTargets
2525
OpTypeDecodeReferenceOrigins
26+
OpTypeDecodeVarsReferences
2627
)

internal/terraform/module/walker.go

+4
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ func (w *Walker) walk(ctx context.Context, rootPath string) error {
295295
if err != nil {
296296
return err
297297
}
298+
err = w.modMgr.EnqueueModuleOp(dir, op.OpTypeDecodeVarsReferences, nil)
299+
if err != nil {
300+
return err
301+
}
298302
}
299303

300304
if dataDir.PluginLockFilePath != "" {

internal/terraform/module/watcher.go

+2
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ func decodeCalledModulesFunc(modMgr ModuleManager, w Watcher, modPath string) De
250250
modMgr.EnqueueModuleOp(mc.Path, op.OpTypeParseVariables, nil)
251251
modMgr.EnqueueModuleOp(mc.Path, op.OpTypeDecodeReferenceTargets, nil)
252252
modMgr.EnqueueModuleOp(mc.Path, op.OpTypeDecodeReferenceOrigins, nil)
253+
modMgr.EnqueueModuleOp(mc.Path, op.OpTypeDecodeVarsReferences, nil)
253254

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

259260
modMgr.EnqueueModuleOp(modPath, op.OpTypeDecodeReferenceTargets, nil)
260261
modMgr.EnqueueModuleOp(modPath, op.OpTypeDecodeReferenceOrigins, nil)
262+
modMgr.EnqueueModuleOp(modPath, op.OpTypeDecodeVarsReferences, nil)
261263
}
262264
}
263265

0 commit comments

Comments
 (0)