@@ -316,6 +316,7 @@ When you create a rule that can apply an automatic fix, you need to:
316316- inherit from `` FixableRule ``
317317- specify fix_availability (which can be `` FixAvailability.ALWAYS `` or `` FixAvailability.SOMETIMES `` )
318318- implement `` fix() `` method and return `` Fix `` instance or `` None `` when no fix can be generated
319+ - or instead of implementing `` fix() `` method create `` Fix `` instance and pass it when reporting the issue
319320
320321A `` Fix `` contains a list of `` TextEdit `` entries that describe which lines in the original file should be replaced.
321322The source file is processed as a list of lines, preserving newline characters (`` \n `` ). If you replace one or more lines
@@ -342,10 +343,62 @@ def fix(self, diag: Diagnostic, source_lines: list[str]) -> Fix | None:
342343 )
343344```
344345
345- The `` fix() `` method gets the diagnostic object. You can also read the contents of the source file from the
346+ The `` fix() `` method gets the diagnostic object. You can also read the contents of the source file from the
346347`` source_lines `` list.
347348
348- If, for a particular case, it is not possible to create a valid fix, the `` fix() `` method should return None.
349+ If, for a particular case, it is not possible to create a valid fix, the `` fix() `` method should return None.
350+
351+ It is also possible to create `` Fix `` when reporting the issue. The main benefit is that `` fix() `` method only
352+ receives diagnostic range and raw source lines, and you may have access to more data on how to fix the issue in place
353+ where you found the issue.
354+
355+ The following custom rule checks if the file contains the `` PLACEHOLD `` string at the end of file.
356+ The issue is reported at the the end of the first section, so `` fix() `` method can't fix the issue. That's why
357+ we can create `` Fix `` and pass it to `` report() `` method instead:
358+
359+ ``` python
360+ from robot.parsing.model.statements import Error
361+
362+ from robocop.linter.fix import Fix, FixAvailability, FixApplicability, TextEdit
363+ from robocop.linter.rules import FixableRule, RuleSeverity, VisitorChecker
364+
365+
366+ class CustomWithFix (FixableRule ):
367+ """
368+ Custom rule that does have a fix.
369+
370+ The fix is available only when reporting the issue.
371+ """
372+ name = " fixable-rule"
373+ rule_id = " FIX01"
374+ message = " Custom rule message"
375+ severity = RuleSeverity.INFO
376+ added_in_version = " 8.0.0"
377+ fix_availability = FixAvailability.ALWAYS
378+
379+
380+ class CustomChecker (VisitorChecker ):
381+ fixable_rule: CustomWithFix
382+
383+ def visit_File (self , node ):
384+ if isinstance (node.sections[0 ].body[- 1 ], Error): # placeholder is not recognized as valid statement
385+ return
386+ fix = Fix(
387+ edits = [
388+ TextEdit(rule_id = self .fixable_rule.rule_id,
389+ rule_name = self .fixable_rule.name,
390+ start_line = node.end_lineno,
391+ end_line = node.end_lineno,
392+ start_col = node.end_col_offset + 1 ,
393+ end_col = node.end_col_offset + 1 ,
394+ replacement = " PLACEHOLDER"
395+ )
396+ ],
397+ message = " Replace last character of file with 'PLACEHOLDER'" ,
398+ applicability = FixApplicability.SAFE
399+ )
400+ self .report(self .fixable_rule, lineno = node.lineno, col = node.col_offset + 1 , fix = fix)
401+ ```
349402
350403## Project checks
351404
@@ -361,7 +414,7 @@ be used to run any code, for example, analysis of the project dependencies and a
361414Example project checker:
362415
363416``` python title="project_checker.py"
364- from robocop.config import ConfigManager
417+ from robocop.config_manager import ConfigManager
365418from robocop.linter.rules import Rule, ProjectChecker, RuleSeverity
366419
367420
0 commit comments