24
24
later in the document).
25
25
* Set ``forbid-duplicated-anchors`` to ``true`` to avoid duplications of a same
26
26
anchor.
27
+ * Set ``forbid-unused-anchors`` to ``true`` to avoid anchors being declared but
28
+ not used anywhere in the YAML document via alias.
27
29
28
30
.. rubric:: Default values (when enabled)
29
31
33
35
anchors:
34
36
forbid-undeclared-aliases: true
35
37
forbid-duplicated-anchors: false
38
+ forbid-unused-anchors: false
36
39
37
40
.. rubric:: Examples
38
41
78
81
---
79
82
- &anchor Foo Bar
80
83
- &anchor [item 1, item 2]
84
+
85
+ #. With ``anchors: {forbid-unused-anchors: true}``
86
+
87
+ the following code snippet would **PASS**:
88
+ ::
89
+
90
+ ---
91
+ - &anchor
92
+ foo: bar
93
+ - *anchor
94
+
95
+ the following code snippet would **FAIL**:
96
+ ::
97
+
98
+ ---
99
+ - &anchor
100
+ foo: bar
101
+ - items:
102
+ - item1
103
+ - item2
81
104
"""
82
105
83
106
89
112
ID = 'anchors'
90
113
TYPE = 'token'
91
114
CONF = {'forbid-undeclared-aliases' : bool ,
92
- 'forbid-duplicated-anchors' : bool }
115
+ 'forbid-duplicated-anchors' : bool ,
116
+ 'forbid-unused-anchors' : bool }
93
117
DEFAULT = {'forbid-undeclared-aliases' : True ,
94
- 'forbid-duplicated-anchors' : False }
118
+ 'forbid-duplicated-anchors' : False ,
119
+ 'forbid-unused-anchors' : False }
95
120
96
121
97
122
def check (conf , token , prev , next , nextnext , context ):
98
- if conf ['forbid-undeclared-aliases' ] or conf ['forbid-duplicated-anchors' ]:
99
- if isinstance (token , (yaml .StreamStartToken , yaml .DocumentStartToken )):
100
- context ['anchors' ] = set ()
123
+ if (conf ['forbid-undeclared-aliases' ] or
124
+ conf ['forbid-duplicated-anchors' ] or
125
+ conf ['forbid-unused-anchors' ]):
126
+ if isinstance (token , (
127
+ yaml .StreamStartToken ,
128
+ yaml .DocumentStartToken ,
129
+ yaml .DocumentEndToken )):
130
+ context ['anchors' ] = {}
101
131
102
132
if (conf ['forbid-undeclared-aliases' ] and
103
133
isinstance (token , yaml .AliasToken ) and
@@ -113,6 +143,32 @@ def check(conf, token, prev, next, nextnext, context):
113
143
token .start_mark .line + 1 , token .start_mark .column + 1 ,
114
144
f'found duplicated anchor "{ token .value } "' )
115
145
116
- if conf ['forbid-undeclared-aliases' ] or conf ['forbid-duplicated-anchors' ]:
146
+ if conf ['forbid-unused-anchors' ]:
147
+ # Unused anchors can only be detected at the end of Document.
148
+ # End of document can be either
149
+ # - end of stream
150
+ # - end of document sign '...'
151
+ # - start of a new document sign '---'
152
+ # If next token indicates end of document,
153
+ # check if the anchors have been used or not.
154
+ # If they haven't been used, report problem on those anchors.
155
+ if isinstance (next , (yaml .StreamEndToken ,
156
+ yaml .DocumentStartToken ,
157
+ yaml .DocumentEndToken )):
158
+ for anchor , info in context ['anchors' ].items ():
159
+ if not info ['used' ]:
160
+ yield LintProblem (info ['line' ] + 1 ,
161
+ info ['column' ] + 1 ,
162
+ f"found unused anchor { anchor } " )
163
+ elif isinstance (token , yaml .AliasToken ):
164
+ context ['anchors' ].get (token .value , {})['used' ] = True
165
+
166
+ if (conf ['forbid-undeclared-aliases' ] or
167
+ conf ['forbid-duplicated-anchors' ] or
168
+ conf ['forbid-unused-anchors' ]):
117
169
if isinstance (token , yaml .AnchorToken ):
118
- context ['anchors' ].add (token .value )
170
+ context ['anchors' ][token .value ] = {
171
+ "line" : token .start_mark .line ,
172
+ "column" : token .start_mark .column ,
173
+ "used" : False
174
+ }
0 commit comments