Skip to content

Commit

Permalink
Add new Gemspec/DateAssignment cop
Browse files Browse the repository at this point in the history
Follow rubocop/rubocop-rails#432.

This PR adds new `Gemspec/DateAssignment` cop.

This cop checks that `date =` is not used in gemspec file.
It is set automatically when the gem is packaged.

```ruby
# bad
Gem::Specification.new do |spec|
  s.name = 'your_cool_gem'
  spec.date = Time.now.strftime('%Y-%m-%d')
end

# good
Gem::Specification.new do |spec|
  s.name = 'your_cool_gem'
end
```

RubyGems doesn't expect the value to be set.
https://github.com/rubygems/rubygems/blob/be08d8307eda3b61f0ec0460fe7fbcf647b526e6/lib/rubygems/specification.rb#L1679-L1681
  • Loading branch information
koic authored and bbatsov committed Feb 12, 2021
1 parent cc87fd4 commit f8f1cd4
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/new_add_new_gemspec_date_assignment_cop.md
@@ -0,0 +1 @@
* [#9496](https://github.com/rubocop-hq/rubocop/pull/9496): Add new `Gemspec/DateAssignment` cop. ([@koic][])
7 changes: 7 additions & 0 deletions config/default.yml
Expand Up @@ -203,6 +203,13 @@ 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: '<<next>>'
Include:
- '**/*.gemspec'

Gemspec/DuplicatedAssignment:
Description: 'An attribute assignment method calls should be listed only once in a gemspec.'
Enabled: true
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Expand Up @@ -152,6 +152,7 @@
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/duplicated_assignment'
require_relative 'rubocop/cop/gemspec/ordered_dependencies'
require_relative 'rubocop/cop/gemspec/required_ruby_version'
Expand Down
56 changes: 56 additions & 0 deletions lib/rubocop/cop/gemspec/date_assignment.rb
@@ -0,0 +1,56 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Gemspec
# This cop 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|
# s.name = 'your_cool_gem_name'
# spec.date = Time.now.strftime('%Y-%m-%d')
# end
#
# # good
# Gem::Specification.new do |spec|
# s.name = 'your_cool_gem_name'
# end
#
class DateAssignment < Base
include RangeHelp
extend AutoCorrector

MSG = 'Do not use `date =` in gemspec, it is set automatically when the gem is packaged.'

def_node_matcher :gem_specification, <<~PATTERN
(block
(send
(const
(const {cbase nil?} :Gem) :Specification) :new)
...)
PATTERN

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
2 changes: 2 additions & 0 deletions spec/rubocop/cli/cli_options_spec.rb
Expand Up @@ -541,6 +541,8 @@ class SomeCop < Cop
Enabled: false
Layout:
Enabled: false
Gemspec:
Enabled: false
Style/SomeCop:
Description: Something
Expand Down
53 changes: 53 additions & 0 deletions spec/rubocop/cop/gemspec/date_assignment_spec.rb
@@ -0,0 +1,53 @@
# 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

0 comments on commit f8f1cd4

Please sign in to comment.