5555)
5656from ansiblelint .constants import RC
5757from ansiblelint .loaders import load_ignore_txt
58+ from ansiblelint .runner import get_matches
5859from ansiblelint .skip_utils import normalize_tag
5960from ansiblelint .version import __version__
6061
@@ -202,6 +203,74 @@ def support_banner() -> None:
202203 )
203204
204205
206+ def fix (runtime_options : Options , result : LintResult , rules : RulesCollection ) -> None :
207+ """Fix the linting errors.
208+
209+ :param options: Options object
210+ :param result: LintResult object
211+ """
212+ match_count = len (result .matches )
213+ _logger .debug ("Begin fixing: %s matches" , match_count )
214+ ruamel_safe_version = "0.17.26"
215+
216+ # pylint: disable=import-outside-toplevel
217+ from packaging .version import Version
218+ from ruamel .yaml import __version__ as ruamel_yaml_version_str
219+
220+ # pylint: enable=import-outside-toplevel
221+
222+ if Version (ruamel_safe_version ) > Version (ruamel_yaml_version_str ):
223+ _logger .warning (
224+ "We detected use of `--fix` feature with a buggy ruamel-yaml %s library instead of >=%s, upgrade it before reporting any bugs like dropped comments." ,
225+ ruamel_yaml_version_str ,
226+ ruamel_safe_version ,
227+ )
228+ acceptable_tags = {"all" , "none" , * rules .known_tags ()}
229+ unknown_tags = set (options .write_list ).difference (acceptable_tags )
230+
231+ if unknown_tags :
232+ _logger .error (
233+ "Found invalid value(s) (%s) for --fix arguments, must be one of: %s" ,
234+ ", " .join (unknown_tags ),
235+ ", " .join (acceptable_tags ),
236+ )
237+ sys .exit (RC .INVALID_CONFIG )
238+ _do_transform (result , options )
239+
240+ rerun = ["yaml" ]
241+ resolved = []
242+ for idx , match in reversed (list (enumerate (result .matches ))):
243+ _logger .debug ("Fixing: (%s of %s) %s" , match_count - idx , match_count , match )
244+ if match .fixed :
245+ _logger .debug ("Fixed, removed: %s" , match )
246+ result .matches .pop (idx )
247+ continue
248+ if match .rule .id not in rerun :
249+ _logger .debug ("Not rerun eligible: %s" , match )
250+ continue
251+
252+ uid = (match .rule .id , match .filename )
253+ if uid in resolved :
254+ _logger .debug ("Previously resolved: %s" , match )
255+ result .matches .pop (idx )
256+ continue
257+ _logger .debug ("Rerunning: %s" , match )
258+ runtime_options .tags = [match .rule .id ]
259+ runtime_options .lintables = [match .filename ]
260+ runtime_options ._skip_ansible_syntax_check = True # noqa: SLF001
261+ new_results = get_matches (rules , runtime_options )
262+ if not new_results .matches :
263+ _logger .debug ("Newly resolved: %s" , match )
264+ result .matches .pop (idx )
265+ resolved .append (uid )
266+ continue
267+ if match in new_results .matches :
268+ _logger .debug ("Still found: %s" , match )
269+ continue
270+ _logger .debug ("Fixed, removed: %s" , match )
271+ result .matches .pop (idx )
272+
273+
205274# pylint: disable=too-many-statements,too-many-locals
206275def main (argv : list [str ] | None = None ) -> int :
207276 """Linter CLI entry point."""
@@ -244,7 +313,6 @@ def main(argv: list[str] | None = None) -> int:
244313
245314 # pylint: disable=import-outside-toplevel
246315 from ansiblelint .rules import RulesCollection
247- from ansiblelint .runner import _get_matches
248316
249317 if options .list_profiles :
250318 from ansiblelint .generate_docs import profiles_as_rich
@@ -265,30 +333,7 @@ def main(argv: list[str] | None = None) -> int:
265333
266334 if isinstance (options .tags , str ):
267335 options .tags = options .tags .split ("," ) # pragma: no cover
268- result = _get_matches (rules , options )
269-
270- if options .write_list :
271- ruamel_safe_version = "0.17.26"
272- from packaging .version import Version
273- from ruamel .yaml import __version__ as ruamel_yaml_version_str
274-
275- if Version (ruamel_safe_version ) > Version (ruamel_yaml_version_str ):
276- _logger .warning (
277- "We detected use of `--fix` feature with a buggy ruamel-yaml %s library instead of >=%s, upgrade it before reporting any bugs like dropped comments." ,
278- ruamel_yaml_version_str ,
279- ruamel_safe_version ,
280- )
281- acceptable_tags = {"all" , "none" , * rules .known_tags ()}
282- unknown_tags = set (options .write_list ).difference (acceptable_tags )
283-
284- if unknown_tags :
285- _logger .error (
286- "Found invalid value(s) (%s) for --fix arguments, must be one of: %s" ,
287- ", " .join (unknown_tags ),
288- ", " .join (acceptable_tags ),
289- )
290- sys .exit (RC .INVALID_CONFIG )
291- _do_transform (result , options )
336+ result = get_matches (rules , options )
292337
293338 mark_as_success = True
294339
@@ -302,6 +347,10 @@ def main(argv: list[str] | None = None) -> int:
302347 for match in result .matches :
303348 if match .tag in ignore_map [match .filename ]:
304349 match .ignored = True
350+ _logger .debug ("Ignored: %s" , match )
351+
352+ if options .write_list :
353+ fix (runtime_options = options , result = result , rules = rules )
305354
306355 app .render_matches (result .matches )
307356
0 commit comments