8.0.0 (2026-02-11)¶
Breaking changes¶
- dropped support for Python 3.9
- dropped support for Robot Framework 4
Robocop can still be used to lint/format Robot Framework 4 code. Install it in the environment
with supported version installed (5+) and use --target-version option.
- Deprecated
deprecated-statementrule
It is now replaced by new deprecated-- rules after split (covered in new features).
Fix the breaking change by removing deprecated-statement from your configuration.
- Deprecated
ReplaceReturnsformatter
The functionality is now replaced by fix of new deprecated-return-keyword rule.
Remove ReplaceReturns from your configuration.
- Deprecated
AddMissingEndformatter
I have decided to not keep formatters that fix incorrect / invalid syntax.
It should be either raised as a rule violation (and potentially fixed) or addressed
manually.
Remove AddMissingEnd from your configuration.
- refactored source files handling with common
SourceFileclass - redesigned configuration layer for typing safety and OOP friendliness
It is an internal change, part of a bigger effort of improving Robocop design. This shouldn't affect you, but if you are using Robocop internal methods directly, you will need to update the usage. It also affects Robotcode, but I have raised the appropriate fix PR, and it should be updated soon.
Features¶
- Fixable rules! (#1617) (128c849)
robocop check now supports --fix. We can now define a potential fix for the rule.
When running robocop, if raised issues have fix, it will be mentioned in the summary:
Currently, I have added a few new rules with fixes and implemented fix for a few old rules.
Over time, I will go over existing rules and check which rules can benefit from having automatic fix.
It also means a shift in how we perceive format - ideally I want format to focus on general formatting,
whitespace changes, etc. For that reason I have already replaced ReplaceReturns formatter with its equivalent
in rules (deprecated-return-keyword). From now on, if the aim is to fix an issue in the code, typically
the rule with a fix will be a better option. You can find which rules currently have fix by running:
> robocop list rules --with-fix
DEPR07 [W]: deprecated-force-tags: 'Force Tags' is deprecated, use 'Test Tags' instead (enabled) [fixable]
DEPR10 [W]: deprecated-return-keyword: '{statement_name}' is deprecated, use '{alternative}' instead (enabled) [fixable]
DEPR11 [W]: deprecated-return-setting: '[Return]' is deprecated, use 'RETURN' instead (enabled) [fixable]
SPC01 [W]: trailing-whitespace: Trailing whitespace at the end of line (enabled) [fixable]
Altogether 4 rules (4 enabled).
It is also marked in our documentation.
I have mimicked similar tools and robocop also has support for --diff (show fixes output without applying them)
and --unsafe-fixes (apply fixes labelled as unsafe).
It is also possible to define which rules are fixable or unfixable. Fixable will work as select - only fixing listed rules,
and unfixable works as ignore - fixing all rules except listed:
Custom rules also support fixes. It is documented in our documentation (https://robocop.dev/stable/linter/custom_rules/). Short example:
class ExampleRuleWithFix(FixableRule):
"""
Check if there is a parametrised substring in the test case name.
"""
name = "rule-name"
rule_id = "EX01"
message = "Error message"
severity = RuleSeverity.WARNING
fix_availability = FixAvailability.ALWAYS
def fix(self, diag: Diagnostic, source_lines: list[str]) -> Fix | None:
return Fix(
edits=[TextEdit.replace_at_range(self.rule_id, self.name, diag.range, "")],
message="Remove unnecessary part of string",
applicability=FixApplicability.SAFE,
)
Fixes can be defined inside the Rule class - it will receive a raised diagnostic and create fix based on it. Otherwise, you can create a fix manually and pass it when reporting the rule violation.
- deprecate
deprecated-statementrule and split into new rules
deprecated-statement covered various deprecated statements. It wasn't ideal when user wanted to ignore specific
deprecation and interfered with fixes. The rule is now split into the following new rules:
- DEPR08
deprecated-run-keyword-if - DEPR09
deprecated-loop-keyword - DEPR10
deprecated-return-keyword(with a fix) -
DEPR11
deprecated-return-setting(with a fix) -
Robocop is now more verbose
By default, Robocop didn't print anything if there wasn't any issue found and no report was enabled. It wasn't friendly for new users or for quick checks without configuration. Now Robocop prints a short summary, regardless of enabled reports:
Also, Robocop will now print a warning if non-existing rule is used in the select / extend-select / ignore:
- Keyword naming rules and formatters quotation handling
Updated keyword naming rules (such as wrong-case-in-keyword-call) and RenameKeywords formatter to ignore quoted
values. Refactored variable naming handling.
Following name:
Will be formatted (with the default configuration) to:
- performance improvements
Several performance improvements in the configuration handling, caching and also specific rules which were refactored.
For example unused-variable, unused-argument, inconsistent-variable-name and possible-overwriting rules
are now 2x faster on average.
We have also performance tests for benchmarking. Since new features will slowly slow down Robocop, it is important to monitor it and keep improving the performance based on arbitary results. (#1611) (eea1c56)
report()can be now used from the rule class (#1644) (8aff795)
The current goal is to move rule-specific code into the rule classes and keep visiting / context-specific code in the visitor. Also, to minimalize the number of visitors, since we currently revisit the file for each checker. It's an internal change, but I am adding new tools that can be also reused in the custom rules.
report() could be only from inside the checker, but now it can be used within the rule class. It allows
to define check() methods:
Rule:
class LibraryImportRule(Rule):
"""
<docs>
"""
<rule attributes>
def check(self, node: LibraryImport) -> None:
if not self.enabled:
return
with_name_token = node.get_token(Token.WITH_NAME)
if not with_name_token or with_name_token.value == "AS":
return
self.report(
node=with_name_token,
col=with_name_token.col_offset + 1,
end_col=with_name_token.end_col_offset + 1,
)
Visitor / Checker:
(...)
def visit_LibraryImport(self, node: LibraryImport) -> None: # noqa: N802
self.deprecated_with_name.check(node)
- Robocop is now fully typed (#1661) (42045dc)
- list rules can now return the result when used from the Python (#1629) (457d135)
- MCP is now aware of local config (#1673) (55e18b6)
MCP overwrote local config before. It should now detect a configuration file in the directory when it runs and loads custom configuration, rules and formatters.
- Skip documentation by default in NormalizeSeparators (#1672) (5b1ae35)
- Added or improved support for variable type conversion (#1654) (#1650) (#1651) (#1652) #1653)
Updated rules:
duplicate-argument(#1654) (af8d35a)duplicated-assigned-var-name(#1650) (3f304e5)inconsistent-variable-name(#1651) (9a0f525)non-local-variables-should-be-uppercase(#1652) (97f4725)-
possible-variable-overwriting(#1653) (322cd95) -
New rule ANN04
set-keyword-with-type
Variable type conversion does not work with Set Test/Suite/Global Variable keywords. Robocop will detect the following syntax:
- Add
case_normalizationparameter to enforce case by RenameKeywords (#1667) (49a0b02)
RenameKeywords formatter only changed case for the first letter (in the sentence, or for each word).
It did not change the case of the remaining letters. It is now possible with case_normalization parameter.
When configured, it will rename the following:
into
Bug fixes¶
- add explicit typing-extensions dependency (#1680) (b406f25)
- Fix #1174 expression-can-be-simplified raised for == 0 (#1649) (d0f4985)
- Fix #1422 - ReplaceWithVAR formatter replacing variables with item access (#1648) (a9c3377)
- Fix caching the issues with fixes (#1623) (256874b)
- Fix extend-select matching only on rule id, not on rule name (#1669) (403ff7d)
- Fix format --extend-select not enabling formatters (#1668) (3c76c50)
- Fix not all issue format parameters supported by extended output (#1624) (727c38d)
- Fix too-long-variable-name throwing exception on Set X Variable without arguments (#1675) (3a55663)
- multiple paths passed to robocop check/format command resolving to the same config (#1614) (bdcfd48)
- Fix rst-style urls in the documentation (#1640) (eb1dcab)
- Update RenameVariables formatter so it treats numbers as part of a word and does not split on it (#1663) (eddfd96)