How to query which RuboCop rules apply to a file?

89 views Asked by At

I am working on a tool to analyze how rubocop is used (enabled/disabled) and fixed (excluded into todo lists) in certain areas of the codebase. Given the multitude of config options, I think I am looking for a way to programmatically ask RuboCop whether given a file or folder, a certain rule is enabled and whether this file is excluded via a todo or not. Is there an API for this?

I have so far spelunked in https://github.com/rubocop/rubocop to see if I could find an API... Searched via SO and google and can't find anything.

1

There are 1 answers

1
cschroed On BEST ANSWER

I don't think there's public interface for what you want. This mobilize_team method in the Runner is what instantiates a RuboCop::Cop::Team. The team object determines the cops to use in this roundup_relevant_cops method. Both of these methods are private, but you could use send to work around that.

For example, say that we have a project with two files called test_one.rb and test_two.rb.

The .rubocop_todo.yml says that one of the files still needs to be handled:

# .rubocop_todo.yml
Style/FrozenStringLiteralComment:
  Exclude:
    - 'test_two.rb'

The .rubocop.yml config says that we just care about Style/FrozenStringLiteralComment:

# .rubocop.yml
inherit_from: .rubocop_todo.yml

AllCops:
  DisabledByDefault: true

Style/FrozenStringLiteralComment:
  Enabled: true

We can see the cops that RuboCop will apply to each file if we do this:

require 'rubocop'

# Set up the Runner. Assumes no special command line options are involved.
options, _paths = RuboCop::Options.new.parse([])
config_store = RuboCop::ConfigStore.new
runner = RuboCop::Runner.new(options, config_store)

# For each file, figure out which cops are enabled for that file
['test_one.rb', 'test_two.rb'].each do |filename|
  full_path = File.join(Dir.pwd, filename)
  config = config_store.for_file(full_path)
  source = RuboCop::ProcessedSource.from_file(full_path, config.target_ruby_version)
  team = runner.send(:mobilize_team, source)
  cops = team.send(:roundup_relevant_cops, source)
  puts "#{filename}: #{cops.map(&:name).join(', ')}"
end

This will show this output:

test_one.rb: Lint/Syntax, Style/FrozenStringLiteralComment
test_two.rb: Lint/Syntax

Because of this special condition in enable_cop? the Lint/Syntax cop is always enabled. And since test_one.rb isn't included in the TODO list, it is the only file that qualifies for the Style/FrozenStringLiteralComment cop.