From 9bfda44dc4aa8748fabce8c418f8a0e434d2a11f Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Sun, 3 Sep 2023 11:21:05 -0400 Subject: [PATCH] [Fix #11920] Skip files that don't satisfy gem version reqs --- changelog/new_requires_gem_api.md | 1 + lib/rubocop/cop/base.rb | 1 + lib/rubocop/cop/team.rb | 3 ++ lib/rubocop/rspec/shared_contexts.rb | 14 +++++- spec/rubocop/cop/cop_spec.rb | 65 ++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 changelog/new_requires_gem_api.md diff --git a/changelog/new_requires_gem_api.md b/changelog/new_requires_gem_api.md new file mode 100644 index 000000000000..70370e219a47 --- /dev/null +++ b/changelog/new_requires_gem_api.md @@ -0,0 +1 @@ +* [#12186](https://github.com/rubocop/rubocop/pull/12186): Add new `requires_gem` API for declaring which gems a Cop needs. ([@amomchilov][]) diff --git a/lib/rubocop/cop/base.rb b/lib/rubocop/cop/base.rb index ad806805cb5e..7b3e8686a167 100644 --- a/lib/rubocop/cop/base.rb +++ b/lib/rubocop/cop/base.rb @@ -269,6 +269,7 @@ def active_support_extensions_enabled? end def relevant_file?(file) + return false unless target_satisfies_all_gem_version_requirements? return true unless @config.clusivity_config_for_badge?(self.class.badge) file == RuboCop::AST::ProcessedSource::STRING_SOURCE_NAME || diff --git a/lib/rubocop/cop/team.rb b/lib/rubocop/cop/team.rb index c4bc47801c87..d83199f1cf99 100644 --- a/lib/rubocop/cop/team.rb +++ b/lib/rubocop/cop/team.rb @@ -174,6 +174,9 @@ def support_target_ruby_version?(cop) end def support_target_rails_version?(cop) + # In this case, the rails version was already checked by `#excluded_file?` + return true if defined?(RuboCop::Rails::TargetRailsVersion::USES_REQUIRES_GEM_API) + return true unless cop.class.respond_to?(:support_target_rails_version?) cop.class.support_target_rails_version?(cop.target_rails_version) diff --git a/lib/rubocop/rspec/shared_contexts.rb b/lib/rubocop/rspec/shared_contexts.rb index 2f5e58caa272..b2f8451daa11 100644 --- a/lib/rubocop/rspec/shared_contexts.rb +++ b/lib/rubocop/rspec/shared_contexts.rb @@ -110,7 +110,19 @@ def source_range(range, buffer: source_buffer) let(:config) do hash = { 'AllCops' => all_cops_config, cop_class.cop_name => cur_cop_config }.merge!(other_cops) - RuboCop::Config.new(hash, "#{Dir.pwd}/.rubocop.yml") + config = RuboCop::Config.new(hash, "#{Dir.pwd}/.rubocop.yml") + + rails_version_in_gemfile = Gem::Version.new( + rails_version || RuboCop::Config::DEFAULT_RAILS_VERSION + ) + + allow(config).to receive(:gem_versions_in_target).and_return( + { + 'railties' => rails_version_in_gemfile + } + ) + + config end let(:cop) { cop_class.new(config, cop_options) } diff --git a/spec/rubocop/cop/cop_spec.rb b/spec/rubocop/cop/cop_spec.rb index a84d99a3ce19..81e048ca6374 100644 --- a/spec/rubocop/cop/cop_spec.rb +++ b/spec/rubocop/cop/cop_spec.rb @@ -378,6 +378,71 @@ def autocorrect(node); end it { is_expected.to be(true) } end + + describe 'for a cop with gem version requirements', :restore_registry do + subject { cop.relevant_file?(file) } + + let(:file) { 'foo.rb' } + + let(:cop_class) do + stub_cop_class('CopSpec::CopWithGemReqs') do + requires_gem 'gem1', '>= 1.2.3' + end + end + + before do + allow(config).to receive(:gem_versions_in_target).and_return(gem_versions_in_target) + end + + context 'the target doesn\'t satisfy any of the gem requirements' do + let(:gem_versions_in_target) { {} } + + it { is_expected.to be(false) } + end + + context 'the target has a required gem, but in a version that\'s too old' do + let(:gem_versions_in_target) { { 'gem1' => Gem::Version.new('1.2.2') } } + + it { is_expected.to be(false) } + end + + context 'the target has a required gem, in a supported version' do + let(:gem_versions_in_target) { { 'gem1' => Gem::Version.new('1.2.3') } } + + it { is_expected.to be(true) } + end + + context 'for a cop with multiple gem requirements' do + let(:cop_class) do + stub_cop_class('CopSpec::CopWithGemReqs') do + requires_gem 'gem1', '>= 1.2.3' + requires_gem 'gem2', '>= 4.5.6' + end + end + + context 'the target satisfies one but not all of the gem requirements' do + let(:gem_versions_in_target) do + { + 'gem1' => Gem::Version.new('1.2.3'), + 'gem2' => Gem::Version.new('4.5.5') + } + end + + it { is_expected.to be(false) } + end + + context 'the target has all the required gems with sufficient versions' do + let(:gem_versions_in_target) do + { + 'gem1' => Gem::Version.new('1.2.3'), + 'gem2' => Gem::Version.new('4.5.6') + } + end + + it { is_expected.to be(true) } + end + end + end end describe '#safe_autocorrect?' do