From a057738222a64f97d14dd6d484436ac69faef3c5 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Mon, 3 Feb 2025 02:43:16 +0900 Subject: [PATCH] Pluginfy RuboCop Rails This PR adds support for RuboCop's Plugin feature. Since RuboCop Rails still supports some older versions of RuboCop, a conditional check using `RuboCop.const_defined?(:Plugin)` has been added for compatibility. Once only versions of RuboCop that support the Plugin feature are supported, the compatibility code and the `RuboCop::Rails::Inject` module will be removed. This means that the legacy style will gradually become deprecated in the near future. --- .rubocop.yml | 6 ++- README.md | 46 ++++++++++++++++++++-- changelog/new_pluginfy_with_lint_roller.md | 1 + docs/modules/ROOT/pages/usage.adoc | 38 ++++++++++++++++-- lib/rubocop-rails.rb | 11 +++++- lib/rubocop/rails.rb | 2 +- lib/rubocop/rails/plugin.rb | 31 +++++++++++++++ rubocop-rails.gemspec | 3 ++ spec/spec_helper.rb | 3 ++ tasks/cops_documentation.rake | 2 +- 10 files changed, 130 insertions(+), 13 deletions(-) create mode 100644 changelog/new_pluginfy_with_lint_roller.md create mode 100644 lib/rubocop/rails/plugin.rb diff --git a/.rubocop.yml b/.rubocop.yml index dc83f549fc..41046a0e40 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,10 +1,12 @@ # This is the configuration used to check the rubocop source code. inherit_from: .rubocop_todo.yml +plugins: + - rubocop-internal_affairs + - rubocop-rails + require: - - rubocop/cop/internal_affairs - rubocop-performance - - rubocop-rails - rubocop-rspec AllCops: diff --git a/README.md b/README.md index d1a193f0ff..1cc5f1369b 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,48 @@ gem 'rubocop-rails', require: false ## Usage -You need to tell RuboCop to load the Rails extension. There are three +You need to tell RuboCop to load the Rails extension. There are some ways to do this: -### RuboCop configuration file +### RuboCop configuration file (Recommended Style) + +Put this into your `.rubocop.yml`. + +```yaml +plugins: rubocop-rails +``` + +Alternatively, use the following array notation when specifying multiple extensions. + +```yaml +plugins: + - rubocop-other-extension + - rubocop-rails +``` + +Now you can run `rubocop` and it will automatically load the RuboCop Rails +cops together with the standard cops. + +> [!NOTE] +> The plugin system is supported in RuboCop 1.72+. + +### Command line + +```sh +$ rubocop --plugin rubocop-rails +``` + +### Rake task + +```ruby +require 'rubocop/rake_task' + +RuboCop::RakeTask.new do |task| + task.plugins << 'rubocop-rails' +end +``` + +### RuboCop configuration file (Legacy Style) Put this into your `.rubocop.yml`. @@ -45,7 +83,7 @@ require: Now you can run `rubocop` and it will automatically load the RuboCop Rails cops together with the standard cops. -### Command line +### Command line (Legacy Style) ```sh $ rubocop --require rubocop-rails @@ -53,7 +91,7 @@ $ rubocop --require rubocop-rails Note: `--rails` option is required while `rubocop` command supports `--rails` option. -### Rake task +### Rake task (Legacy Style) ```ruby require 'rubocop/rake_task' diff --git a/changelog/new_pluginfy_with_lint_roller.md b/changelog/new_pluginfy_with_lint_roller.md new file mode 100644 index 0000000000..5b940f6249 --- /dev/null +++ b/changelog/new_pluginfy_with_lint_roller.md @@ -0,0 +1 @@ +* [#1434](https://github.com/rubocop/rubocop-rails/pull/1434): Pluginfy RuboCop Rails. ([@koic][]) diff --git a/docs/modules/ROOT/pages/usage.adoc b/docs/modules/ROOT/pages/usage.adoc index 78f77ef854..e8ee60500e 100644 --- a/docs/modules/ROOT/pages/usage.adoc +++ b/docs/modules/ROOT/pages/usage.adoc @@ -1,15 +1,15 @@ = Usage -You need to tell RuboCop to load the Rails extension. There are three +You need to tell RuboCop to load the Rails extension. There are some ways to do this: -== RuboCop configuration file +== RuboCop configuration file (Recommended Style) Put this into your `.rubocop.yml`. [source,yaml] ---- -require: rubocop-rails +plugins: rubocop-rails ---- Now you can run `rubocop` and it will automatically load the RuboCop Rails @@ -19,11 +19,41 @@ cops together with the standard cops. [source,sh] ---- -$ rubocop --require rubocop-rails +$ rubocop --plugin rubocop-rails ---- == Rake task +[source,ruby] +---- +RuboCop::RakeTask.new do |task| + task.plugins << 'rubocop-rails' +end +---- + +NOTE: The plugin system is supported in RuboCop 1.72+. + +== RuboCop configuration file (Legacy Style) + +Put this into your `.rubocop.yml`. + +[source,yaml] +---- +require: rubocop-rails +---- + +Now you can run `rubocop` and it will automatically load the RuboCop Rails +cops together with the standard cops. + +== Command line (Legacy Style) + +[source,sh] +---- +$ rubocop --require rubocop-rails +---- + +== Rake task (Legacy Style) + [source,ruby] ---- RuboCop::RakeTask.new do |task| diff --git a/lib/rubocop-rails.rb b/lib/rubocop-rails.rb index 65c443c91a..062a8cdedd 100644 --- a/lib/rubocop-rails.rb +++ b/lib/rubocop-rails.rb @@ -11,7 +11,16 @@ require_relative 'rubocop/rails/schema_loader' require_relative 'rubocop/rails/schema_loader/schema' -RuboCop::Rails::Inject.defaults! +# FIXME: When RuboCop Rails requires RuboCop 1.72.0+ only, the following compatibility code can be removed. +if RuboCop.const_defined?(:Plugin) + require_relative 'rubocop/rails/plugin' +else + # NOTE: Until the plugin stabilizes, an option to use the older version of RuboCop is provided. + # The plugin will be unified in the future. + require_relative 'rubocop/rails/inject' + + RuboCop::Rails::Inject.defaults! +end require_relative 'rubocop/cop/rails_cops' diff --git a/lib/rubocop/rails.rb b/lib/rubocop/rails.rb index 39ce8159ee..8182869164 100644 --- a/lib/rubocop/rails.rb +++ b/lib/rubocop/rails.rb @@ -8,6 +8,6 @@ module Rails private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT) - ::RuboCop::ConfigObsoletion.files << PROJECT_ROOT.join('config', 'obsoletion.yml') + ConfigObsoletion.files << Pathname("#{__dir__}/../../config/obsoletion.yml") end end diff --git a/lib/rubocop/rails/plugin.rb b/lib/rubocop/rails/plugin.rb new file mode 100644 index 0000000000..0bc5c8375f --- /dev/null +++ b/lib/rubocop/rails/plugin.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'lint_roller' + +module RuboCop + module Rails + # A plugin that integrates RuboCop Rails with RuboCop's plugin system. + class Plugin < LintRoller::Plugin + def about + LintRoller::About.new( + name: 'rubocop-rails', + version: Version::STRING, + homepage: 'https://github.com/rubocop/rubocop-rails', + description: 'A RuboCop extension focused on enforcing Rails best practices and coding conventions.' + ) + end + + def supported?(context) + context.engine == :rubocop + end + + def rules(_context) + LintRoller::Rules.new( + type: :path, + config_format: :rubocop, + value: Pathname.new(__dir__).join('../../../config/default.yml') + ) + end + end + end +end diff --git a/rubocop-rails.gemspec b/rubocop-rails.gemspec index 5c942573e4..ec0a528fa6 100644 --- a/rubocop-rails.gemspec +++ b/rubocop-rails.gemspec @@ -31,9 +31,12 @@ Gem::Specification.new do |s| 'rubygems_mfa_required' => 'true' } + s.metadata['default_lint_roller_plugin'] = 'RuboCop::Rails::Plugin' + s.add_dependency 'activesupport', '>= 4.2.0' # Rack::Utils::SYMBOL_TO_STATUS_CODE, which is used by HttpStatus cop, was # introduced in rack 1.1 + s.add_dependency 'lint_roller', '~> 1.1' s.add_dependency 'rack', '>= 1.1' s.add_dependency 'rubocop', '>= 1.52.0', '< 2.0' s.add_dependency 'rubocop-ast', '>= 1.38.0', '< 2.0' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6efe3b2516..63e7f589ad 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,6 +5,9 @@ require_relative 'support/file_helper' require_relative 'support/shared_contexts' +# FIXME: Once only RuboCop versions that support plugins remain, please remove the `if` condition. +RuboCop::ConfigLoader.inject_defaults!("#{__dir__}/../config/default.yml") if RuboCop.const_defined?(:Plugin) + # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |f| require f } diff --git a/tasks/cops_documentation.rake b/tasks/cops_documentation.rake index 3804b175ee..dc9ae28bcb 100644 --- a/tasks/cops_documentation.rake +++ b/tasks/cops_documentation.rake @@ -22,7 +22,7 @@ task update_cops_documentation: :yard_for_generate_documentation do # NOTE: Update `<>` version for docs/modules/ROOT/pages/cops_rails.adoc # when running release tasks. - RuboCop::Rails::Inject.defaults! + RuboCop::ConfigLoader.inject_defaults!("#{__dir__}/../config/default.yml") CopsDocumentationGenerator.new(departments: deps, extra_info: extra_info).call end