diff --git a/changelog/change_integrate_date_assignment_cop.md b/changelog/change_integrate_date_assignment_cop.md new file mode 100644 index 00000000000..8b52c3e6866 --- /dev/null +++ b/changelog/change_integrate_date_assignment_cop.md @@ -0,0 +1 @@ +* [#10245](https://github.com/rubocop/rubocop/pull/10245): **(Breaking)** integrate `Gemspec/DateAssignment` into `Gemspec/DeprecatedAttributeAssignment`. ([@kaitielth][]) diff --git a/config/default.yml b/config/default.yml index 60f1c4b39eb..735e1ba24f9 100644 --- a/config/default.yml +++ b/config/default.yml @@ -235,13 +235,6 @@ Bundler/OrderedGems: #################### Gemspec ############################### -Gemspec/DateAssignment: - Description: 'Checks that `date =` is not used in gemspec file, it is set automatically when the gem is packaged.' - Enabled: pending - VersionAdded: '1.10' - Include: - - '**/*.gemspec' - Gemspec/DependencyVersion: Description: 'Requires or forbids specifying gem dependency versions.' Enabled: false diff --git a/config/obsoletion.yml b/config/obsoletion.yml index b998563c283..141f5a3c9a8 100644 --- a/config/obsoletion.yml +++ b/config/obsoletion.yml @@ -55,6 +55,8 @@ renamed: # Cops that were removed removed: + Gemspec/DateAssignment: + alternatives: Gemspec/DeprecatedAttributeAssignment Layout/SpaceAfterControlKeyword: alternatives: Layout/SpaceAroundKeyword Layout/SpaceBeforeModifierKeyword: diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index df6162b2748..97c30d3b8f6 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -82,7 +82,6 @@ In the following section you find all available cops: === Department xref:cops_gemspec.adoc[Gemspec] -* xref:cops_gemspec.adoc#gemspecdateassignment[Gemspec/DateAssignment] * xref:cops_gemspec.adoc#gemspecdependencyversion[Gemspec/DependencyVersion] * xref:cops_gemspec.adoc#gemspecdeprecatedattributeassignment[Gemspec/DeprecatedAttributeAssignment] * xref:cops_gemspec.adoc#gemspecduplicatedassignment[Gemspec/DuplicatedAssignment] diff --git a/docs/modules/ROOT/pages/cops_gemspec.adoc b/docs/modules/ROOT/pages/cops_gemspec.adoc index 6929b67fe9e..9d33ab12f3b 100644 --- a/docs/modules/ROOT/pages/cops_gemspec.adoc +++ b/docs/modules/ROOT/pages/cops_gemspec.adoc @@ -1,36 +1,5 @@ = Gemspec -== Gemspec/DateAssignment - -|=== -| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed - -| Pending -| Yes -| Yes -| 1.10 -| - -|=== - -Checks that `date =` is not used in gemspec file. -It is set automatically when the gem is packaged. - -=== Examples - -[source,ruby] ----- -# bad -Gem::Specification.new do |spec| - spec.name = 'your_cool_gem_name' - spec.date = Time.now.strftime('%Y-%m-%d') -end - -# good -Gem::Specification.new do |spec| - spec.name = 'your_cool_gem_name' -end ----- - === Configurable attributes |=== diff --git a/lib/rubocop.rb b/lib/rubocop.rb index 8868659df44..11a64ff1224 100644 --- a/lib/rubocop.rb +++ b/lib/rubocop.rb @@ -160,7 +160,6 @@ require_relative 'rubocop/cop/bundler/insecure_protocol_source' require_relative 'rubocop/cop/bundler/ordered_gems' -require_relative 'rubocop/cop/gemspec/date_assignment' require_relative 'rubocop/cop/gemspec/dependency_version' require_relative 'rubocop/cop/gemspec/deprecated_attribute_assignment' require_relative 'rubocop/cop/gemspec/duplicated_assignment' diff --git a/lib/rubocop/cop/gemspec/date_assignment.rb b/lib/rubocop/cop/gemspec/date_assignment.rb deleted file mode 100644 index f13d89855dd..00000000000 --- a/lib/rubocop/cop/gemspec/date_assignment.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true - -module RuboCop - module Cop - module Gemspec - # Checks that `date =` is not used in gemspec file. - # It is set automatically when the gem is packaged. - # - # @example - # - # # bad - # Gem::Specification.new do |spec| - # spec.name = 'your_cool_gem_name' - # spec.date = Time.now.strftime('%Y-%m-%d') - # end - # - # # good - # Gem::Specification.new do |spec| - # spec.name = 'your_cool_gem_name' - # end - # - class DateAssignment < Base - include RangeHelp - include GemspecHelp - extend AutoCorrector - - MSG = 'Do not use `date =` in gemspec, it is set automatically when the gem is packaged.' - - def on_block(block_node) - return unless gem_specification?(block_node) - - block_parameter = block_node.arguments.first.source - - date_assignment = block_node.descendants.detect do |node| - node.send_type? && node.receiver&.source == block_parameter && node.method?(:date=) - end - - return unless date_assignment - - add_offense(date_assignment) do |corrector| - range = range_by_whole_lines(date_assignment.source_range, include_final_newline: true) - - corrector.remove(range) - end - end - end - end - end -end diff --git a/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb b/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb index 3d1acb91bff..938d9f872f4 100644 --- a/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +++ b/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb @@ -4,7 +4,7 @@ module RuboCop module Cop module Gemspec # Checks that deprecated attribute attributes are not set in a gemspec file. - # Removing `test_files` allows the user to receive smaller packed gems. + # Removing deprecated attributes allows the user to receive smaller packed gems. # # @example # @@ -29,7 +29,7 @@ class DeprecatedAttributeAssignment < Base include RangeHelp extend AutoCorrector - MSG = 'Do not set `test_files` in gemspec.' + MSG = 'Do not set `%s` in gemspec.' # @!method gem_specification(node) def_node_matcher :gem_specification, <<~PATTERN @@ -45,14 +45,14 @@ def on_block(block_node) block_parameter = block_node.arguments.first.source - date_assignment = block_node.descendants.detect do |node| - use_test_files?(node, block_parameter) + assignment = block_node.descendants.detect do |node| + use_deprecated_attributes?(node, block_parameter) end + return unless assignment - return unless date_assignment - - add_offense(date_assignment) do |corrector| - range = range_by_whole_lines(date_assignment.source_range, include_final_newline: true) + message = format_message_from + add_offense(assignment, message: message) do |corrector| + range = range_by_whole_lines(assignment.source_range, include_final_newline: true) corrector.remove(range) end @@ -60,16 +60,31 @@ def on_block(block_node) private - def use_test_files?(node, block_parameter) - node, method_name = if node.op_asgn_type? - lhs, _op, _rhs = *node + def node_and_method_name(node, attribute) + if node.op_asgn_type? + lhs, _op, _rhs = *node + [lhs, attribute] + else + [node, "#{attribute}=".to_sym] + end + end + + def use_deprecated_attributes?(node, block_parameter) + %i[test_files date].each do |attribute| + node, method_name = node_and_method_name(node, attribute) + unless node.send_type? && node.receiver&.source == block_parameter && + node.method?(method_name) + next + end - [lhs, :test_files] - else - [node, :test_files=] - end + @attribute = attribute.to_s + return true + end + false + end - node.send_type? && node.receiver&.source == block_parameter && node.method?(method_name) + def format_message_from + format(MSG, attribute: @attribute) end end end diff --git a/spec/rubocop/cop/gemspec/date_assignment_spec.rb b/spec/rubocop/cop/gemspec/date_assignment_spec.rb deleted file mode 100644 index ea3d6ef5075..00000000000 --- a/spec/rubocop/cop/gemspec/date_assignment_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe RuboCop::Cop::Gemspec::DateAssignment, :config do - it 'registers and corrects an offense when using `s.date =`' do - expect_offense(<<~RUBY) - Gem::Specification.new do |s| - s.name = 'your_cool_gem_name' - s.date = Time.now.strftime('%Y-%m-%d') - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use `date =` in gemspec, it is set automatically when the gem is packaged. - s.bindir = 'exe' - end - RUBY - - expect_correction(<<~RUBY) - Gem::Specification.new do |s| - s.name = 'your_cool_gem_name' - s.bindir = 'exe' - end - RUBY - end - - it 'registers and corrects an offense when using `spec.date =`' do - expect_offense(<<~RUBY) - Gem::Specification.new do |spec| - spec.name = 'your_cool_gem_name' - spec.date = Time.now.strftime('%Y-%m-%d') - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use `date =` in gemspec, it is set automatically when the gem is packaged. - spec.bindir = 'exe' - end - RUBY - - expect_correction(<<~RUBY) - Gem::Specification.new do |spec| - spec.name = 'your_cool_gem_name' - spec.bindir = 'exe' - end - RUBY - end - - it 'does not register an offense when using `s.date =` outside `Gem::Specification.new`' do - expect_no_offenses(<<~RUBY) - s.date = Time.now.strftime('%Y-%m-%d') - RUBY - end - - it 'does not register an offense when using `date =` and receiver is not `Gem::Specification.new` block variable' do - expect_no_offenses(<<~RUBY) - Gem::Specification.new do |spec| - s.date = Time.now.strftime('%Y-%m-%d') - end - RUBY - end -end diff --git a/spec/rubocop/cop/gemspec/deprecated_attribute_assignment_spec.rb b/spec/rubocop/cop/gemspec/deprecated_attribute_assignment_spec.rb index 7f8daa64fef..6e1ecfa1f43 100644 --- a/spec/rubocop/cop/gemspec/deprecated_attribute_assignment_spec.rb +++ b/spec/rubocop/cop/gemspec/deprecated_attribute_assignment_spec.rb @@ -1,89 +1,97 @@ # frozen_string_literal: true RSpec.describe RuboCop::Cop::Gemspec::DeprecatedAttributeAssignment, :config do - it 'registers and corrects an offense when using `s.test_files =`' do - expect_offense(<<~RUBY) - Gem::Specification.new do |s| - s.name = 'your_cool_gem_name' - s.test_files = Dir.glob('test/**/*') - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not set `test_files` in gemspec. - s.bindir = 'exe' - end - RUBY + shared_examples 'deprecated attributes' do |attribute, value| + it 'registers and corrects an offense when using `s.rubygems_version =`' do + expect_offense(<<~RUBY) + Gem::Specification.new do |s| + s.name = 'your_cool_gem_name' + s.#{attribute} = #{value} + ^^^^^#{'^' * (attribute.size + value.size)} Do not set `#{attribute}` in gemspec. + s.bindir = 'exe' + end + RUBY - expect_correction(<<~RUBY) - Gem::Specification.new do |s| - s.name = 'your_cool_gem_name' - s.bindir = 'exe' - end - RUBY - end + expect_correction(<<~RUBY) + Gem::Specification.new do |s| + s.name = 'your_cool_gem_name' + s.bindir = 'exe' + end + RUBY + end - it 'registers and corrects an offense when using `s.test_files +=`' do - expect_offense(<<~RUBY) - Gem::Specification.new do |s| - s.name = 'your_cool_gem_name' - s.test_files += Dir.glob('test/**/*') - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not set `test_files` in gemspec. - s.bindir = 'exe' - end - RUBY + it 'registers and corrects an offense when using `spec.rubygems_version =`' do + expect_offense(<<~RUBY) + Gem::Specification.new do |spec| + spec.name = 'your_cool_gem_name' + spec.#{attribute} = #{value} + ^^^^^^^^#{'^' * (attribute.size + value.size)} Do not set `#{attribute}` in gemspec. + spec.bindir = 'exe' + end + RUBY - expect_correction(<<~RUBY) - Gem::Specification.new do |s| - s.name = 'your_cool_gem_name' - s.bindir = 'exe' - end - RUBY - end + expect_correction(<<~RUBY) + Gem::Specification.new do |spec| + spec.name = 'your_cool_gem_name' + spec.bindir = 'exe' + end + RUBY + end - it 'registers and corrects an offense when using `spec.test_files =`' do - expect_offense(<<~RUBY) - Gem::Specification.new do |spec| - spec.name = 'your_cool_gem_name' - spec.test_files = Dir.glob('test/**/*') - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not set `test_files` in gemspec. - spec.bindir = 'exe' - end - RUBY + it 'does not register an offense when using `s.rubygems_version =` outside `Gem::Specification.new`' do + expect_no_offenses(<<~RUBY) + s.#{attribute} = #{value} + RUBY + end - expect_correction(<<~RUBY) - Gem::Specification.new do |spec| - spec.name = 'your_cool_gem_name' - spec.bindir = 'exe' - end - RUBY + it 'does not register an offense when using `rubygems_version =` and receiver is not `Gem::Specification.new` block variable' do + expect_no_offenses(<<~RUBY) + Gem::Specification.new do |spec| + s.#{attribute} = #{value} + end + RUBY + end end - it 'registers and corrects an offense when using `spec.test_files +=`' do - expect_offense(<<~RUBY) - Gem::Specification.new do |spec| - spec.name = 'your_cool_gem_name' - spec.test_files += Dir.glob('test/**/*') - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not set `test_files` in gemspec. - spec.bindir = 'exe' - end - RUBY + shared_examples 'deprecated attributes with addition' do |attribute, value| + it 'registers and corrects an offense when using `s.rubygems_version +=`' do + expect_offense(<<~RUBY) + Gem::Specification.new do |s| + s.name = 'your_cool_gem_name' + s.#{attribute} += #{value} + ^^^^^^#{'^' * (attribute.size + value.size)} Do not set `#{attribute}` in gemspec. + s.bindir = 'exe' + end + RUBY - expect_correction(<<~RUBY) - Gem::Specification.new do |spec| - spec.name = 'your_cool_gem_name' - spec.bindir = 'exe' - end - RUBY - end + expect_correction(<<~RUBY) + Gem::Specification.new do |s| + s.name = 'your_cool_gem_name' + s.bindir = 'exe' + end + RUBY + end - it 'does not register an offense when using `s.test_files =` outside `Gem::Specification.new`' do - expect_no_offenses(<<~RUBY) - s.test_files = Dir.glob('test/**/*') - RUBY - end + it 'registers and corrects an offense when using `spec.rubygems_version +=`' do + expect_offense(<<~RUBY) + Gem::Specification.new do |spec| + spec.name = 'your_cool_gem_name' + spec.#{attribute} += #{value} + ^^^^^^^^^#{'^' * (attribute.size + value.size)} Do not set `#{attribute}` in gemspec. + spec.bindir = 'exe' + end + RUBY - it 'does not register an offense when using `test_files =` and receiver is not `Gem::Specification.new` block variable' do - expect_no_offenses(<<~RUBY) - Gem::Specification.new do |spec| - s.test_files = Dir.glob('test/**/*') - end - RUBY + expect_correction(<<~RUBY) + Gem::Specification.new do |spec| + spec.name = 'your_cool_gem_name' + spec.bindir = 'exe' + end + RUBY + end end + + it_behaves_like 'deprecated attributes', 'date', "Time.now.strftime('%Y-%m-%d')" + it_behaves_like 'deprecated attributes', 'test_files', "Dir.glob('test/**/*')" + it_behaves_like 'deprecated attributes with addition', 'test_files', "Dir.glob('test/**/*')" end