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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce ABC complexity #7450

Merged
merged 2 commits into from
Oct 23, 2019
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
11 changes: 7 additions & 4 deletions lib/rubocop/cli.rb
Expand Up @@ -83,18 +83,21 @@ def execute_runners(paths)

def maybe_run_line_length_cop(paths)
if !line_length_enabled?(@config_store.for(Dir.pwd))
puts Rainbow("#{PHASE_1} #{PHASE_1_DISABLED}").yellow
''
skip_line_length_cop(PHASE_1_DISABLED)
elsif !same_max_line_length?(
@config_store.for(Dir.pwd), ConfigLoader.default_configuration
)
puts Rainbow("#{PHASE_1} #{PHASE_1_OVERRIDDEN}").yellow
''
skip_line_length_cop(PHASE_1_OVERRIDDEN)
else
run_line_length_cop_auto_gen_config(paths)
end
end

def skip_line_length_cop(reason)
puts Rainbow("#{PHASE_1} #{reason}").yellow
''
end

def line_length_enabled?(config)
line_length_cop(config)['Enabled']
end
Expand Down
7 changes: 7 additions & 0 deletions lib/rubocop/config.rb
Expand Up @@ -53,6 +53,13 @@ def signature
@signature ||= Digest::SHA1.hexdigest(to_s)
end

# True if this is a config file that is shipped with RuboCop
def internal?
base_config_path = File.expand_path(File.join(ConfigLoader::RUBOCOP_HOME,
'config'))
File.expand_path(loaded_path).start_with?(base_config_path)
end

def make_excludes_absolute
each_key do |key|
@validator.validate_section_presence(key)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/config_loader.rb
Expand Up @@ -46,7 +46,7 @@ def load_file(file)

add_missing_namespaces(path, hash)

resolver.resolve_inheritance_from_gems(hash, hash.delete('inherit_gem'))
resolver.resolve_inheritance_from_gems(hash)
resolver.resolve_inheritance(path, hash, file, debug?)

hash.delete('inherit_from')
Expand Down
3 changes: 2 additions & 1 deletion lib/rubocop/config_loader_resolver.rb
Expand Up @@ -35,7 +35,8 @@ def resolve_inheritance(path, hash, file, debug)
end
end

def resolve_inheritance_from_gems(hash, gems)
def resolve_inheritance_from_gems(hash)
gems = hash.delete('inherit_gem')
(gems || {}).each_pair do |gem_name, config_path|
if gem_name == 'rubocop'
raise ArgumentError,
Expand Down
19 changes: 10 additions & 9 deletions lib/rubocop/config_validator.rb
Expand Up @@ -32,10 +32,7 @@ def initialize(config)

def validate
# Don't validate RuboCop's own files. Avoids infinite recursion.
base_config_path = File.expand_path(File.join(ConfigLoader::RUBOCOP_HOME,
'config'))
return if File.expand_path(@config.loaded_path)
.start_with?(base_config_path)
return if @config.internal?

valid_cop_names, invalid_cop_names = @config.keys.partition do |key|
ConfigLoader.default_configuration.key?(key)
Expand Down Expand Up @@ -133,12 +130,16 @@ def validate_parameter_names(valid_cop_names)
@config[name].each_key do |param|
next if COMMON_PARAMS.include?(param) || default_config.key?(param)

message =
"Warning: #{name} does not support #{param} parameter.\n\n" \
"Supported parameters are:\n\n" \
" - #{(default_config.keys - INTERNAL_PARAMS).join("\n - ")}\n"
supported_params = default_config.keys - INTERNAL_PARAMS
# FIXME: Remove .to_s, which works around a JRuby bug:
# https://github.com/jruby/jruby/issues/5935
warn Rainbow(<<~MESSAGE).yellow.to_s
Warning: #{name} does not support #{param} parameter.

warn Rainbow(message).yellow.to_s
Supported parameters are:

- #{supported_params.join("\n - ")}
MESSAGE
end
end
end
Expand Down
22 changes: 15 additions & 7 deletions lib/rubocop/cop/commissioner.rb
Expand Up @@ -64,17 +64,25 @@ def reset_errors
end

def remove_irrelevant_cops(filename)
@cops.reject! { |cop| cop.excluded_file?(filename) }
@cops.reject! do |cop|
cop.class.respond_to?(:support_target_ruby_version?) &&
!cop.class.support_target_ruby_version?(cop.target_ruby_version)
end
@cops.reject! do |cop|
cop.class.respond_to?(:support_target_rails_version?) &&
!cop.class.support_target_rails_version?(cop.target_rails_version)
cop.excluded_file?(filename) ||
!support_target_ruby_version?(cop) ||
!support_target_rails_version?(cop)
end
end

def support_target_ruby_version?(cop)
return true unless cop.class.respond_to?(:support_target_ruby_version?)

cop.class.support_target_ruby_version?(cop.target_ruby_version)
end

def support_target_rails_version?(cop)
return true unless cop.class.respond_to?(:support_target_rails_version?)

cop.class.support_target_rails_version?(cop.target_rails_version)
end

def reset_callbacks
@callbacks.clear
end
Expand Down
11 changes: 8 additions & 3 deletions lib/rubocop/cop/layout/end_of_line.rb
Expand Up @@ -45,9 +45,7 @@ class EndOfLine < Cop
MSG_MISSING = 'Carriage return character missing.'

def investigate(processed_source)
last_token = processed_source.tokens.last
last_line =
last_token ? last_token.line : processed_source.lines.length
last_line = last_line(processed_source)

processed_source.raw_source.each_line.with_index do |line, index|
break if index >= last_line
Expand Down Expand Up @@ -81,6 +79,13 @@ def offense_message(line)
else MSG_MISSING if line !~ /\r$/
end
end

private

def last_line(processed_source)
last_token = processed_source.tokens.last
last_token ? last_token.line : processed_source.lines.length
end
end
end
end
Expand Down
16 changes: 9 additions & 7 deletions lib/rubocop/cop/layout/indent_first_argument.rb
Expand Up @@ -228,19 +228,21 @@ def column_of(range)
# containing the previous line that's not a comment line or a blank
# line.
def previous_code_line(line_number)
@comment_lines ||=
processed_source
.comments
.select { |c| begins_its_line?(c.loc.expression) }
.map { |c| c.loc.line }

line = ''
while line.blank? || @comment_lines.include?(line_number)
while line.blank? || comment_lines.include?(line_number)
line_number -= 1
line = processed_source.lines[line_number - 1]
end
line
end

def comment_lines
@comment_lines ||=
processed_source
.comments
.select { |c| begins_its_line?(c.loc.expression) }
.map { |c| c.loc.line }
end
end
end
end
Expand Down
17 changes: 12 additions & 5 deletions lib/rubocop/cop/naming/file_name.rb
Expand Up @@ -50,21 +50,28 @@ def investigate(processed_source)
def for_bad_filename(file_path)
basename = File.basename(file_path)
msg = if filename_good?(basename)
return unless expect_matching_definition?
return if find_class_or_module(processed_source.ast,
to_namespace(file_path))
return if matching_definition?(file_path)

no_definition_message(basename, file_path)
else
return if ignore_executable_scripts? &&
processed_source.start_with?('#!')
return if bad_filename_allowed?

other_message(basename)
end

yield source_range(processed_source.buffer, 1, 0), msg
end

def matching_definition?(file_path)
return true unless expect_matching_definition?

find_class_or_module(processed_source.ast, to_namespace(file_path))
end

def bad_filename_allowed?
ignore_executable_scripts? && processed_source.start_with?('#!')
end

def no_definition_message(basename, file_path)
format(MSG_NO_DEFINITION,
basename: basename,
Expand Down
18 changes: 11 additions & 7 deletions lib/rubocop/cop/style/copyright.rb
Expand Up @@ -33,13 +33,7 @@ def investigate(processed_source)
end

def autocorrect(token)
raise Warning, AUTOCORRECT_EMPTY_WARNING if autocorrect_notice.empty?

regex = Regexp.new(notice)
unless autocorrect_notice =~ regex
raise Warning, "AutocorrectNotice '#{autocorrect_notice}' must " \
"match Notice /#{notice}/"
end
verify_autocorrect_notice!

lambda do |corrector|
range = token.nil? ? range_between(0, 0) : token.pos
Expand All @@ -57,6 +51,16 @@ def autocorrect_notice
cop_config['AutocorrectNotice']
end

def verify_autocorrect_notice!
raise Warning, AUTOCORRECT_EMPTY_WARNING if autocorrect_notice.empty?

regex = Regexp.new(notice)
return if autocorrect_notice =~ regex

raise Warning, "AutocorrectNotice '#{autocorrect_notice}' must " \
"match Notice /#{notice}/"
end

def insert_notice_before(processed_source)
token_index = 0
token_index += 1 if shebang_token?(processed_source, token_index)
Expand Down
9 changes: 5 additions & 4 deletions lib/rubocop/cop/style/format_string.rb
Expand Up @@ -106,14 +106,15 @@ def autocorrect_from_percent(corrector, node)
end

def autocorrect_to_percent(corrector, node)
format = node.first_argument.source
format_arg, *param_args = node.arguments
format = format_arg.source

args = if node.arguments.size == 2
arg = node.arguments.last
args = if param_args.one?
arg = param_args.last

arg.hash_type? ? "{ #{arg.source} }" : arg.source
else
"[#{node.arguments[1..-1].map(&:source).join(', ')}]"
"[#{param_args.map(&:source).join(', ')}]"
end

corrector.replace(node.loc.expression, "#{format} % #{args}")
Expand Down
7 changes: 4 additions & 3 deletions lib/rubocop/cop/style/inverse_methods.rb
Expand Up @@ -122,18 +122,19 @@ def correct_inverse_block(node)
end

def correct_inverse_selector(block, corrector)
selector = block.loc.selector.source
selector_loc = block.loc.selector
selector = selector_loc.source

if NEGATED_EQUALITY_METHODS.include?(selector.to_sym)
selector[0] = '='
corrector.replace(block.loc.selector, selector)
corrector.replace(selector_loc, selector)
else
if block.loc.dot
range = dot_range(block.loc)
corrector.remove(range)
end

corrector.remove(block.loc.selector)
corrector.remove(selector_loc)
end
end

Expand Down
6 changes: 6 additions & 0 deletions lib/rubocop/options.rb
Expand Up @@ -255,6 +255,12 @@ def initialize(options)
@options = options
end

def validate_cop_options
%i[only except].each do |opt|
OptionsValidator.validate_cop_list(@options[opt])
end
end

# rubocop:disable Metrics/AbcSize
def validate_compatibility # rubocop:disable Metrics/MethodLength
if only_includes_unneeded_disable?
Expand Down
23 changes: 12 additions & 11 deletions lib/rubocop/runner.rb
Expand Up @@ -104,18 +104,13 @@ def list_files(paths)
end

def process_file(file)
puts "Scanning #{file}" if @options[:debug]
file_started(file)

offenses = file_offenses(file)
if @options[:display_only_fail_level_offenses]
offenses = offenses.select { |o| considered_failure?(o) }
end
formatter_set.file_finished(file, offenses)
offenses
rescue InfiniteCorrectionLoop => e
formatter_set.file_finished(file, e.offenses.compact.sort.freeze)
offenses = e.offenses.compact.sort.freeze
raise
ensure
file_finished(file, offenses || [])
end

def file_offenses(file)
Expand Down Expand Up @@ -189,11 +184,19 @@ def autocorrect_unneeded_disables(file, source, cop, offenses)
end

def file_started(file)
puts "Scanning #{file}" if @options[:debug]
formatter_set.file_started(file,
cli_options: @options,
config_store: @config_store)
end

def file_finished(file, offenses)
if @options[:display_only_fail_level_offenses]
offenses = offenses.select { |o| considered_failure?(o) }
end
formatter_set.file_finished(file, offenses)
end

def cached_run?
@cached_run ||=
(@options[:cache] == 'true' ||
Expand Down Expand Up @@ -291,9 +294,7 @@ def mobilized_cop_classes(config)
@mobilized_cop_classes[config.object_id] ||= begin
cop_classes = Cop::Cop.all

%i[only except].each do |opt|
OptionsValidator.validate_cop_list(@options[opt])
end
OptionsValidator.new(@options).validate_cop_options

if @options[:only]
cop_classes.select! { |c| c.match?(@options[:only]) }
Expand Down
18 changes: 12 additions & 6 deletions lib/rubocop/target_finder.rb
Expand Up @@ -65,12 +65,7 @@ def target_files_in_dir(base_dir = Dir.pwd)
to_inspect?(file, hidden_files, base_dir_config)
end

if fail_fast?
# Most recently modified file first.
target_files.sort_by! { |path| -Integer(File.mtime(path)) }
else
target_files.sort!
end
target_files.sort_by!(&order)
end

def to_inspect?(file, hidden_files, base_dir_config)
Expand Down Expand Up @@ -186,5 +181,16 @@ def process_explicit_path(path)
config.file_to_exclude?(file)
end
end

private

def order
if fail_fast?
# Most recently modified file first.
->(path) { -Integer(File.mtime(path)) }
else
:itself
end
end
end
end