Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support asdf's .tool-versions file #9319

Merged
merged 1 commit into from
Jan 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/new_support_asdfs_toolversions_file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#9319](https://github.com/rubocop-hq/rubocop/pull/9319): Support asdf's .tool-versions file. ([@noon-ng][])
13 changes: 7 additions & 6 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,13 @@ AllCops:
# If a value is specified for TargetRubyVersion then it is used. Acceptable
# values are specificed as a float (i.e. 2.5); the teeny version of Ruby
# should not be included. If the project specifies a Ruby version in the
# .ruby-version file, Gemfile or gems.rb file, RuboCop will try to determine
# the desired version of Ruby by inspecting the .ruby-version file first,
# followed by the Gemfile.lock or gems.locked file. (Although the Ruby version
# is specified in the Gemfile or gems.rb file, RuboCop reads the final value
# from the lock file.) If the Ruby version is still unresolved, RuboCop will
# use the oldest officially supported Ruby version (currently Ruby 2.4).
# .tool-versions or .ruby-version files, Gemfile or gems.rb file, RuboCop will
# try to determine the desired version of Ruby by inspecting the
# .tool-versions file first, then .ruby-version, followed by the Gemfile.lock
# or gems.locked file. (Although the Ruby version is specified in the Gemfile
# or gems.rb file, RuboCop reads the final value from the lock file.) If the
# Ruby version is still unresolved, RuboCop will use the oldest officially
# supported Ruby version (currently Ruby 2.4).
TargetRubyVersion: ~
# Determines if a notification for extension libraries should be shown when
# rubocop is run. Keys are the name of the extension, and values are an array
Expand Down
58 changes: 47 additions & 11 deletions lib/rubocop/target_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,61 @@ def find_version
# The target ruby version may be found in a .ruby-version file.
# @api private
class RubyVersionFile < Source
FILENAME = '.ruby-version'
RUBY_VERSION_FILENAME = '.ruby-version'
RUBY_VERSION_PATTERN = /\A(?:ruby-)?(?<version>\d+\.\d+)/.freeze

def name
"`#{FILENAME}`"
"`#{RUBY_VERSION_FILENAME}`"
end

private

def filename
RUBY_VERSION_FILENAME
end

def pattern
RUBY_VERSION_PATTERN
end

def find_version
file = ruby_version_file
file = version_file
return unless file && File.file?(file)

# rubocop:disable Lint/MixedRegexpCaptureTypes
# `(ruby-)` is not a capture type.
File.read(file).match(/\A(ruby-)?(?<version>\d+\.\d+)/) do |md|
# rubocop:enable Lint/MixedRegexpCaptureTypes
File.read(file).match(pattern) do |md|
md[:version].to_f
end
end

def ruby_version_file
@ruby_version_file ||=
@config.find_file_upwards(FILENAME,
def version_file
@version_file ||=
@config.find_file_upwards(filename,
@config.base_dir_for_path_parameters)
end
end

# The target ruby version may be found in a .tool-versions file, in a line
# starting with `ruby`.
# @api private
class ToolVersionsFile < RubyVersionFile
TOOL_VERSIONS_FILENAME = '.tool-versions'
TOOL_VERSIONS_PATTERN = /\Aruby (?:ruby-)?(?<version>\d+\.\d+)/.freeze

def name
"`#{TOOL_VERSIONS_FILENAME}`"
end

private

def filename
TOOL_VERSIONS_FILENAME
end

def pattern
TOOL_VERSIONS_PATTERN
end
end

# The lock file of Bundler may identify the target ruby version.
# @api private
class BundlerLockFile < Source
Expand Down Expand Up @@ -194,7 +222,15 @@ def self.supported_versions
KNOWN_RUBIES
end

SOURCES = [RuboCopConfig, RubyVersionFile, BundlerLockFile, GemspecFile, Default].freeze
SOURCES = [
RuboCopConfig,
RubyVersionFile,
ToolVersionsFile,
BundlerLockFile,
GemspecFile,
Default
].freeze

private_constant :SOURCES

def initialize(config)
Expand Down
34 changes: 33 additions & 1 deletion spec/rubocop/target_ruby_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,45 @@
end
end

it 'does not read Gemfile.lock or gems.locked' do
it 'does not read .tool-versions, Gemfile.lock or gems.locked' do
expect(File).not_to receive(:file?).with('.tool-versions')
expect(File).not_to receive(:file?).with('Gemfile')
expect(File).not_to receive(:file?).with('gems.locked')
target_ruby.version
end
end

context 'when .tool-versions is present' do
before do
dir = configuration.base_dir_for_path_parameters
create_file(File.join(dir, '.tool-versions'), tool_versions)
end

context 'when .tool-versions contains a ruby version' do
let(:tool_versions) { ['ruby 3.0.0', 'nodejs 14.9.0'] }
let(:ruby_version_to_f) { 3.0 }

it 'reads it to determine the target ruby version' do
expect(target_ruby.version).to eq ruby_version_to_f
end

it 'does not read Gemfile.lock, gems.locked' do
expect(File).not_to receive(:file?).with(/Gemfile/)
expect(File).not_to receive(:file?).with(/gems\.locked/)
target_ruby.version
end
end

context 'when .tool-versions does not contain a ruby version' do
let(:tool_versions) { ['nodejs 14.9.0'] }
let(:ruby_version_to_f) { 3.0 }

it 'uses the default ruby version' do
expect(target_ruby.version).to eq default_version
end
end
end

context 'when .ruby-version is not present' do
['Gemfile.lock', 'gems.locked'].each do |file_name|
context "and #{file_name} exists" do
Expand Down