Extensions
It’s possible to extend RuboCop with custom (third-party) cops and formatters.
Loading Extensions
Besides the --require
command line option you can also specify ruby
files that should be loaded with the optional require
directive in the
.rubocop.yml
file:
require:
- ../my/custom/file.rb
- rubocop-extension
The paths are directly passed to Kernel.require . If your
extension file is not in $LOAD_PATH , you need to specify the path as
relative path prefixed with ./ explicitly or absolute path. Paths
starting with a . are resolved relative to .rubocop.yml .
If a path containing - is given, it will be used as is, but if we
cannot find the file to load, we will replace - with / and try it
again as when Bundler loads gems.
|
Extension Suggestions
Depending on what gems you have in your bundle, RuboCop might suggest extensions
that can be added to provide further functionality. For instance, if you are using
rspec
without the corresponding rubocop-rspec
extension, RuboCop will suggest
enabling it.
This message can be disabled by adding the following to your configuration:
AllCops:
SuggestExtensions: false
Suggest default extensions if SuggestExtensions: true
.
You can also opt-out of suggestions for a particular extension library as so (unspecified extensions will continue to be notified, as appropriate):
AllCops:
SuggestExtensions:
rubocop-rake: false
Custom Cops
You can configure the custom cops in your .rubocop.yml
just like any
other cop.
Writing your own Cops
If you’d like to create an extension gem, you can use rubocop-extension-generator.
See development to learn how to implement a cop.
Cop Extensions
The main RuboCop gem focuses on the core Ruby language and doesn’t include functionality related to any external Ruby libraries/frameworks. There are, however, many RuboCop extensions dedicated to those and a few of them are maintained by RuboCop’s Core Team.
Official Extensions
-
rubocop-performance - Performance optimization analysis
-
rubocop-rails - Rails-specific analysis
-
rubocop-rspec - RSpec-specific analysis
-
rubocop-minitest - Minitest-specific analysis
-
rubocop-rake - Rake-specific analysis
-
rubocop-sequel - Code style checking for Sequel gem
-
rubocop-thread_safety - Thread-safety analysis
-
rubocop-capybara - Capybara-specific analysis
-
rubocop-factory_bot - factory_bot-specific analysis
Third-party Extensions
-
rubocop-require_tools - Dynamic analysis for missing
require
statements -
rubocop-i18n - i18n wrapper function analysis (
gettext
andrails-i18n
) -
cookstyle - Custom cops and config defaults for Chef Infra Cookbooks
-
rubocop-packaging - Upstream best practices and coding conventions for downstream (e.g. Debian packages) compatibility.
-
rubocop-sorbet - Sorbet-specific analysis
-
rubocop-graphql - GraphQL-specific analysis
-
rubocop-changed - Reduced CI time by analyzing only changed files
-
rubocop-sketchup - SketchUp Ruby API specific analysis
Any extensions missing? Send us a Pull Request!
Configuring an Extension
If you’re writing an extension, you can tie some of its configuration into RuboCop.
Config Obsoletions
When a cop that has been released is later renamed or removed, or one of its parameters is, RuboCop can output error messages letting users know to update their configuration to the newest values. If any obsolete configurations are encountered, RuboCop will output an error message and quit.
You can tie your extension into this system by creating your own obsoletions.yml
file and letting RuboCop know where to find it:
RuboCop::ConfigObsoletion.files << File.expand_path(filename)
There are currently three types of obsoletions that can be defined for cops:
-
renamed
: A cop was changed to have a new name, or moved to a different department. -
removed
: A cop was deleted (usually this is configured withalternatives
or areason
why it was removed). -
split
: A cop was removed and replaced with multiple other cops.
Two additional types are available to be defined for parameter changes. These configurations can apply to multiple cops and multiple parameters at the same time (so are expressed in YAML as an array of hashes):
-
changed_parameters
: A parameter has been renamed. -
changed_enforced_styles
: A previously acceptedEnforcedStyle
value has been changed or removed.
Parameter obsoletions can be set with severity: warning to deprecate an old parameter but still accept it. RuboCop will output a warning but continue to run.
|
Example Obsoletion Configuration
See config/obsoletion.yml
for more examples.
All plural keys (eg. cops , parameters , alternatives , etc.) can either take a single value or an array.
|
renamed:
Layout/AlignArguments: Layout/ArgumentAlignment
Lint/BlockAlignment: Layout/BlockAlignment
removed:
Layout/SpaceAfterControlKeyword:
alternatives: Layout/SpaceAroundKeyword
Lint/InvalidCharacterLiteral:
reason: it was never being actually triggered
split:
Style/MethodMissing:
alternatives:
- Style/MethodMissingSuper
- Style/MissingRespondToMissing
changed_parameters: # must be an array of hashes
- cops:
- Metrics/BlockLength
- Metrics/MethodLength
parameters: ExcludedMethods
alternative: IgnoredMethods
severity: warning
changed_enforced_styles: # must be an array of hashes
- cops: Layout/IndentationConsistency
parameters: EnforcedStyle
value: rails
reason: >
`EnforcedStyle: rails` has been renamed to
`EnforcedStyle: indented_internal_methods`
Custom Formatters
You can customize RuboCop’s output format with custom formatters.
Creating a Custom Formatter
To implement a custom formatter, you need to subclass
RuboCop::Formatter::BaseFormatter
and override some methods,
or implement all formatter API methods by duck typing.
Please see the documents below for more formatter API details.
Using a Custom Formatter from the Command Line
You can tell RuboCop to use your custom formatter with a combination of
--format
and --require
option.
For example, when you have defined MyCustomFormatter
in
./path/to/my_custom_formatter.rb
, you would type this command:
$ rubocop --require ./path/to/my_custom_formatter --format MyCustomFormatter
Template support
RuboCop has API for extensions to support templates such as ERB, Haml, Slim, etc.
Normally, RuboCop extracts one Ruby code from one Ruby file, however there are multiple embedded Ruby codes in one template file. To solve this problem, RuboCop has a mechanism called RuboCop::Runner.ruby_extractors
, to which any Ruby extractor can be added on the extension side.
Ruby extractor must be a callable object that takes a RuboCop::ProcessedSource
and returns an Array
of Hash
that contains Ruby source codes and their offsets from original source code, or returns nil
for unrelated file.
ruby_extractor.call(processed_source)
An example returned value from a Ruby extractor would be as follows:
[
{
offset: 2,
processed_source: #<RuboCop::ProcessedSource>
},
{
offset: 10,
processed_source: #<RuboCop::ProcessedSource>
}
]
On the extension side, the code would be something like this:
RuboCop::Runner.ruby_extractors.unshift(ruby_extractor)
RuboCop::Runners.ruby_extractors
is processed from the beginning and ends when one of them returns a non-nil value. By default, there is a Ruby extractor that returns the given Ruby source code with offset 0, so you can unshift any Ruby extractor before it.
This is still an experimental feature and may change in the future. |