Skip to content

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-statement rule

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 ReplaceReturns formatter

The functionality is now replaced by fix of new deprecated-return-keyword rule. Remove ReplaceReturns from your configuration.

  • Deprecated AddMissingEnd formatter

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 SourceFile class
  • 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:

Found 1 issue.
1 fixable with the '--fix' option.

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:

[tool.robocop.lint]
fix = true
unfixable = [
  "rule-name-or-id",
  "other-rule"
]

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-statement rule 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:

Found 8 issues.
No issues found.

Also, Robocop will now print a warning if non-existing rule is used in the select / extend-select / ignore:

Option value 'idontexist' from '--select' did not match with any rule name or id.
  • 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:

    Keyword with "potential embedded value" and ${variable}

Will be formatted (with the default configuration) to:

    Keyword With "potential embedded value" And ${variable}
  • 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:

Set Suite Variable    ${variable: int}    value
  • Add case_normalization parameter 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:

*** Keywords ***
keyword name
    Keyword Call
    EXECUTE actioN

into

*** Keywords ***
Keyword Name
    Keyword Call
    Execute Action

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)