rubocop 1.91.0 → 1.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +3 -1
- data/lib/rubocop/cached_data.rb +47 -7
- data/lib/rubocop/changed_files.rb +35 -13
- data/lib/rubocop/cli/command/cop_names.rb +57 -0
- data/lib/rubocop/cli/command/execute_runner.rb +2 -2
- data/lib/rubocop/cli/command/explain.rb +34 -0
- data/lib/rubocop/cli/command/show_cops.rb +6 -0
- data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
- data/lib/rubocop/cli.rb +3 -2
- data/lib/rubocop/comment_config.rb +17 -8
- data/lib/rubocop/config_loader.rb +6 -3
- data/lib/rubocop/config_loader_resolver.rb +37 -12
- data/lib/rubocop/config_obsoletion/removed_cop.rb +1 -1
- data/lib/rubocop/config_validator.rb +11 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
- data/lib/rubocop/cop/base.rb +42 -21
- data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
- data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
- data/lib/rubocop/cop/cop_documentation.rb +81 -0
- data/lib/rubocop/cop/cop_explanation.rb +140 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +23 -2
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
- data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
- data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
- data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
- data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/class_structure.rb +9 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
- data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +16 -10
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -3
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +16 -12
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -0
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
- data/lib/rubocop/cop/layout/line_length.rb +52 -18
- data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +7 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +14 -0
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
- data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +6 -11
- data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
- data/lib/rubocop/cop/lint/literal_as_condition.rb +15 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
- data/lib/rubocop/cop/lint/loop.rb +24 -2
- data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +71 -11
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
- data/lib/rubocop/cop/lint/void.rb +8 -1
- data/lib/rubocop/cop/metrics/class_length.rb +4 -2
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
- data/lib/rubocop/cop/metrics/module_length.rb +4 -2
- data/lib/rubocop/cop/mixin/alignment.rb +4 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +17 -14
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -1
- data/lib/rubocop/cop/mixin/code_length.rb +10 -2
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
- data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
- data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +26 -2
- data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +17 -2
- data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
- data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +22 -2
- data/lib/rubocop/cop/mixin.rb +2 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
- data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
- data/lib/rubocop/cop/offense.rb +59 -3
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +16 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +7 -0
- data/lib/rubocop/cop/style/alias.rb +18 -5
- data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
- data/lib/rubocop/cop/style/and_or.rb +4 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +4 -1
- data/lib/rubocop/cop/style/attr.rb +3 -4
- data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
- data/lib/rubocop/cop/style/block_delimiters.rb +29 -3
- data/lib/rubocop/cop/style/case_like_if.rb +6 -3
- data/lib/rubocop/cop/style/class_and_module_children.rb +54 -16
- data/lib/rubocop/cop/style/class_methods_definitions.rb +8 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +85 -11
- data/lib/rubocop/cop/style/concat_array_literals.rb +46 -7
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +65 -9
- data/lib/rubocop/cop/style/double_negation.rb +11 -0
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +3 -1
- data/lib/rubocop/cop/style/endless_method.rb +67 -6
- data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
- data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
- data/lib/rubocop/cop/style/float_division.rb +22 -2
- data/lib/rubocop/cop/style/for.rb +40 -2
- data/lib/rubocop/cop/style/format_string.rb +28 -6
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +9 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
- data/lib/rubocop/cop/style/hash_lookup_method.rb +32 -9
- data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
- data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -20
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
- data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
- data/lib/rubocop/cop/style/it_block_parameter.rb +32 -3
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
- data/lib/rubocop/cop/style/lambda.rb +18 -0
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/map_into_array.rb +1 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +45 -10
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
- data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
- data/lib/rubocop/cop/style/missing_else.rb +7 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
- data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
- data/lib/rubocop/cop/style/mutable_constant.rb +28 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
- data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
- data/lib/rubocop/cop/style/nested_modifier.rb +27 -8
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
- data/lib/rubocop/cop/style/next.rb +24 -10
- data/lib/rubocop/cop/style/nil_comparison.rb +16 -4
- data/lib/rubocop/cop/style/non_nil_check.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +10 -5
- data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
- data/lib/rubocop/cop/style/one_line_conditional.rb +13 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
- data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +20 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +30 -13
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +9 -1
- data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +20 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
- data/lib/rubocop/cop/style/require_order.rb +9 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +5 -9
- data/lib/rubocop/cop/style/return_nil.rb +17 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
- data/lib/rubocop/cop/style/sample.rb +9 -8
- data/lib/rubocop/cop/style/self_assignment.rb +12 -15
- data/lib/rubocop/cop/style/semicolon.rb +16 -5
- data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
- data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
- data/lib/rubocop/cop/style/super_arguments.rb +3 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +23 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
- data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
- data/lib/rubocop/cop/team.rb +10 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable.rb +14 -1
- data/lib/rubocop/formatter/base_formatter.rb +22 -0
- data/lib/rubocop/formatter/formatter_set.rb +4 -0
- data/lib/rubocop/formatter/json_formatter.rb +71 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
- data/lib/rubocop/formatter/sarif_formatter.rb +12 -7
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
- data/lib/rubocop/lsp/runtime.rb +47 -11
- data/lib/rubocop/lsp/stdin_runner.rb +11 -5
- data/lib/rubocop/lsp.rb +5 -2
- data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
- data/lib/rubocop/mcp/explain_tool.rb +68 -0
- data/lib/rubocop/mcp/scope.rb +65 -0
- data/lib/rubocop/mcp/server.rb +184 -76
- data/lib/rubocop/mcp/source_files.rb +35 -0
- data/lib/rubocop/offense_limit.rb +30 -0
- data/lib/rubocop/options.rb +45 -10
- data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
- data/lib/rubocop/remote_config.rb +4 -1
- data/lib/rubocop/result_cache.rb +20 -13
- data/lib/rubocop/runner.rb +109 -41
- data/lib/rubocop/server/cache.rb +2 -2
- data/lib/rubocop/util.rb +69 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +16 -5
data/lib/rubocop/cop/base.rb
CHANGED
|
@@ -216,14 +216,8 @@ module RuboCop
|
|
|
216
216
|
message = find_message(range_to_pass, message)
|
|
217
217
|
|
|
218
218
|
status, corrector = enabled_lines?(range) ? correct(range, &block) : :disabled
|
|
219
|
-
justification = suppression_reason(range) if status == :disabled
|
|
220
219
|
|
|
221
|
-
|
|
222
|
-
# template file, we convert it to location info in the original file.
|
|
223
|
-
range = range_for_original(range)
|
|
224
|
-
|
|
225
|
-
current_offenses << Offense.new(severity, range, message, name, status, corrector,
|
|
226
|
-
justification: justification)
|
|
220
|
+
current_offenses << new_offense(range, severity, message, status, corrector)
|
|
227
221
|
end
|
|
228
222
|
|
|
229
223
|
# This method should be overridden when a cop's behavior depends
|
|
@@ -271,10 +265,21 @@ module RuboCop
|
|
|
271
265
|
@config.target_ruby_version
|
|
272
266
|
end
|
|
273
267
|
|
|
274
|
-
# Returns a
|
|
275
|
-
#
|
|
268
|
+
# Returns the version of a gem in the target, by default its locked version
|
|
269
|
+
# (i.e. from Gemfile.lock or gems.locked).
|
|
270
|
+
#
|
|
271
|
+
# The requirements declared with `requires_gem` are checked against the version
|
|
272
|
+
# this method returns, so an extension that lets users state the version of its
|
|
273
|
+
# gem in `AllCops` (e.g. `TargetFrameworkVersion`) can override it for that gem,
|
|
274
|
+
# returning a `Gem::Version`, and fall back to `super` for any other gem.
|
|
275
|
+
#
|
|
276
|
+
# @param [String] gem_name
|
|
277
|
+
# @return [Gem::Version, nil] The gem version, or nil if the gem is not present.
|
|
278
|
+
#
|
|
279
|
+
# @api public
|
|
276
280
|
def target_gem_version(gem_name)
|
|
277
|
-
|
|
281
|
+
gem_versions = @config.gem_versions_in_target
|
|
282
|
+
gem_versions && gem_versions[gem_name]
|
|
278
283
|
end
|
|
279
284
|
|
|
280
285
|
def parser_engine
|
|
@@ -382,6 +387,12 @@ module RuboCop
|
|
|
382
387
|
cop_config.fetch('AutoCorrect', 'always') == 'contextual'
|
|
383
388
|
end
|
|
384
389
|
|
|
390
|
+
# @api private
|
|
391
|
+
def disabled_autocorrect?
|
|
392
|
+
# `false` is the same as `'disabled'` for backward compatibility.
|
|
393
|
+
['disabled', false].include?(cop_config['AutoCorrect'])
|
|
394
|
+
end
|
|
395
|
+
|
|
385
396
|
def inspect # :nodoc:
|
|
386
397
|
"#<#{self.class.name}:#{object_id} @config=#{@config} @options=#{@options}>"
|
|
387
398
|
end
|
|
@@ -394,6 +405,22 @@ module RuboCop
|
|
|
394
405
|
@restrict_on_send ||= self::RESTRICT_ON_SEND.to_a.freeze
|
|
395
406
|
end
|
|
396
407
|
|
|
408
|
+
# @return [Offense]
|
|
409
|
+
def new_offense(range, severity, message, status, corrector)
|
|
410
|
+
justification = suppression_reason(range) if status == :disabled
|
|
411
|
+
|
|
412
|
+
# Since this range may be generated from Ruby code embedded in some
|
|
413
|
+
# template file, we convert it to location info in the original file.
|
|
414
|
+
# A cop configured with `AutoCorrect: false` reports no edits, since
|
|
415
|
+
# nothing that honors the configuration applies them. The corrector
|
|
416
|
+
# stays, so an editor can still offer it as a quick fix to choose.
|
|
417
|
+
corrections = [] if corrector && disabled_autocorrect?
|
|
418
|
+
|
|
419
|
+
Offense.new(severity, range_for_original(range), message, name, status, corrector,
|
|
420
|
+
justification: justification, correction_safe: safe_autocorrect?,
|
|
421
|
+
corrections: corrections)
|
|
422
|
+
end
|
|
423
|
+
|
|
397
424
|
### Reserved for Cop::Cop
|
|
398
425
|
|
|
399
426
|
def callback_argument(range)
|
|
@@ -465,7 +492,8 @@ module RuboCop
|
|
|
465
492
|
# The unsafe correction will not run, so the offense is
|
|
466
493
|
# uncorrectable for this run and gets a todo comment.
|
|
467
494
|
attempt_correction(range, nil)
|
|
468
|
-
elsif corrector && (always_autocorrect? ||
|
|
495
|
+
elsif corrector && (always_autocorrect? ||
|
|
496
|
+
(contextual_autocorrect? && !contextual_autocorrect_held_back?))
|
|
469
497
|
:uncorrected
|
|
470
498
|
else
|
|
471
499
|
:unsupported
|
|
@@ -601,17 +629,10 @@ module RuboCop
|
|
|
601
629
|
end
|
|
602
630
|
|
|
603
631
|
def target_satisfies_all_gem_version_requirements?
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
gem_requirements.all? do |gem_name, version_req|
|
|
608
|
-
all_gem_versions_in_target = @config.gem_versions_in_target
|
|
609
|
-
next false unless all_gem_versions_in_target
|
|
610
|
-
|
|
611
|
-
gem_version_in_target = all_gem_versions_in_target[gem_name]
|
|
612
|
-
next false unless gem_version_in_target
|
|
632
|
+
self.class.gem_requirements.all? do |gem_name, version_requirement|
|
|
633
|
+
gem_version = target_gem_version(gem_name)
|
|
613
634
|
|
|
614
|
-
|
|
635
|
+
gem_version && version_requirement.satisfied_by?(gem_version)
|
|
615
636
|
end
|
|
616
637
|
end
|
|
617
638
|
end
|
|
@@ -51,14 +51,6 @@ module RuboCop
|
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
private
|
|
55
|
-
|
|
56
|
-
def previous_declaration(node)
|
|
57
|
-
declarations = gem_declarations(processed_source.ast)
|
|
58
|
-
node_index = declarations.map(&:location).find_index(node.location)
|
|
59
|
-
declarations.to_a[node_index - 1]
|
|
60
|
-
end
|
|
61
|
-
|
|
62
54
|
# @!method gem_declarations(node)
|
|
63
55
|
def_node_search :gem_declarations, <<~PATTERN
|
|
64
56
|
(:send nil? :gem str ...)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
# Reads the documentation comment a cop carries above its class definition
|
|
6
|
+
# and splits it into the sections worth showing on their own.
|
|
7
|
+
#
|
|
8
|
+
# YARD is a development dependency, so the comment is read straight from the
|
|
9
|
+
# source rather than through a doclet.
|
|
10
|
+
# @api private
|
|
11
|
+
class CopDocumentation
|
|
12
|
+
TAG = /^@(\w+)\s*(.*)$/.freeze
|
|
13
|
+
|
|
14
|
+
def initialize(cop_class)
|
|
15
|
+
@cop_class = cop_class
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @return [Array<Array(String, Array<String>)>] title and body per section
|
|
19
|
+
def sections
|
|
20
|
+
comment = comment_lines
|
|
21
|
+
return [] if comment.empty?
|
|
22
|
+
|
|
23
|
+
prose, tagged = split_on_first_tag(comment)
|
|
24
|
+
|
|
25
|
+
[['Details', strip_blank(prose)], *tagged_sections(tagged)].reject { |_, b| b.empty? }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def comment_lines
|
|
31
|
+
path, line = source_location
|
|
32
|
+
return [] unless path && File.file?(path)
|
|
33
|
+
|
|
34
|
+
lines = File.readlines(path, chomp: true)
|
|
35
|
+
collect_comment_above(lines, line - 2)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def source_location
|
|
39
|
+
name = @cop_class.name
|
|
40
|
+
return [] unless name
|
|
41
|
+
|
|
42
|
+
Module.const_source_location(name) || []
|
|
43
|
+
rescue NameError
|
|
44
|
+
[]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Walks up from the class definition for as long as the lines are comments.
|
|
48
|
+
def collect_comment_above(lines, index)
|
|
49
|
+
block = []
|
|
50
|
+
while index >= 0 && lines[index].match?(/^\s*#/)
|
|
51
|
+
block.unshift(lines[index].sub(/^\s*# ?/, ''))
|
|
52
|
+
index -= 1
|
|
53
|
+
end
|
|
54
|
+
block
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def split_on_first_tag(comment)
|
|
58
|
+
first_tag = comment.index { |line| line.match?(TAG) }
|
|
59
|
+
return [comment, []] unless first_tag
|
|
60
|
+
|
|
61
|
+
[comment[0...first_tag], comment[first_tag..]]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def tagged_sections(lines)
|
|
65
|
+
lines.slice_before { |line| line.match?(TAG) }.map do |(head, *body)|
|
|
66
|
+
tag, argument = head.match(TAG).captures
|
|
67
|
+
[section_title(tag, argument), strip_blank(body)]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def section_title(tag, argument)
|
|
72
|
+
title = tag.capitalize
|
|
73
|
+
argument.empty? ? title : "#{title}: #{argument}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def strip_blank(lines)
|
|
77
|
+
lines.drop_while(&:empty?).reverse.drop_while(&:empty?).reverse
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
# Explains what a single cop does: its description, how it is configured,
|
|
6
|
+
# whether it corrects, and the examples from its own documentation.
|
|
7
|
+
#
|
|
8
|
+
# Rendered as plain text, which is what `--explain` prints and what the MCP
|
|
9
|
+
# server hands to an agent.
|
|
10
|
+
# @api private
|
|
11
|
+
class CopExplanation
|
|
12
|
+
# Keys that describe the cop to RuboCop itself rather than something a
|
|
13
|
+
# user would set, so they are reported in their own section or not at all.
|
|
14
|
+
METADATA_KEYS = %w[
|
|
15
|
+
Description StyleGuide Reference References Enabled Safe SafeAutoCorrect
|
|
16
|
+
AutoCorrect VersionAdded VersionChanged Include Exclude Details Preview
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
def initialize(cop_class, config)
|
|
20
|
+
@cop_class = cop_class
|
|
21
|
+
@config = config
|
|
22
|
+
@cop_config = config.for_cop(cop_class.cop_name)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def to_s
|
|
26
|
+
lines.join("\n")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def lines
|
|
32
|
+
description = description_lines
|
|
33
|
+
|
|
34
|
+
[
|
|
35
|
+
@cop_class.cop_name,
|
|
36
|
+
*section(nil, description),
|
|
37
|
+
*section('Properties', property_lines),
|
|
38
|
+
*documentation_sections(description).flat_map { |title, body| section(title, body) },
|
|
39
|
+
*section('Configuration', configuration_lines),
|
|
40
|
+
*section('References', reference_lines)
|
|
41
|
+
]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def section(title, body)
|
|
45
|
+
return [] if body.empty?
|
|
46
|
+
|
|
47
|
+
heading = title ? [title, ''] : []
|
|
48
|
+
['', *heading, *body.map { |line| line.empty? ? '' : " #{line}" }]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def description_lines
|
|
52
|
+
Array(@cop_config['Description']).flat_map { |line| line.split("\n") }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def property_lines
|
|
56
|
+
[
|
|
57
|
+
"Enabled: #{@cop_config.fetch('Enabled', true)}",
|
|
58
|
+
"Safe: #{@cop_config.fetch('Safe', true)}",
|
|
59
|
+
"Autocorrect: #{autocorrect_description}",
|
|
60
|
+
*version_lines,
|
|
61
|
+
*scope_lines
|
|
62
|
+
]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Which files the cop looks at. A cop that only runs on Gemfiles
|
|
66
|
+
# explains an absent offense better than anything else here does.
|
|
67
|
+
def scope_lines
|
|
68
|
+
[
|
|
69
|
+
*patterns_line('Applies to: ', @cop_config['Include']),
|
|
70
|
+
*patterns_line('Excludes: ', @cop_config['Exclude'])
|
|
71
|
+
]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def patterns_line(label, patterns)
|
|
75
|
+
patterns = Array(patterns).compact
|
|
76
|
+
return [] if patterns.empty?
|
|
77
|
+
|
|
78
|
+
["#{label}#{patterns.map { |pattern| readable_pattern(pattern) }.join(', ')}"]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# `Exclude` patterns are absolutized against the config that set them,
|
|
82
|
+
# which makes for a wall of identical prefixes. A user config can also
|
|
83
|
+
# hold a regexp rather than a glob.
|
|
84
|
+
def readable_pattern(pattern)
|
|
85
|
+
pattern.is_a?(String) ? PathUtil.smart_path(pattern) : pattern.inspect
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def autocorrect_description
|
|
89
|
+
return 'not supported' unless @cop_class.support_autocorrect?
|
|
90
|
+
|
|
91
|
+
# Asks the cop, so `AutoCorrect` is read the way the cop reads it.
|
|
92
|
+
cop = @cop_class.new(@config)
|
|
93
|
+
return 'disabled' unless cop.always_autocorrect? || cop.contextual_autocorrect?
|
|
94
|
+
|
|
95
|
+
description = cop.safe_autocorrect? ? 'safe, applied by -a' : 'unsafe, applied by -A only'
|
|
96
|
+
# Contextual corrections wait until the code is finished, which an
|
|
97
|
+
# editor or an agent mid-edit cannot promise, so they have to ask.
|
|
98
|
+
description += ', but through LSP or MCP only on request' if cop.contextual_autocorrect?
|
|
99
|
+
description
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def version_lines
|
|
103
|
+
lines = []
|
|
104
|
+
lines << "Added: #{@cop_config['VersionAdded']}" if @cop_config['VersionAdded']
|
|
105
|
+
lines << "Changed: #{@cop_config['VersionChanged']}" if @cop_config['VersionChanged']
|
|
106
|
+
lines
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def configuration_lines
|
|
110
|
+
(@cop_config.keys - METADATA_KEYS).sort.map do |key|
|
|
111
|
+
"#{key}: #{format_value(@cop_config[key])}"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def format_value(value)
|
|
116
|
+
value.is_a?(Array) ? value.join(', ') : value.to_s
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def reference_lines
|
|
120
|
+
annotator = MessageAnnotator.new(@config, @cop_class.cop_name, @cop_config, {})
|
|
121
|
+
|
|
122
|
+
[*annotator.urls, Documentation.url_for(@cop_class, @config)].compact
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# The comment above the class opens by restating the description, which
|
|
126
|
+
# is already printed above, so that opening is dropped.
|
|
127
|
+
def documentation_sections(description)
|
|
128
|
+
CopDocumentation.new(@cop_class).sections.filter_map do |title, body|
|
|
129
|
+
body -= description if title == 'Details'
|
|
130
|
+
body = strip_blank(body)
|
|
131
|
+
[title, body] unless body.empty?
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def strip_blank(lines)
|
|
136
|
+
lines.drop_while(&:empty?).reverse.drop_while(&:empty?).reverse
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -109,8 +109,20 @@ module RuboCop
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
def inside_string_ranges(node)
|
|
112
|
-
return
|
|
112
|
+
return source_string_ranges unless node.is_a?(Parser::AST::Node)
|
|
113
113
|
|
|
114
|
+
string_ranges(node)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def source_string_ranges
|
|
118
|
+
return [] unless processed_source.ast
|
|
119
|
+
return @source_string_ranges if @source_string_ranges_source.equal?(processed_source)
|
|
120
|
+
|
|
121
|
+
@source_string_ranges_source = processed_source
|
|
122
|
+
@source_string_ranges = string_ranges(processed_source.ast)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def string_ranges(node)
|
|
114
126
|
node.each_node(:any_str).filter_map { |n| inside_string_range(n) }
|
|
115
127
|
end
|
|
116
128
|
|
|
@@ -17,6 +17,7 @@ module RuboCop
|
|
|
17
17
|
|
|
18
18
|
def call(corrector)
|
|
19
19
|
corrector.replace(offending_range, correction)
|
|
20
|
+
corrector.replace(block_node.loc.end, closing_keyword) if block_node.braces?
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
private
|
|
@@ -24,13 +25,27 @@ module RuboCop
|
|
|
24
25
|
attr_reader :block_node, :collection_node, :argument_node
|
|
25
26
|
|
|
26
27
|
def correction
|
|
27
|
-
if block_node.arguments?
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
keyword = if block_node.arguments?
|
|
29
|
+
format(
|
|
30
|
+
CORRECTION_WITH_ARGUMENTS,
|
|
31
|
+
collection: collection_node.source,
|
|
32
|
+
variables: argument_node.children.map(&:source).join(', ')
|
|
33
|
+
)
|
|
34
|
+
else
|
|
35
|
+
format(CORRECTION_WITHOUT_ARGUMENTS, enumerable: collection_node.source)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
padding_needed?(offending_range.end_pos) ? "#{keyword} " : keyword
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def closing_keyword
|
|
42
|
+
padding_needed?(block_node.loc.end.begin_pos - 1) ? ' end' : 'end'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def padding_needed?(position)
|
|
46
|
+
character = block_node.source_range.source_buffer.source[position]
|
|
47
|
+
|
|
48
|
+
!character.nil? && !character.match?(/\s/)
|
|
34
49
|
end
|
|
35
50
|
|
|
36
51
|
def offending_range
|
|
@@ -29,6 +29,10 @@ module RuboCop
|
|
|
29
29
|
insert_arguments(corrector)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
def replace_delimiters?
|
|
33
|
+
!block_node.braces? && arg_to_unparenthesized_call?
|
|
34
|
+
end
|
|
35
|
+
|
|
32
36
|
private
|
|
33
37
|
|
|
34
38
|
attr_reader :block_node, :method, :arguments
|
|
@@ -77,7 +81,7 @@ module RuboCop
|
|
|
77
81
|
end
|
|
78
82
|
|
|
79
83
|
def replace_delimiters(corrector)
|
|
80
|
-
return
|
|
84
|
+
return unless replace_delimiters?
|
|
81
85
|
|
|
82
86
|
corrector.insert_after(block_begin, ' ') unless separating_space?
|
|
83
87
|
|
|
@@ -90,7 +94,7 @@ module RuboCop
|
|
|
90
94
|
# `;`; joining everything with `,` would turn them into extra parameters
|
|
91
95
|
# and change the lambda's arity.
|
|
92
96
|
regular, shadow = arguments.children.partition { |arg| !arg.shadowarg_type? }
|
|
93
|
-
arg_string = regular.map(
|
|
97
|
+
arg_string = regular.map { |arg| argument_source(arg) }.join(', ')
|
|
94
98
|
arg_string += "; #{shadow.map(&:source).join(', ')}" unless shadow.empty?
|
|
95
99
|
arg_string
|
|
96
100
|
end
|
|
@@ -140,6 +144,23 @@ module RuboCop
|
|
|
140
144
|
def separating_space?
|
|
141
145
|
block_begin.source_buffer.source[block_begin.begin_pos + 2].match?(/\s/)
|
|
142
146
|
end
|
|
147
|
+
|
|
148
|
+
def argument_source(argument)
|
|
149
|
+
return argument.source unless argument.type?(:optarg, :kwoptarg)
|
|
150
|
+
return argument.source unless operator_expression?(argument.default_value)
|
|
151
|
+
|
|
152
|
+
default_value = argument.default_value
|
|
153
|
+
name = argument.source_range.begin.join(default_value.source_range.begin).source
|
|
154
|
+
|
|
155
|
+
"#{name}(#{default_value.source})"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def operator_expression?(node)
|
|
159
|
+
return true if node.type?(:range, :if, :and, :or)
|
|
160
|
+
return false unless node.call_type?
|
|
161
|
+
|
|
162
|
+
node.operator_method? && !node.method?(:[])
|
|
163
|
+
end
|
|
143
164
|
end
|
|
144
165
|
end
|
|
145
166
|
end
|
|
@@ -21,14 +21,55 @@ module RuboCop
|
|
|
21
21
|
corrector.insert_after(node.loc.end, ' ')
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def heredoc_strands_code_after_close_paren?(node)
|
|
25
|
+
return false unless heredoc_body_before_close_paren?(node)
|
|
26
|
+
|
|
27
|
+
after_paren = text_after_close_paren(node)
|
|
28
|
+
|
|
29
|
+
!after_paren.empty? && !after_paren.start_with?('.', '&.', ',')
|
|
30
|
+
end
|
|
31
|
+
|
|
24
32
|
private
|
|
25
33
|
|
|
26
34
|
# When the line above `)` ends with a comment and a chained call follows `)`,
|
|
27
35
|
# crossing the newline would pull the chain into the comment. Preserve the newline.
|
|
36
|
+
# When a heredoc body comes before `)`, a chained call has to start on the line
|
|
37
|
+
# after the terminator instead, since the terminator must stay alone on its line.
|
|
28
38
|
def remove_close_paren(corrector, node, buffer)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
if heredoc_above_close_paren_swallows_chain?(node)
|
|
40
|
+
range = range_with_surrounding_space(range: node.loc.end, buffer: buffer, side: :left)
|
|
41
|
+
|
|
42
|
+
corrector.replace(range, "\n")
|
|
43
|
+
else
|
|
44
|
+
newlines = !comment_above_close_paren_swallows_chain?(node, buffer)
|
|
45
|
+
range = range_with_surrounding_space(
|
|
46
|
+
range: node.loc.end, buffer: buffer, side: :left, newlines: newlines
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
corrector.remove(range)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def heredoc_above_close_paren_swallows_chain?(node)
|
|
54
|
+
return false unless heredoc_body_before_close_paren?(node)
|
|
55
|
+
|
|
56
|
+
text_after_close_paren(node).start_with?('.', '&.')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def heredoc_body_before_close_paren?(node)
|
|
60
|
+
return false unless (last_child = node.children.last)
|
|
61
|
+
|
|
62
|
+
close_paren_pos = node.loc.end.begin_pos
|
|
63
|
+
|
|
64
|
+
last_child.each_node(:any_str).any? do |str_node|
|
|
65
|
+
str_node.heredoc? && str_node.loc.heredoc_end.end_pos <= close_paren_pos
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def text_after_close_paren(node)
|
|
70
|
+
close_paren = node.loc.end
|
|
71
|
+
|
|
72
|
+
close_paren.source_line[(close_paren.column + 1)..].to_s.lstrip
|
|
32
73
|
end
|
|
33
74
|
|
|
34
75
|
def comment_above_close_paren_swallows_chain?(node, buffer)
|
|
@@ -46,12 +87,8 @@ module RuboCop
|
|
|
46
87
|
end
|
|
47
88
|
|
|
48
89
|
def chained_after_close_paren?(node)
|
|
49
|
-
|
|
50
|
-
line_text = close_paren.source_line
|
|
51
|
-
after_paren = line_text[(close_paren.column + 1)..]
|
|
52
|
-
return false if after_paren.nil?
|
|
90
|
+
trimmed = text_after_close_paren(node)
|
|
53
91
|
|
|
54
|
-
trimmed = after_paren.lstrip
|
|
55
92
|
!trimmed.empty? && !trimmed.start_with?('#')
|
|
56
93
|
end
|
|
57
94
|
|
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
|
14
14
|
# @api private
|
|
15
15
|
def url_for(cop_class, config = nil)
|
|
16
16
|
base = department_to_basename(cop_class.department)
|
|
17
|
-
fragment = cop_class.cop_name.downcase.
|
|
17
|
+
fragment = cop_class.cop_name.downcase.delete('/')
|
|
18
18
|
base_url = base_url_for(cop_class, config)
|
|
19
19
|
extension = extension_for(cop_class, config)
|
|
20
20
|
|
|
@@ -109,12 +109,6 @@ module RuboCop
|
|
|
109
109
|
end
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
def match_block_variable_name?(receiver_name)
|
|
113
|
-
gem_specification(processed_source.ast) do |block_variable_name|
|
|
114
|
-
return block_variable_name == receiver_name
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
112
|
def add_dependency_method?(method_name)
|
|
119
113
|
ADD_DEPENDENCY_METHODS.include?(method_name)
|
|
120
114
|
end
|
|
@@ -80,12 +80,6 @@ module RuboCop
|
|
|
80
80
|
|
|
81
81
|
private
|
|
82
82
|
|
|
83
|
-
def previous_declaration(node)
|
|
84
|
-
declarations = dependency_declarations(processed_source.ast)
|
|
85
|
-
node_index = declarations.find_index(node)
|
|
86
|
-
declarations.to_a[node_index - 1]
|
|
87
|
-
end
|
|
88
|
-
|
|
89
83
|
def get_dependency_name(node)
|
|
90
84
|
node.method_name
|
|
91
85
|
end
|
|
@@ -201,11 +201,8 @@ module RuboCop
|
|
|
201
201
|
def add_newline?(node)
|
|
202
202
|
# Determine if a blank line should be inserted before the new directive
|
|
203
203
|
# in order to spread out pattern matchers
|
|
204
|
-
|
|
205
|
-
return false unless
|
|
206
|
-
|
|
207
|
-
prev_sibling = node.parent.child_nodes[node.sibling_index - 1]
|
|
208
|
-
return false unless prev_sibling && pattern_matcher?(prev_sibling)
|
|
204
|
+
prev_sibling = node.left_sibling
|
|
205
|
+
return false unless prev_sibling.is_a?(AST::Node) && pattern_matcher?(prev_sibling)
|
|
209
206
|
|
|
210
207
|
node.loc.line == last_line(prev_sibling) + 1
|
|
211
208
|
end
|
|
@@ -46,13 +46,6 @@ module RuboCop
|
|
|
46
46
|
|
|
47
47
|
private
|
|
48
48
|
|
|
49
|
-
def arguments_range(node)
|
|
50
|
-
range_between(
|
|
51
|
-
node.first_argument.source_range.begin_pos,
|
|
52
|
-
node.last_argument.source_range.end_pos
|
|
53
|
-
)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
49
|
def group_satisfied?(group_types, symbol_args)
|
|
57
50
|
group_types.all? { |type| symbol_args.any? { |arg| arg.value == type } }
|
|
58
51
|
end
|
|
@@ -31,15 +31,9 @@ module RuboCop
|
|
|
31
31
|
dup_arguments = arguments.dup
|
|
32
32
|
dup_arguments.delete(config_node)
|
|
33
33
|
|
|
34
|
-
corrector.replace(
|
|
34
|
+
corrector.replace(arguments_range(node), dup_arguments.map(&:source).join(', '))
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
def offense_range(arguments)
|
|
41
|
-
range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
|
|
42
|
-
end
|
|
43
37
|
end
|
|
44
38
|
end
|
|
45
39
|
end
|
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
def on_if(node)
|
|
112
|
-
|
|
112
|
+
node.condition.each_node(:send) do |cond|
|
|
113
113
|
add_offense(cond, message: MSG_FOR_CONDITIONAL_USE) if style_detected_api_used?(cond)
|
|
114
114
|
end
|
|
115
115
|
end
|
|
@@ -134,12 +134,6 @@ module RuboCop
|
|
|
134
134
|
no_acceptable_style_check(node) ||
|
|
135
135
|
style_detected_check(node)
|
|
136
136
|
end
|
|
137
|
-
|
|
138
|
-
def traverse_condition(condition, &block)
|
|
139
|
-
yield condition if condition.send_type?
|
|
140
|
-
|
|
141
|
-
condition.each_child_node { |child| traverse_condition(child, &block) }
|
|
142
|
-
end
|
|
143
137
|
end
|
|
144
138
|
end
|
|
145
139
|
end
|