@@ -10,15 +10,13 @@ import (
1010 "github.com/hashicorp/hcl/v2/hclsyntax"
1111)
1212
13- var annotationPattern = regexp .MustCompile (`tflint-ignore: ([^\n*/#]+)` )
14-
1513// Annotation represents comments with special meaning in TFLint
16- type Annotation struct {
17- Content string
18- Token hclsyntax. Token
14+ type Annotation interface {
15+ IsAffected ( * Issue ) bool
16+ String () string
1917}
2018
21- // Annotations is slice of Annotation
19+ // Annotations is a slice of Annotation
2220type Annotations []Annotation
2321
2422// NewAnnotations find annotations from the passed tokens and return that list.
@@ -35,21 +33,49 @@ func NewAnnotations(path string, file *hcl.File) (Annotations, hcl.Diagnostics)
3533 continue
3634 }
3735
38- match := annotationPattern .FindStringSubmatch (string (token .Bytes ))
39- if len (match ) != 2 {
36+ // tflint-ignore annotation
37+ match := lineAnnotationPattern .FindStringSubmatch (string (token .Bytes ))
38+ if len (match ) == 2 {
39+ ret = append (ret , & LineAnnotation {
40+ Content : strings .TrimSpace (match [1 ]),
41+ Token : token ,
42+ })
43+ continue
44+ }
45+
46+ // tflint-ignore-file annotation
47+ match = fileAnnotationPattern .FindStringSubmatch (string (token .Bytes ))
48+ if len (match ) == 2 {
49+ if ! (token .Range .Start .Line == 1 && token .Range .Start .Column == 1 ) {
50+ diags = append (diags , & hcl.Diagnostic {
51+ Severity : hcl .DiagError ,
52+ Summary : "tflint-ignore-file annotation must be written at the top of file" ,
53+ Detail : fmt .Sprintf ("tflint-ignore-file annotation is written at line %d, column %d" , token .Range .Start .Line , token .Range .Start .Column ),
54+ Subject : token .Range .Ptr (),
55+ })
56+ continue
57+ }
58+ ret = append (ret , & FileAnnotation {
59+ Content : strings .TrimSpace (match [1 ]),
60+ Token : token ,
61+ })
4062 continue
4163 }
42- ret = append (ret , Annotation {
43- Content : strings .TrimSpace (match [1 ]),
44- Token : token ,
45- })
4664 }
4765
4866 return ret , diags
4967}
5068
69+ var lineAnnotationPattern = regexp .MustCompile (`tflint-ignore: ([^\n*/#]+)` )
70+
71+ // LineAnnotation is an annotation for ignoring issues in a line
72+ type LineAnnotation struct {
73+ Content string
74+ Token hclsyntax.Token
75+ }
76+
5177// IsAffected checks if the passed issue is affected with the annotation
52- func (a * Annotation ) IsAffected (issue * Issue ) bool {
78+ func (a * LineAnnotation ) IsAffected (issue * Issue ) bool {
5379 if a .Token .Range .Filename != issue .Range .Filename {
5480 return false
5581 }
@@ -71,6 +97,36 @@ func (a *Annotation) IsAffected(issue *Issue) bool {
7197}
7298
7399// String returns the string representation of the annotation
74- func (a * Annotation ) String () string {
75- return fmt .Sprintf ("annotation:%s (%s)" , a .Content , a .Token .Range .String ())
100+ func (a * LineAnnotation ) String () string {
101+ return fmt .Sprintf ("tflint-ignore: %s (%s)" , a .Content , a .Token .Range .String ())
102+ }
103+
104+ var fileAnnotationPattern = regexp .MustCompile (`tflint-ignore-file: ([^\n*/#]+)` )
105+
106+ // FileAnnotation is an annotation for ignoring issues in a file
107+ type FileAnnotation struct {
108+ Content string
109+ Token hclsyntax.Token
110+ }
111+
112+ // IsAffected checks if the passed issue is affected with the annotation
113+ func (a * FileAnnotation ) IsAffected (issue * Issue ) bool {
114+ if a .Token .Range .Filename != issue .Range .Filename {
115+ return false
116+ }
117+
118+ rules := strings .Split (a .Content , "," )
119+ for i , rule := range rules {
120+ rules [i ] = strings .TrimSpace (rule )
121+ }
122+
123+ if slices .Contains (rules , issue .Rule .Name ()) || slices .Contains (rules , "all" ) {
124+ return true
125+ }
126+ return false
127+ }
128+
129+ // String returns the string representation of the annotation
130+ func (a * FileAnnotation ) String () string {
131+ return fmt .Sprintf ("tflint-ignore-file: %s (%s)" , a .Content , a .Token .Range .String ())
76132}
0 commit comments