@@ -10,6 +10,7 @@ import (
10
10
"github.com/hashicorp/hcl-lang/schema"
11
11
"github.com/hashicorp/hcl/v2"
12
12
"github.com/hashicorp/hcl/v2/hclsyntax"
13
+ "github.com/zclconf/go-cty-debug/ctydebug"
13
14
"github.com/zclconf/go-cty/cty"
14
15
)
15
16
@@ -2566,3 +2567,181 @@ another_block "meh" {
2566
2567
})
2567
2568
}
2568
2569
}
2570
+
2571
+ func TestDecoder_CandidateAtPos_expressions_crossFileTraversal (t * testing.T ) {
2572
+ f1 , _ := hclsyntax .ParseConfig ([]byte (`variable "aaa" {}
2573
+ variable "bbb" {}
2574
+ variable "ccc" {}
2575
+ ` ), "test1.tf" , hcl .InitialPos )
2576
+ f2 , _ := hclsyntax .ParseConfig ([]byte (`value =
2577
+ ` ), "test2.tf" , hcl .InitialPos )
2578
+
2579
+ bodySchema := & schema.BodySchema {
2580
+ Attributes : map [string ]* schema.AttributeSchema {
2581
+ "value" : {
2582
+ IsOptional : true ,
2583
+ Expr : schema.ExprConstraints {
2584
+ schema.TraversalExpr {
2585
+ OfScopeId : lang .ScopeId ("variable" ),
2586
+ OfType : cty .DynamicPseudoType ,
2587
+ },
2588
+ },
2589
+ },
2590
+ },
2591
+ Blocks : map [string ]* schema.BlockSchema {
2592
+ "variable" : {
2593
+ Labels : []* schema.LabelSchema {
2594
+ {Name : "name" },
2595
+ },
2596
+ Address : & schema.BlockAddrSchema {
2597
+ Steps : []schema.AddrStep {
2598
+ schema.StaticStep {Name : "var" },
2599
+ schema.LabelStep {Index : 0 },
2600
+ },
2601
+ FriendlyName : "variable" ,
2602
+ ScopeId : lang .ScopeId ("variable" ),
2603
+ AsTypeOf : & schema.BlockAsTypeOf {
2604
+ AttributeExpr : "type" ,
2605
+ AttributeValue : "default" ,
2606
+ },
2607
+ },
2608
+ },
2609
+ },
2610
+ }
2611
+
2612
+ testDir := t .TempDir ()
2613
+ dirReader := & testPathReader {
2614
+ paths : map [string ]* PathContext {
2615
+ testDir : {
2616
+ Schema : bodySchema ,
2617
+ Files : map [string ]* hcl.File {
2618
+ "test1.tf" : f1 ,
2619
+ "test2.tf" : f2 ,
2620
+ },
2621
+ ReferenceTargets : reference.Targets {},
2622
+ },
2623
+ },
2624
+ }
2625
+ decoder := NewDecoder (dirReader )
2626
+ d , err := decoder .Path (lang.Path {Path : testDir })
2627
+ if err != nil {
2628
+ t .Fatal (err )
2629
+ }
2630
+ refTargets , err := d .CollectReferenceTargets ()
2631
+ if err != nil {
2632
+ t .Fatal (err )
2633
+ }
2634
+
2635
+ expectedTargets := reference.Targets {
2636
+ {
2637
+ Addr : lang.Address {lang.RootStep {Name : "var" }, lang.AttrStep {Name : "aaa" }},
2638
+ ScopeId : lang .ScopeId ("variable" ),
2639
+ RangePtr : & hcl.Range {
2640
+ Filename : "test1.tf" ,
2641
+ Start : hcl.Pos {Line : 1 , Column : 1 , Byte : 0 },
2642
+ End : hcl.Pos {Line : 1 , Column : 18 , Byte : 17 },
2643
+ },
2644
+ DefRangePtr : & hcl.Range {
2645
+ Filename : "test1.tf" ,
2646
+ Start : hcl.Pos {Line : 1 , Column : 1 , Byte : 0 },
2647
+ End : hcl.Pos {Line : 1 , Column : 15 , Byte : 14 },
2648
+ },
2649
+ Type : cty .DynamicPseudoType ,
2650
+ },
2651
+ {
2652
+ Addr : lang.Address {lang.RootStep {Name : "var" }, lang.AttrStep {Name : "bbb" }},
2653
+ ScopeId : lang .ScopeId ("variable" ),
2654
+ RangePtr : & hcl.Range {
2655
+ Filename : "test1.tf" ,
2656
+ Start : hcl.Pos {Line : 2 , Column : 1 , Byte : 18 },
2657
+ End : hcl.Pos {Line : 2 , Column : 18 , Byte : 35 },
2658
+ },
2659
+ DefRangePtr : & hcl.Range {
2660
+ Filename : "test1.tf" ,
2661
+ Start : hcl.Pos {Line : 2 , Column : 1 , Byte : 18 },
2662
+ End : hcl.Pos {Line : 2 , Column : 15 , Byte : 32 },
2663
+ },
2664
+ Type : cty .DynamicPseudoType ,
2665
+ },
2666
+ {
2667
+ Addr : lang.Address {lang.RootStep {Name : "var" }, lang.AttrStep {Name : "ccc" }},
2668
+ ScopeId : lang .ScopeId ("variable" ),
2669
+ RangePtr : & hcl.Range {
2670
+ Filename : "test1.tf" ,
2671
+ Start : hcl.Pos {Line : 3 , Column : 1 , Byte : 36 },
2672
+ End : hcl.Pos {Line : 3 , Column : 18 , Byte : 53 },
2673
+ },
2674
+ DefRangePtr : & hcl.Range {
2675
+ Filename : "test1.tf" ,
2676
+ Start : hcl.Pos {Line : 3 , Column : 1 , Byte : 36 },
2677
+ End : hcl.Pos {Line : 3 , Column : 15 , Byte : 50 },
2678
+ },
2679
+ Type : cty .DynamicPseudoType ,
2680
+ },
2681
+ }
2682
+ if diff := cmp .Diff (expectedTargets , refTargets , ctydebug .CmpOptions ); diff != "" {
2683
+ t .Fatalf ("unexpected targets: %s" , diff )
2684
+ }
2685
+
2686
+ dirReader .paths [testDir ].ReferenceTargets = refTargets
2687
+
2688
+ candidates , err := d .CandidatesAtPos ("test2.tf" , hcl.Pos {
2689
+ Line : 1 ,
2690
+ Column : 9 ,
2691
+ Byte : 8 ,
2692
+ })
2693
+ if err != nil {
2694
+ t .Fatal (err )
2695
+ }
2696
+
2697
+ expectedCandidates := lang.Candidates {
2698
+ List : []lang.Candidate {
2699
+ {
2700
+ Label : "var.aaa" ,
2701
+ Detail : "dynamic" ,
2702
+ TextEdit : lang.TextEdit {
2703
+ Range : hcl.Range {
2704
+ Filename : "test2.tf" ,
2705
+ Start : hcl.Pos {Line : 1 , Column : 9 , Byte : 8 },
2706
+ End : hcl.Pos {Line : 1 , Column : 9 , Byte : 8 },
2707
+ },
2708
+ NewText : "var.aaa" ,
2709
+ Snippet : "var.aaa" ,
2710
+ },
2711
+ Kind : lang .TraversalCandidateKind ,
2712
+ },
2713
+ {
2714
+ Label : "var.bbb" ,
2715
+ Detail : "dynamic" ,
2716
+ TextEdit : lang.TextEdit {
2717
+ Range : hcl.Range {
2718
+ Filename : "test2.tf" ,
2719
+ Start : hcl.Pos {Line : 1 , Column : 9 , Byte : 8 },
2720
+ End : hcl.Pos {Line : 1 , Column : 9 , Byte : 8 },
2721
+ },
2722
+ NewText : "var.bbb" ,
2723
+ Snippet : "var.bbb" ,
2724
+ },
2725
+ Kind : lang .TraversalCandidateKind ,
2726
+ },
2727
+ {
2728
+ Label : "var.ccc" ,
2729
+ Detail : "dynamic" ,
2730
+ TextEdit : lang.TextEdit {
2731
+ Range : hcl.Range {
2732
+ Filename : "test2.tf" ,
2733
+ Start : hcl.Pos {Line : 1 , Column : 9 , Byte : 8 },
2734
+ End : hcl.Pos {Line : 1 , Column : 9 , Byte : 8 },
2735
+ },
2736
+ NewText : "var.ccc" ,
2737
+ Snippet : "var.ccc" ,
2738
+ },
2739
+ Kind : lang .TraversalCandidateKind ,
2740
+ },
2741
+ },
2742
+ IsComplete : true ,
2743
+ }
2744
+ if diff := cmp .Diff (expectedCandidates , candidates ); diff != "" {
2745
+ t .Fatalf ("unexpected candidates: %s" , diff )
2746
+ }
2747
+ }
0 commit comments