@@ -280,6 +280,221 @@ func Test_GetModuleContent_json(t *testing.T) {
280
280
}
281
281
}
282
282
283
+ func TestWalkExpressions (t * testing.T ) {
284
+ tests := []struct {
285
+ name string
286
+ files map [string ]string
287
+ walked []hcl.Range
288
+ }{
289
+ {
290
+ name : "resource" ,
291
+ files : map [string ]string {
292
+ "resource.tf" : `
293
+ resource "null_resource" "test" {
294
+ key = "foo"
295
+ }` ,
296
+ },
297
+ walked : []hcl.Range {
298
+ {Start : hcl.Pos {Line : 3 , Column : 9 }, End : hcl.Pos {Line : 3 , Column : 14 }},
299
+ {Start : hcl.Pos {Line : 3 , Column : 10 }, End : hcl.Pos {Line : 3 , Column : 13 }},
300
+ },
301
+ },
302
+ {
303
+ name : "data source" ,
304
+ files : map [string ]string {
305
+ "data.tf" : `
306
+ data "null_dataresource" "test" {
307
+ key = "foo"
308
+ }` ,
309
+ },
310
+ walked : []hcl.Range {
311
+ {Start : hcl.Pos {Line : 3 , Column : 9 }, End : hcl.Pos {Line : 3 , Column : 14 }},
312
+ {Start : hcl.Pos {Line : 3 , Column : 10 }, End : hcl.Pos {Line : 3 , Column : 13 }},
313
+ },
314
+ },
315
+ {
316
+ name : "module call" ,
317
+ files : map [string ]string {
318
+ "module.tf" : `
319
+ module "m" {
320
+ source = "./module"
321
+ key = "foo"
322
+ }` ,
323
+ },
324
+ walked : []hcl.Range {
325
+ {Start : hcl.Pos {Line : 3 , Column : 12 }, End : hcl.Pos {Line : 3 , Column : 22 }},
326
+ {Start : hcl.Pos {Line : 3 , Column : 13 }, End : hcl.Pos {Line : 3 , Column : 21 }},
327
+ {Start : hcl.Pos {Line : 4 , Column : 12 }, End : hcl.Pos {Line : 4 , Column : 17 }},
328
+ {Start : hcl.Pos {Line : 4 , Column : 13 }, End : hcl.Pos {Line : 4 , Column : 16 }},
329
+ },
330
+ },
331
+ {
332
+ name : "provider config" ,
333
+ files : map [string ]string {
334
+ "provider.tf" : `
335
+ provider "p" {
336
+ key = "foo"
337
+ }` ,
338
+ },
339
+ walked : []hcl.Range {
340
+ {Start : hcl.Pos {Line : 3 , Column : 9 }, End : hcl.Pos {Line : 3 , Column : 14 }},
341
+ {Start : hcl.Pos {Line : 3 , Column : 10 }, End : hcl.Pos {Line : 3 , Column : 13 }},
342
+ },
343
+ },
344
+ {
345
+ name : "locals" ,
346
+ files : map [string ]string {
347
+ "locals.tf" : `
348
+ locals {
349
+ key = "foo"
350
+ }` ,
351
+ },
352
+ walked : []hcl.Range {
353
+ {Start : hcl.Pos {Line : 3 , Column : 9 }, End : hcl.Pos {Line : 3 , Column : 14 }},
354
+ {Start : hcl.Pos {Line : 3 , Column : 10 }, End : hcl.Pos {Line : 3 , Column : 13 }},
355
+ },
356
+ },
357
+ {
358
+ name : "output" ,
359
+ files : map [string ]string {
360
+ "output.tf" : `
361
+ output "o" {
362
+ value = "foo"
363
+ }` ,
364
+ },
365
+ walked : []hcl.Range {
366
+ {Start : hcl.Pos {Line : 3 , Column : 11 }, End : hcl.Pos {Line : 3 , Column : 16 }},
367
+ {Start : hcl.Pos {Line : 3 , Column : 12 }, End : hcl.Pos {Line : 3 , Column : 15 }},
368
+ },
369
+ },
370
+ {
371
+ name : "resource with block" ,
372
+ files : map [string ]string {
373
+ "resource.tf" : `
374
+ resource "null_resource" "test" {
375
+ key = "foo"
376
+
377
+ lifecycle {
378
+ ignore_changes = [key]
379
+ }
380
+ }` ,
381
+ },
382
+ walked : []hcl.Range {
383
+ {Start : hcl.Pos {Line : 3 , Column : 9 }, End : hcl.Pos {Line : 3 , Column : 14 }},
384
+ {Start : hcl.Pos {Line : 3 , Column : 10 }, End : hcl.Pos {Line : 3 , Column : 13 }},
385
+ {Start : hcl.Pos {Line : 6 , Column : 22 }, End : hcl.Pos {Line : 6 , Column : 27 }},
386
+ {Start : hcl.Pos {Line : 6 , Column : 23 }, End : hcl.Pos {Line : 6 , Column : 26 }},
387
+ },
388
+ },
389
+ {
390
+ name : "resource json" ,
391
+ files : map [string ]string {
392
+ "resource.tf.json" : `
393
+ {
394
+ "resource": {
395
+ "null_resource": {
396
+ "test": {
397
+ "key": "foo",
398
+ "nested": {
399
+ "key": "foo"
400
+ },
401
+ "list": [{
402
+ "key": "foo"
403
+ }]
404
+ }
405
+ }
406
+ }
407
+ }` ,
408
+ },
409
+ walked : []hcl.Range {
410
+ {Start : hcl.Pos {Line : 3 , Column : 15 }, End : hcl.Pos {Line : 15 , Column : 4 }},
411
+ },
412
+ },
413
+ {
414
+ name : "multiple files" ,
415
+ files : map [string ]string {
416
+ "main.tf" : `
417
+ provider "aws" {
418
+ region = "us-east-1"
419
+
420
+ assume_role {
421
+ role_arn = "arn:aws:iam::123412341234:role/ExampleRole"
422
+ }
423
+ }` ,
424
+ "main_override.tf" : `
425
+ provider "aws" {
426
+ region = "us-east-1"
427
+
428
+ assume_role {
429
+ role_arn = null
430
+ }
431
+ }` ,
432
+ },
433
+ walked : []hcl.Range {
434
+ {Start : hcl.Pos {Line : 3 , Column : 12 }, End : hcl.Pos {Line : 3 , Column : 23 }, Filename : "main.tf" },
435
+ {Start : hcl.Pos {Line : 3 , Column : 13 }, End : hcl.Pos {Line : 3 , Column : 22 }, Filename : "main.tf" },
436
+ {Start : hcl.Pos {Line : 6 , Column : 16 }, End : hcl.Pos {Line : 6 , Column : 60 }, Filename : "main.tf" },
437
+ {Start : hcl.Pos {Line : 6 , Column : 17 }, End : hcl.Pos {Line : 6 , Column : 59 }, Filename : "main.tf" },
438
+ {Start : hcl.Pos {Line : 3 , Column : 12 }, End : hcl.Pos {Line : 3 , Column : 23 }, Filename : "main_override.tf" },
439
+ {Start : hcl.Pos {Line : 3 , Column : 13 }, End : hcl.Pos {Line : 3 , Column : 22 }, Filename : "main_override.tf" },
440
+ {Start : hcl.Pos {Line : 6 , Column : 16 }, End : hcl.Pos {Line : 6 , Column : 20 }, Filename : "main_override.tf" },
441
+ },
442
+ },
443
+ {
444
+ name : "nested attributes" ,
445
+ files : map [string ]string {
446
+ "data.tf" : `
447
+ data "terraform_remote_state" "remote_state" {
448
+ backend = "remote"
449
+
450
+ config = {
451
+ organization = "Organization"
452
+ workspaces = {
453
+ name = "${var.environment}"
454
+ }
455
+ }
456
+ }` ,
457
+ },
458
+ walked : []hcl.Range {
459
+ {Start : hcl.Pos {Line : 3 , Column : 13 }, End : hcl.Pos {Line : 3 , Column : 21 }},
460
+ {Start : hcl.Pos {Line : 3 , Column : 14 }, End : hcl.Pos {Line : 3 , Column : 20 }},
461
+ {Start : hcl.Pos {Line : 5 , Column : 12 }, End : hcl.Pos {Line : 10 , Column : 4 }},
462
+ {Start : hcl.Pos {Line : 6 , Column : 5 }, End : hcl.Pos {Line : 6 , Column : 17 }},
463
+ {Start : hcl.Pos {Line : 6 , Column : 20 }, End : hcl.Pos {Line : 6 , Column : 34 }},
464
+ {Start : hcl.Pos {Line : 6 , Column : 21 }, End : hcl.Pos {Line : 6 , Column : 33 }},
465
+ {Start : hcl.Pos {Line : 7 , Column : 5 }, End : hcl.Pos {Line : 7 , Column : 15 }},
466
+ {Start : hcl.Pos {Line : 7 , Column : 18 }, End : hcl.Pos {Line : 9 , Column : 6 }},
467
+ {Start : hcl.Pos {Line : 8 , Column : 7 }, End : hcl.Pos {Line : 8 , Column : 11 }},
468
+ {Start : hcl.Pos {Line : 8 , Column : 14 }, End : hcl.Pos {Line : 8 , Column : 34 }},
469
+ {Start : hcl.Pos {Line : 8 , Column : 17 }, End : hcl.Pos {Line : 8 , Column : 32 }},
470
+ },
471
+ },
472
+ }
473
+
474
+ for _ , test := range tests {
475
+ t .Run (test .name , func (t * testing.T ) {
476
+ runner := TestRunner (t , test .files )
477
+
478
+ walked := []hcl.Range {}
479
+ diags := runner .WalkExpressions (tflint .ExprWalkFunc (func (expr hcl.Expression ) hcl.Diagnostics {
480
+ walked = append (walked , expr .Range ())
481
+ return nil
482
+ }))
483
+ if diags .HasErrors () {
484
+ t .Fatal (diags )
485
+ }
486
+ opts := cmp.Options {
487
+ cmpopts .IgnoreFields (hcl.Range {}, "Filename" ),
488
+ cmpopts .IgnoreFields (hcl.Pos {}, "Byte" ),
489
+ cmpopts .SortSlices (func (x , y hcl.Range ) bool { return x .String () > y .String () }),
490
+ }
491
+ if diff := cmp .Diff (walked , test .walked , opts ); diff != "" {
492
+ t .Error (diff )
493
+ }
494
+ })
495
+ }
496
+ }
497
+
283
498
func Test_DecodeRuleConfig (t * testing.T ) {
284
499
files := map [string ]string {
285
500
".tflint.hcl" : `
0 commit comments