Skip to content

Commit

Permalink
Required ruby version fixes (rubocop#9515)
Browse files Browse the repository at this point in the history
- Create `Gem::Requirement` from required_ruby_version
- Return first `KNOWN_RUBY` that satisfies the requirement when one exists
- Support more types of version entries
  • Loading branch information
HeroProtagonist committed Feb 20, 2021
1 parent d198e92 commit 3ade276
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 57 deletions.
1 change: 1 addition & 0 deletions changelog/fix_return_minimal_known_ruby_version_from.md
@@ -0,0 +1 @@
* [#9482](https://github.com/rubocop-hq/rubocop/issues/9482): Return minimal known ruby version from gemspecs `required_ruby_version`. ([@HeroProtagonist][])
32 changes: 19 additions & 13 deletions lib/rubocop/target_ruby.rb
Expand Up @@ -165,14 +165,10 @@ def find_version
file = gemspec_filepath
return unless file && File.file?(file)

version = version_from_gemspec_file(file)
return if version.nil?
right_hand_side = version_from_gemspec_file(file)
return if right_hand_side.nil?

requirement = version.children.last
return version_from_array(version) if version.array_type?
return version_from_array(requirement) if gem_requirement? version

version_from_str(version.str_content)
find_minimal_known_ruby(right_hand_side)
end

def gemspec_filename
Expand All @@ -192,15 +188,25 @@ def version_from_gemspec_file(file)
required_ruby_version(processed_source.ast).first
end

def version_from_right_hand_side(right_hand_side)
if right_hand_side.array_type?
version_from_array(right_hand_side)
elsif gem_requirement?(right_hand_side)
right_hand_side.children.last.value
else
right_hand_side.value
end
end

def version_from_array(array)
versions = array.children.map { |v| version_from_str(v.is_a?(String) ? v : v.str_content) }
versions.compact.min
array.children.map(&:value)
end

def version_from_str(str)
str.match(/^(?:>=|<=)?\s*(?<version>\d+(?:\.\d+)*)/) do |md|
md[:version].to_f
end
def find_minimal_known_ruby(right_hand_side)
version = version_from_right_hand_side(right_hand_side)
requirement = Gem::Requirement.new(version)

KNOWN_RUBIES.detect { |v| requirement.satisfied_by?(Gem::Version.new("#{v}.99")) }
end
end

Expand Down
60 changes: 16 additions & 44 deletions spec/rubocop/target_ruby_spec.rb
Expand Up @@ -294,82 +294,68 @@
let(:base_path) { configuration.base_dir_for_path_parameters }
let(:gemspec_file_path) { File.join(base_path, 'example.gemspec') }

it 'sets target_ruby from required_ruby_version from exact version' do
it 'sets target_ruby from inclusive range' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
s.name = 'test'
s.required_ruby_version = '2.7.4'
s.required_ruby_version = '>= 2.6.1'
s.licenses = ['MIT']
end
HEREDOC

create_file(gemspec_file_path, content)
expect(target_ruby.version).to eq 2.7
expect(target_ruby.version).to eq 2.6
end

it 'sets target_ruby from required_ruby_version from inclusive range' do
it 'sets target_ruby from exclusive range' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
s.name = 'test'
s.required_ruby_version = '>= 3.0.0'
s.required_ruby_version = '> 2.4.1'
s.licenses = ['MIT']
end
HEREDOC

create_file(gemspec_file_path, content)
expect(target_ruby.version).to eq 3.0
expect(target_ruby.version).to eq 2.4
end

it 'sets default target_ruby from exclusive range' do
it 'sets target_ruby from approximate version' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
s.name = 'test'
s.required_ruby_version = '< 3.0.0'
s.required_ruby_version = '~> 2.5.0'
s.licenses = ['MIT']
end
HEREDOC

create_file(gemspec_file_path, content)
expect(target_ruby.version).to eq default_version
expect(target_ruby.version).to eq 2.5
end
end

context 'when file contains `required_ruby_version` as a requirement' do
let(:base_path) { configuration.base_dir_for_path_parameters }
let(:gemspec_file_path) { File.join(base_path, 'example.gemspec') }

it 'sets target_ruby from required_ruby_version from exact requirement version' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
s.name = 'test'
s.required_ruby_version = Gem::Requirement.new('2.7.4')
s.licenses = ['MIT']
end
HEREDOC

create_file(gemspec_file_path, content)
expect(target_ruby.version).to eq 2.7
end

it 'sets target_ruby from required_ruby_version from inclusive requirement range' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
s.name = 'test'
s.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
s.required_ruby_version = Gem::Requirement.new('>= 2.3.1')
s.licenses = ['MIT']
end
HEREDOC

create_file(gemspec_file_path, content)
expect(target_ruby.version).to eq 3.0
expect(target_ruby.version).to eq default_version
end

it 'sets default target_ruby from exclusive requirement range' do
it 'sets first known ruby version that satisfies requirement' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
Expand All @@ -388,7 +374,7 @@
let(:base_path) { configuration.base_dir_for_path_parameters }
let(:gemspec_file_path) { File.join(base_path, 'example.gemspec') }

it 'sets target_ruby from the lowest value' do
it 'sets target_ruby to the minimal version satisfying the requirements' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
Expand All @@ -402,32 +388,18 @@
expect(target_ruby.version).to eq 2.6
end

it 'sets target_ruby from required_ruby_version with inclusive range' do
it 'sets target_ruby from required_ruby_version with many requirements' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
s.name = 'test'
s.required_ruby_version = ['<=2.7.4', '>2.6.5']
s.required_ruby_version = ['<=2.7.4', '>2.4.5', '~>2.5.1']
s.licenses = ['MIT']
end
HEREDOC

create_file(gemspec_file_path, content)
expect(target_ruby.version).to eq 2.7
end

it 'sets default target_ruby with all exclusive ranges' do
content =
<<-HEREDOC
Gem::Specification.new do |s|
s.name = 'test'
s.required_ruby_version = ['<2.7.4', '>2.6.5']
s.licenses = ['MIT']
end
HEREDOC

create_file(gemspec_file_path, content)
expect(target_ruby.version).to eq default_version
expect(target_ruby.version).to eq 2.5
end
end

Expand Down

0 comments on commit 3ade276

Please sign in to comment.