@@ -39,7 +39,7 @@ func (r *TerraformDeprecatedInterpolationRule) Link() string {
3939
4040// Check emits issues on the deprecated interpolation syntax.
4141// This logic is equivalent to the warning logic implemented in Terraform.
42- // See https://github.com/hashicorp/terraform/pull/23348
42+ // See https://github.com/hashicorp/terraform/blob/2ce03abe480c3f40d04bd0f289762721ea280848/configs/compat_shim.go#L144-L156
4343func (r * TerraformDeprecatedInterpolationRule ) Check (runner tflint.Runner ) error {
4444 path , err := runner .GetModulePath ()
4545 if err != nil {
@@ -50,29 +50,76 @@ func (r *TerraformDeprecatedInterpolationRule) Check(runner tflint.Runner) error
5050 return nil
5151 }
5252
53- diags := runner .WalkExpressions (tflint .ExprWalkFunc (func (expr hcl.Expression ) hcl.Diagnostics {
54- return r .checkForDeprecatedInterpolationsInExpr (runner , expr )
55- }))
53+ diags := runner .WalkExpressions (& terraformDeprecatedInterpolationWalker {
54+ runner : runner ,
55+ rule : r ,
56+ // create some capacity so that we can deal with simple expressions
57+ // without any further allocation during our walk.
58+ contextStack : make ([]terraformDeprecatedInterpolationContext , 0 , 16 ),
59+ })
5660 if diags .HasErrors () {
5761 return diags
5862 }
5963 return nil
6064}
6165
62- func (r * TerraformDeprecatedInterpolationRule ) checkForDeprecatedInterpolationsInExpr (runner tflint.Runner , expr hcl.Expression ) hcl.Diagnostics {
63- wrapExpr , ok := expr .(* hclsyntax.TemplateWrapExpr )
64- if ! ok {
65- return nil
66+ type terraformDeprecatedInterpolationWalker struct {
67+ runner tflint.Runner
68+ rule * TerraformDeprecatedInterpolationRule
69+ contextStack []terraformDeprecatedInterpolationContext
70+ }
71+
72+ var _ tflint.ExprWalker = (* terraformDeprecatedInterpolationWalker )(nil )
73+
74+ type terraformDeprecatedInterpolationContext int
75+
76+ const (
77+ terraformDeprecatedInterpolationContextNormal terraformDeprecatedInterpolationContext = 0
78+ terraformDeprecatedInterpolationContextObjKey terraformDeprecatedInterpolationContext = 1
79+ )
80+
81+ func (w * terraformDeprecatedInterpolationWalker ) Enter (expr hcl.Expression ) hcl.Diagnostics {
82+ var err error
83+
84+ context := terraformDeprecatedInterpolationContextNormal
85+ switch expr := expr .(type ) {
86+ case * hclsyntax.ObjectConsKeyExpr :
87+ context = terraformDeprecatedInterpolationContextObjKey
88+ case * hclsyntax.TemplateWrapExpr :
89+ // hclsyntax.TemplateWrapExpr is a special node type used by HCL only
90+ // for the situation where a template is just a single interpolation,
91+ // so we don't need to do anything further to distinguish that
92+ // situation. ("normal" templates are *hclsyntax.TemplateExpr.)
93+
94+ const message = "Interpolation-only expressions are deprecated in Terraform v0.12.14"
95+ switch w .currentContext () {
96+ case terraformDeprecatedInterpolationContextObjKey :
97+ // This case requires a different autofix strategy is needed
98+ // to avoid ambiguous attribute keys.
99+ err = w .runner .EmitIssueWithFix (
100+ w .rule ,
101+ message ,
102+ expr .Range (),
103+ func (f tflint.Fixer ) error {
104+ return f .ReplaceText (expr .Range (), "(" , f .TextAt (expr .Wrapped .Range ()), ")" )
105+ },
106+ )
107+ default :
108+ err = w .runner .EmitIssueWithFix (
109+ w .rule ,
110+ message ,
111+ expr .Range (),
112+ func (f tflint.Fixer ) error {
113+ return f .ReplaceText (expr .Range (), f .TextAt (expr .Wrapped .Range ()))
114+ },
115+ )
116+ }
66117 }
67118
68- err := runner .EmitIssueWithFix (
69- r ,
70- "Interpolation-only expressions are deprecated in Terraform v0.12.14" ,
71- expr .Range (),
72- func (f tflint.Fixer ) error {
73- return f .ReplaceText (expr .Range (), f .TextAt (wrapExpr .Wrapped .Range ()))
74- },
75- )
119+ // Note the context of the current node for when we potentially visit
120+ // child nodes.
121+ w .contextStack = append (w .contextStack , context )
122+
76123 if err != nil {
77124 return hcl.Diagnostics {
78125 {
@@ -84,3 +131,15 @@ func (r *TerraformDeprecatedInterpolationRule) checkForDeprecatedInterpolationsI
84131 }
85132 return nil
86133}
134+
135+ func (w * terraformDeprecatedInterpolationWalker ) Exit (expr hcl.Expression ) hcl.Diagnostics {
136+ w .contextStack = w .contextStack [:len (w .contextStack )- 1 ]
137+ return nil
138+ }
139+
140+ func (w * terraformDeprecatedInterpolationWalker ) currentContext () terraformDeprecatedInterpolationContext {
141+ if len (w .contextStack ) == 0 {
142+ return terraformDeprecatedInterpolationContextNormal
143+ }
144+ return w .contextStack [len (w .contextStack )- 1 ]
145+ }
0 commit comments