rubocop 1.18.1 → 1.22.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (249) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +116 -23
  4. data/lib/rubocop/cli.rb +18 -0
  5. data/lib/rubocop/config.rb +5 -0
  6. data/lib/rubocop/config_loader.rb +5 -3
  7. data/lib/rubocop/config_loader_resolver.rb +22 -7
  8. data/lib/rubocop/config_validator.rb +27 -6
  9. data/lib/rubocop/cop/base.rb +3 -3
  10. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  11. data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
  12. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
  13. data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
  14. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
  15. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  16. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
  17. data/lib/rubocop/cop/correctors/require_library_corrector.rb +23 -0
  18. data/lib/rubocop/cop/documentation.rb +1 -1
  19. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
  20. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
  21. data/lib/rubocop/cop/generator.rb +14 -8
  22. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +34 -0
  23. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
  24. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  25. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +71 -0
  26. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  27. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  28. data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
  29. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  30. data/lib/rubocop/cop/layout/class_structure.rb +7 -2
  31. data/lib/rubocop/cop/layout/dot_position.rb +34 -5
  32. data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
  33. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -0
  34. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
  35. data/lib/rubocop/cop/layout/end_alignment.rb +9 -2
  36. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  37. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  38. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  39. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  40. data/lib/rubocop/cop/layout/hash_alignment.rb +22 -18
  41. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  42. data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -7
  43. data/lib/rubocop/cop/layout/indentation_style.rb +2 -2
  44. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  45. data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
  46. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +36 -17
  47. data/lib/rubocop/cop/layout/line_length.rb +9 -7
  48. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  49. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
  50. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
  51. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  52. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
  53. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +23 -10
  54. data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
  55. data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
  56. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
  57. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  58. data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
  59. data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
  60. data/lib/rubocop/cop/layout/space_before_comment.rb +2 -2
  61. data/lib/rubocop/cop/layout/space_inside_parens.rb +78 -32
  62. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
  63. data/lib/rubocop/cop/layout/trailing_whitespace.rb +24 -1
  64. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
  65. data/lib/rubocop/cop/lint/ambiguous_range.rb +105 -0
  66. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -2
  67. data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
  68. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
  69. data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
  70. data/lib/rubocop/cop/lint/debugger.rb +2 -4
  71. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
  72. data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
  73. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
  74. data/lib/rubocop/cop/lint/duplicate_branch.rb +2 -1
  75. data/lib/rubocop/cop/lint/duplicate_methods.rb +8 -5
  76. data/lib/rubocop/cop/lint/else_layout.rb +10 -6
  77. data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
  78. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  79. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  80. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
  81. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
  82. data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
  83. data/lib/rubocop/cop/lint/loop.rb +4 -3
  84. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
  85. data/lib/rubocop/cop/lint/number_conversion.rb +12 -1
  86. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
  87. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
  88. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
  89. data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
  90. data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
  91. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
  92. data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
  93. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -1
  94. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  95. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  96. data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
  97. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
  98. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
  99. data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
  100. data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
  101. data/lib/rubocop/cop/lint/useless_times.rb +5 -4
  102. data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
  103. data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
  104. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  105. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  106. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  107. data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
  108. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  109. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  110. data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
  111. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
  112. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
  113. data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -4
  114. data/lib/rubocop/cop/mixin/heredoc.rb +5 -0
  115. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
  116. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
  117. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  118. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
  119. data/lib/rubocop/cop/mixin/percent_array.rb +18 -7
  120. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
  121. data/lib/rubocop/cop/mixin/require_library.rb +59 -0
  122. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  123. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -2
  124. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
  125. data/lib/rubocop/cop/mixin/string_literals_help.rb +5 -1
  126. data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
  127. data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
  128. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  129. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  130. data/lib/rubocop/cop/naming/inclusive_language.rb +27 -10
  131. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
  132. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
  133. data/lib/rubocop/cop/security/io_methods.rb +49 -0
  134. data/lib/rubocop/cop/security/json_load.rb +8 -7
  135. data/lib/rubocop/cop/security/open.rb +4 -0
  136. data/lib/rubocop/cop/security/yaml_load.rb +4 -0
  137. data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
  138. data/lib/rubocop/cop/style/and_or.rb +5 -0
  139. data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
  140. data/lib/rubocop/cop/style/array_coercion.rb +21 -3
  141. data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
  142. data/lib/rubocop/cop/style/block_delimiters.rb +50 -2
  143. data/lib/rubocop/cop/style/case_equality.rb +6 -9
  144. data/lib/rubocop/cop/style/case_like_if.rb +5 -0
  145. data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
  146. data/lib/rubocop/cop/style/collection_compact.rb +7 -5
  147. data/lib/rubocop/cop/style/collection_methods.rb +8 -6
  148. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  149. data/lib/rubocop/cop/style/comment_annotation.rb +55 -25
  150. data/lib/rubocop/cop/style/commented_keyword.rb +9 -3
  151. data/lib/rubocop/cop/style/conditional_assignment.rb +19 -5
  152. data/lib/rubocop/cop/style/date_time.rb +5 -0
  153. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  154. data/lib/rubocop/cop/style/documentation.rb +23 -8
  155. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
  156. data/lib/rubocop/cop/style/double_negation.rb +27 -6
  157. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  158. data/lib/rubocop/cop/style/encoding.rb +26 -15
  159. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  160. data/lib/rubocop/cop/style/explicit_block_argument.rb +46 -11
  161. data/lib/rubocop/cop/style/float_division.rb +10 -2
  162. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +14 -3
  163. data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
  164. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
  165. data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
  166. data/lib/rubocop/cop/style/hash_except.rb +4 -3
  167. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  168. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -9
  169. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
  170. data/lib/rubocop/cop/style/identical_conditional_branches.rb +32 -5
  171. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
  172. data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
  173. data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
  174. data/lib/rubocop/cop/style/lambda_call.rb +1 -1
  175. data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
  176. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
  177. data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -1
  178. data/lib/rubocop/cop/style/missing_else.rb +7 -0
  179. data/lib/rubocop/cop/style/module_function.rb +8 -9
  180. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  181. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
  182. data/lib/rubocop/cop/style/mutable_constant.rb +79 -14
  183. data/lib/rubocop/cop/style/negated_if.rb +1 -1
  184. data/lib/rubocop/cop/style/negated_unless.rb +1 -1
  185. data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
  186. data/lib/rubocop/cop/style/not.rb +2 -2
  187. data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
  188. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
  189. data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
  190. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  191. data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
  192. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
  193. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  194. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  195. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
  196. data/lib/rubocop/cop/style/quoted_symbols.rb +10 -6
  197. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  198. data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
  199. data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
  200. data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
  201. data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
  202. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
  203. data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
  204. data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
  205. data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
  206. data/lib/rubocop/cop/style/redundant_self.rb +10 -0
  207. data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
  208. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +83 -0
  209. data/lib/rubocop/cop/style/redundant_sort.rb +53 -20
  210. data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
  211. data/lib/rubocop/cop/style/return_nil.rb +2 -1
  212. data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
  213. data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
  214. data/lib/rubocop/cop/style/semicolon.rb +32 -24
  215. data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
  216. data/lib/rubocop/cop/style/single_line_block_params.rb +3 -1
  217. data/lib/rubocop/cop/style/single_line_methods.rb +25 -15
  218. data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
  219. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
  220. data/lib/rubocop/cop/style/special_global_vars.rb +25 -0
  221. data/lib/rubocop/cop/style/static_class.rb +5 -5
  222. data/lib/rubocop/cop/style/string_chars.rb +4 -2
  223. data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
  224. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
  225. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
  226. data/lib/rubocop/cop/style/swap_values.rb +4 -2
  227. data/lib/rubocop/cop/style/symbol_array.rb +3 -3
  228. data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
  229. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
  230. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  231. data/lib/rubocop/cop/style/word_array.rb +23 -5
  232. data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
  233. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
  234. data/lib/rubocop/cop/util.rb +22 -6
  235. data/lib/rubocop/cops_documentation_generator.rb +17 -5
  236. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
  237. data/lib/rubocop/magic_comment.rb +44 -15
  238. data/lib/rubocop/options.rb +127 -113
  239. data/lib/rubocop/rake_task.rb +1 -1
  240. data/lib/rubocop/result_cache.rb +3 -3
  241. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  242. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  243. data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
  244. data/lib/rubocop/rspec/support.rb +1 -0
  245. data/lib/rubocop/runner.rb +2 -3
  246. data/lib/rubocop/target_finder.rb +1 -1
  247. data/lib/rubocop/version.rb +1 -1
  248. data/lib/rubocop.rb +14 -2
  249. metadata +21 -5
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Looks for references to a cop configuration key that isn't defined in config/default.yml.
7
+ class UndefinedConfig < Base
8
+ ALLOWED_CONFIGURATIONS = %w[
9
+ Safe SafeAutoCorrect AutoCorrect Severity StyleGuide Details Reference Include Exclude
10
+ ].freeze
11
+ RESTRICT_ON_SEND = %i[[] fetch].freeze
12
+ MSG = '`%<name>s` is not defined in the configuration for `%<cop>s` ' \
13
+ 'in `config/default.yml`.'
14
+
15
+ # @!method cop_class_def(node)
16
+ def_node_search :cop_class_def, <<~PATTERN
17
+ (class _ (const _ {:Base :Cop}) ...)
18
+ PATTERN
19
+
20
+ # @!method cop_config_accessor?(node)
21
+ def_node_matcher :cop_config_accessor?, <<~PATTERN
22
+ (send (send nil? :cop_config) {:[] :fetch} ${str sym}...)
23
+ PATTERN
24
+
25
+ def on_new_investigation
26
+ super
27
+ return unless processed_source.ast
28
+
29
+ cop_class = cop_class_def(processed_source.ast).first
30
+ return unless (@cop_class_name = extract_cop_name(cop_class))
31
+
32
+ @config_for_cop = RuboCop::ConfigLoader.default_configuration.for_cop(@cop_class_name)
33
+ end
34
+
35
+ def on_send(node)
36
+ return unless cop_class_name
37
+ return unless (config_name_node = cop_config_accessor?(node))
38
+ return if always_allowed?(config_name_node)
39
+ return if configuration_key_defined?(config_name_node)
40
+
41
+ message = format(MSG, name: config_name_node.value, cop: cop_class_name)
42
+ add_offense(config_name_node, message: message)
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :config_for_cop, :cop_class_name
48
+
49
+ def extract_cop_name(class_node)
50
+ return unless class_node
51
+
52
+ segments = [class_node].concat(
53
+ class_node.each_ancestor(:class, :module).take_while do |n|
54
+ n.identifier.short_name != :Cop
55
+ end
56
+ )
57
+
58
+ segments.reverse_each.map { |s| s.identifier.short_name }.join('/')
59
+ end
60
+
61
+ def always_allowed?(node)
62
+ ALLOWED_CONFIGURATIONS.include?(node.value)
63
+ end
64
+
65
+ def configuration_key_defined?(node)
66
+ config_for_cop.key?(node.value)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require_relative 'internal_affairs/empty_line_between_expect_offense_and_correction'
4
4
  require_relative 'internal_affairs/example_description'
5
+ require_relative 'internal_affairs/inherit_deprecated_cop_class'
6
+ require_relative 'internal_affairs/location_line_equality_comparison'
5
7
  require_relative 'internal_affairs/method_name_equal'
6
8
  require_relative 'internal_affairs/node_destructuring'
7
9
  require_relative 'internal_affairs/node_matcher_directive'
@@ -12,4 +14,5 @@ require_relative 'internal_affairs/redundant_let_rubocop_config_new'
12
14
  require_relative 'internal_affairs/redundant_location_argument'
13
15
  require_relative 'internal_affairs/redundant_message_argument'
14
16
  require_relative 'internal_affairs/style_detected_api_use'
17
+ require_relative 'internal_affairs/undefined_config'
15
18
  require_relative 'internal_affairs/useless_message_assertion'
@@ -54,7 +54,7 @@ module RuboCop
54
54
 
55
55
  def on_send(node)
56
56
  first_arg = node.first_argument
57
- return if !multiple_arguments?(node, first_arg) || node.send_type? && node.method?(:[]=)
57
+ return if !multiple_arguments?(node, first_arg) || (node.send_type? && node.method?(:[]=))
58
58
 
59
59
  if first_arg.hash_type? && !first_arg.braces?
60
60
  pairs = first_arg.pairs
@@ -33,7 +33,7 @@ module RuboCop
33
33
  def check_assignment(node, rhs)
34
34
  return unless rhs
35
35
  return unless node.loc.operator
36
- return if node.loc.operator.line == rhs.first_line
36
+ return if same_line?(node.loc.operator, rhs)
37
37
 
38
38
  base = display_column(leftmost_multiple_assignment(node).source_range)
39
39
  check_alignment([rhs], base + configured_indentation_width)
@@ -101,11 +101,11 @@ module RuboCop
101
101
  def block_end_align_target(node)
102
102
  lineage = [node, *node.ancestors]
103
103
 
104
- target = lineage.each_cons(2) do |current, parent|
105
- break current if end_align_target?(current, parent)
104
+ lineage.each_cons(2) do |current, parent|
105
+ return current if end_align_target?(current, parent)
106
106
  end
107
107
 
108
- target || lineage.last
108
+ lineage.last
109
109
  end
110
110
 
111
111
  def end_align_target?(node, parent)
@@ -264,7 +264,8 @@ module RuboCop
264
264
 
265
265
  def source_range_with_comment(node)
266
266
  begin_pos, end_pos =
267
- if node.def_type? && !node.method?(:initialize) || node.send_type? && node.def_modifier?
267
+ if (node.def_type? && !node.method?(:initialize)) ||
268
+ (node.send_type? && node.def_modifier?)
268
269
  start_node = find_visibility_start(node) || node
269
270
  end_node = find_visibility_end(node) || node
270
271
  [begin_pos_with_comment(start_node),
@@ -289,12 +290,16 @@ module RuboCop
289
290
  (node.first_line - 1).downto(1) do |annotation_line|
290
291
  break unless (comment = processed_source.comment_at_line(annotation_line))
291
292
 
292
- first_comment = comment
293
+ first_comment = comment if whole_line_comment_at_line?(annotation_line)
293
294
  end
294
295
 
295
296
  start_line_position(first_comment || node)
296
297
  end
297
298
 
299
+ def whole_line_comment_at_line?(line)
300
+ /\A\s*#/.match?(processed_source.lines[line - 1])
301
+ end
302
+
298
303
  def start_line_position(node)
299
304
  buffer.line_range(node.loc.line).begin_pos - 1
300
305
  end
@@ -68,19 +68,22 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def proper_dot_position?(node)
71
- receiver_line = node.receiver.source_range.end.line
72
- selector_line = selector_range(node).line
71
+ selector_range = selector_range(node)
73
72
 
74
- # receiver and selector are on the same line
75
- return true if selector_line == receiver_line
73
+ return true if same_line?(selector_range, end_range(node.receiver))
76
74
 
75
+ selector_line = selector_range.line
76
+ receiver_line = receiver_end_line(node.receiver)
77
77
  dot_line = node.loc.dot.line
78
78
 
79
79
  # don't register an offense if there is a line comment between the
80
80
  # dot and the selector otherwise, we might break the code while
81
81
  # "correcting" it (even if there is just an extra blank line, treat
82
82
  # it the same)
83
- return true if line_between?(selector_line, dot_line)
83
+ # Also, in the case of a heredoc, the receiver will end after the dot,
84
+ # because the heredoc body is on subsequent lines, so use the highest
85
+ # line to compare to.
86
+ return true if line_between?(selector_line, [receiver_line, dot_line].max)
84
87
 
85
88
  correct_dot_position_style?(dot_line, selector_line)
86
89
  end
@@ -96,7 +99,33 @@ module RuboCop
96
99
  end
97
100
  end
98
101
 
102
+ def receiver_end_line(node)
103
+ if (line = last_heredoc_line(node))
104
+ line
105
+ else
106
+ node.source_range.end.line
107
+ end
108
+ end
109
+
110
+ def last_heredoc_line(node)
111
+ if node.send_type?
112
+ node.arguments.select { |arg| heredoc?(arg) }.map { |arg| arg.loc.heredoc_end.line }.max
113
+ elsif heredoc?(node)
114
+ node.loc.heredoc_end.line
115
+ end
116
+ end
117
+
118
+ def heredoc?(node)
119
+ (node.str_type? || node.dstr_type?) && node.heredoc?
120
+ end
121
+
122
+ def end_range(node)
123
+ node.source_range.end
124
+ end
125
+
99
126
  def selector_range(node)
127
+ return node unless node.call_type?
128
+
100
129
  # l.(1) has no selector, so we use the opening parenthesis instead
101
130
  node.loc.selector || node.loc.begin
102
131
  end
@@ -96,7 +96,7 @@ module RuboCop
96
96
 
97
97
  def autocorrect(corrector, node)
98
98
  previous_token = previous_token(node)
99
- range = if previous_token && node.loc.line == previous_token.line
99
+ range = if previous_token && same_line?(node, previous_token)
100
100
  range_with_surrounding_space(range: node.loc.expression, newlines: false)
101
101
  else
102
102
  range_by_whole_lines(node.loc.expression, include_final_newline: true)
@@ -38,12 +38,14 @@ module RuboCop
38
38
  class EmptyLineAfterGuardClause < Base
39
39
  include RangeHelp
40
40
  extend AutoCorrector
41
+ extend Util
41
42
 
42
43
  MSG = 'Add empty line after guard clause.'
43
44
  END_OF_HEREDOC_LINE = 1
44
45
 
45
46
  def on_if(node)
46
47
  return if correct_style?(node)
48
+ return if multiple_statements_on_line?(node)
47
49
 
48
50
  if node.modifier_form? && (heredoc_node = last_heredoc_argument(node))
49
51
  return if next_line_empty_or_enable_directive_comment?(heredoc_line(node, heredoc_node))
@@ -166,6 +168,13 @@ module RuboCop
166
168
  node
167
169
  end
168
170
  end
171
+
172
+ def multiple_statements_on_line?(node)
173
+ parent = node.parent
174
+ return false unless parent
175
+
176
+ parent.begin_type? && parent.single_line?
177
+ end
169
178
  end
170
179
  end
171
180
  end
@@ -65,21 +65,24 @@ module RuboCop
65
65
  MSG = 'Extra empty line detected %<location>s the `%<keyword>s`.'
66
66
 
67
67
  def on_def(node)
68
- check_body(node.body)
68
+ check_body(node.body, node.loc.line)
69
69
  end
70
70
  alias on_defs on_def
71
71
 
72
72
  def on_kwbegin(node)
73
73
  body, = *node
74
- check_body(body)
74
+ check_body(body, node.loc.line)
75
75
  end
76
76
 
77
77
  private
78
78
 
79
- def check_body(node)
80
- locations = keyword_locations(node)
79
+ def check_body(body, line_of_def_or_kwbegin)
80
+ locations = keyword_locations(body)
81
+
81
82
  locations.each do |loc|
82
83
  line = loc.line
84
+ next if line == line_of_def_or_kwbegin
85
+
83
86
  keyword = loc.source
84
87
  # below the keyword
85
88
  check_line(style, line, message('after', keyword), &:empty?)
@@ -165,9 +165,10 @@ module RuboCop
165
165
  end
166
166
 
167
167
  def alignment_node_for_variable_style(node)
168
- return node.parent if node.case_type? && node.argument?
168
+ return node.parent if node.case_type? && node.argument? && same_line?(node, node.parent)
169
+
170
+ assignment = assignment_or_operator_method(node)
169
171
 
170
- assignment = node.ancestors.find(&:assignment_or_similar?)
171
172
  if assignment && !line_break_before_keyword?(assignment.source_range, node)
172
173
  assignment
173
174
  else
@@ -177,6 +178,12 @@ module RuboCop
177
178
  node
178
179
  end
179
180
  end
181
+
182
+ def assignment_or_operator_method(node)
183
+ node.ancestors.find do |ancestor|
184
+ ancestor.assignment_or_similar? || (ancestor.send_type? && ancestor.operator_method?)
185
+ end
186
+ end
180
187
  end
181
188
  end
182
189
  end
@@ -154,7 +154,7 @@ module RuboCop
154
154
 
155
155
  def on_send(node)
156
156
  return if style != :consistent && enforce_first_argument_with_fixed_indentation?
157
- return if !node.arguments? || bare_operator?(node)
157
+ return if !node.arguments? || bare_operator?(node) || node.setter_method?
158
158
 
159
159
  indent = base_indentation(node) + configured_indentation_width
160
160
 
@@ -115,7 +115,7 @@ module RuboCop
115
115
  left_bracket = array_node.loc.begin
116
116
  first_elem = array_node.values.first
117
117
  if first_elem
118
- return if first_elem.source_range.line == left_bracket.line
118
+ return if same_line?(first_elem, left_bracket)
119
119
 
120
120
  check_first(first_elem, left_bracket, left_parenthesis, 0)
121
121
  end
@@ -116,7 +116,7 @@ module RuboCop
116
116
  first_pair = hash_node.pairs.first
117
117
 
118
118
  if first_pair
119
- return if first_pair.first_line == left_brace.line
119
+ return if same_line?(first_pair, left_brace)
120
120
 
121
121
  if separator_style?(first_pair)
122
122
  check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
@@ -74,7 +74,7 @@ module RuboCop
74
74
  left_parenthesis = def_node.arguments.loc.begin
75
75
  first_elem = def_node.arguments.first
76
76
  return unless first_elem
77
- return if first_elem.source_range.line == left_parenthesis.line
77
+ return if same_line?(first_elem, left_parenthesis)
78
78
 
79
79
  check_first(first_elem, left_parenthesis, nil, 0)
80
80
  end
@@ -213,18 +213,22 @@ module RuboCop
213
213
  check_pairs(node)
214
214
  end
215
215
 
216
- attr_accessor :offences_by, :column_deltas
216
+ attr_accessor :offenses_by, :column_deltas
217
217
 
218
218
  private
219
219
 
220
220
  def autocorrect_incompatible_with_other_cops?(node)
221
- enforce_first_argument_with_fixed_indentation? &&
222
- node.pairs.any? &&
223
- node.parent&.call_type? && node.parent.loc.selector.line == node.pairs.first.loc.line
221
+ return false unless enforce_first_argument_with_fixed_indentation? &&
222
+ node.pairs.any? &&
223
+ node.parent&.call_type?
224
+
225
+ parent_loc = node.parent.loc
226
+ selector = parent_loc.selector || parent_loc.expression
227
+ same_line?(selector, node.pairs.first)
224
228
  end
225
229
 
226
230
  def reset!
227
- self.offences_by = {}
231
+ self.offenses_by = {}
228
232
  self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
229
233
  end
230
234
 
@@ -248,33 +252,33 @@ module RuboCop
248
252
  end
249
253
  end
250
254
 
251
- add_offences
255
+ add_offenses
252
256
  end
253
257
 
254
- def add_offences
255
- kwsplat_offences = offences_by.delete(KeywordSplatAlignment)
256
- register_offences_with_format(kwsplat_offences, KeywordSplatAlignment)
258
+ def add_offenses
259
+ kwsplat_offenses = offenses_by.delete(KeywordSplatAlignment)
260
+ register_offenses_with_format(kwsplat_offenses, KeywordSplatAlignment)
257
261
 
258
- format, offences = offences_by.min_by { |_, v| v.length }
259
- register_offences_with_format(offences, format)
262
+ format, offenses = offenses_by.min_by { |_, v| v.length }
263
+ register_offenses_with_format(offenses, format)
260
264
  end
261
265
 
262
- def register_offences_with_format(offences, format)
263
- (offences || []).each do |offence|
264
- add_offense(offence, message: MESSAGES[format]) do |corrector|
265
- delta = column_deltas[alignment_for(offence).first.class][offence]
266
+ def register_offenses_with_format(offenses, format)
267
+ (offenses || []).each do |offense|
268
+ add_offense(offense, message: MESSAGES[format]) do |corrector|
269
+ delta = column_deltas[alignment_for(offense).first.class][offense]
266
270
 
267
- correct_node(corrector, offence, delta) unless delta.nil?
271
+ correct_node(corrector, offense, delta) unless delta.nil?
268
272
  end
269
273
  end
270
274
  end
271
275
 
272
276
  def check_delta(delta, node:, alignment:)
273
- offences_by[alignment.class] ||= []
277
+ offenses_by[alignment.class] ||= []
274
278
  return if good_alignment? delta
275
279
 
276
280
  column_deltas[alignment.class][node] = delta
277
- offences_by[alignment.class].push(node)
281
+ offenses_by[alignment.class].push(node)
278
282
  end
279
283
 
280
284
  def ignore_hash_argument?(node)
@@ -167,7 +167,7 @@ module RuboCop
167
167
 
168
168
  end_of_outer_send = outermost_send.loc.end
169
169
 
170
- end_of_outer_send.line == end_of_last_arg_of_outer_send.line &&
170
+ same_line?(end_of_outer_send, end_of_last_arg_of_outer_send) &&
171
171
  end_of_outer_send.column == end_of_last_arg_of_outer_send.column + 1
172
172
  end
173
173
 
@@ -143,13 +143,6 @@ module RuboCop
143
143
  indent_level(base_line)
144
144
  end
145
145
 
146
- def indent_level(str)
147
- indentations = str.lines
148
- .map { |line| line[/^\s*/] }
149
- .reject { |line| line.end_with?("\n") }
150
- indentations.empty? ? 0 : indentations.min_by(&:size).size
151
- end
152
-
153
146
  # Returns '~', '-' or nil
154
147
  def heredoc_indent_type(node)
155
148
  node.source[/^<<([~-])/, 1]
@@ -43,7 +43,7 @@ module RuboCop
43
43
  str_ranges = string_literal_ranges(processed_source.ast)
44
44
 
45
45
  processed_source.lines.each.with_index(1) do |line, lineno|
46
- next unless (range = find_offence(line, lineno))
46
+ next unless (range = find_offense(line, lineno))
47
47
  next if in_string_literal?(str_ranges, range)
48
48
 
49
49
  add_offense(range) { |corrector| autocorrect(corrector, range) }
@@ -60,7 +60,7 @@ module RuboCop
60
60
  end
61
61
  end
62
62
 
63
- def find_offence(line, lineno)
63
+ def find_offense(line, lineno)
64
64
  match = if style == :spaces
65
65
  line.match(/\A\s*\t+/)
66
66
  else
@@ -341,7 +341,7 @@ module RuboCop
341
341
  return true unless body_node
342
342
 
343
343
  # Don't check if expression is on same line as "then" keyword, etc.
344
- return true if body_node.loc.line == base_loc.line
344
+ return true if same_line?(body_node, base_loc)
345
345
 
346
346
  return true if starts_with_access_modifier?(body_node)
347
347
 
@@ -57,7 +57,7 @@ module RuboCop
57
57
 
58
58
  def on_new_investigation
59
59
  processed_source.comments.each do |comment|
60
- next unless /\A#+[^#\s=:+-]/.match?(comment.text)
60
+ next unless /\A#+[^#\s=+-]/.match?(comment.text)
61
61
  next if comment.loc.line == 1 && allowed_on_first_line?(comment)
62
62
  next if doxygen_comment_style?(comment)
63
63
  next if gemfile_ruby_comment?(comment)
@@ -77,7 +77,7 @@ module RuboCop
77
77
  end
78
78
 
79
79
  def allowed_on_first_line?(comment)
80
- shebang?(comment) || rackup_config_file? && rackup_options?(comment)
80
+ shebang?(comment) || (rackup_config_file? && rackup_options?(comment))
81
81
  end
82
82
 
83
83
  def shebang?(comment)
@@ -11,8 +11,7 @@ module RuboCop
11
11
  # concatenated string parts shall be indented regardless of `EnforcedStyle` configuration.
12
12
  #
13
13
  # If `EnforcedStyle: indented` is set, it's the second line that shall be indented one step
14
- # more than the first line. Lines 3 and forward shall be aligned with line 2. Here too there
15
- # are exceptions. Values in a hash literal are always aligned.
14
+ # more than the first line. Lines 3 and forward shall be aligned with line 2.
16
15
  #
17
16
  # @example
18
17
  # # bad
@@ -34,29 +33,44 @@ module RuboCop
34
33
  # 'z'
35
34
  # end
36
35
  #
37
- # my_hash = {
38
- # first: 'a message' \
39
- # 'in two parts'
40
- # }
41
- #
42
36
  # @example EnforcedStyle: aligned (default)
43
37
  # # bad
44
38
  # puts 'x' \
45
39
  # 'y'
46
40
  #
41
+ # my_hash = {
42
+ # first: 'a message' \
43
+ # 'in two parts'
44
+ # }
45
+ #
47
46
  # # good
48
47
  # puts 'x' \
49
48
  # 'y'
50
49
  #
50
+ # my_hash = {
51
+ # first: 'a message' \
52
+ # 'in two parts'
53
+ # }
54
+ #
51
55
  # @example EnforcedStyle: indented
52
56
  # # bad
53
57
  # result = 'x' \
54
58
  # 'y'
55
59
  #
60
+ # my_hash = {
61
+ # first: 'a message' \
62
+ # 'in two parts'
63
+ # }
64
+ #
56
65
  # # good
57
66
  # result = 'x' \
58
67
  # 'y'
59
68
  #
69
+ # my_hash = {
70
+ # first: 'a message' \
71
+ # 'in two parts'
72
+ # }
73
+ #
60
74
  class LineEndStringConcatenationIndentation < Base
61
75
  include ConfigurableEnforcedStyle
62
76
  include Alignment
@@ -70,7 +84,7 @@ module RuboCop
70
84
  return unless strings_concatenated_with_backslash?(node)
71
85
 
72
86
  children = node.children
73
- if style == :aligned && !always_indented?(node) || always_aligned?(node)
87
+ if style == :aligned && !always_indented?(node)
74
88
  check_aligned(children, 1)
75
89
  else
76
90
  check_indented(children)
@@ -85,19 +99,15 @@ module RuboCop
85
99
  private
86
100
 
87
101
  def strings_concatenated_with_backslash?(dstr_node)
88
- !dstr_node.heredoc? &&
89
- dstr_node.children.length > 1 &&
90
- dstr_node.children.all? { |c| c.str_type? || c.dstr_type? }
102
+ dstr_node.multiline? &&
103
+ dstr_node.children.all? { |c| c.str_type? || c.dstr_type? } &&
104
+ dstr_node.children.none?(&:multiline?)
91
105
  end
92
106
 
93
107
  def always_indented?(dstr_node)
94
108
  PARENT_TYPES_FOR_INDENTED.include?(dstr_node.parent&.type)
95
109
  end
96
110
 
97
- def always_aligned?(dstr_node)
98
- dstr_node.parent&.pair_type?
99
- end
100
-
101
111
  def check_aligned(children, start_index)
102
112
  base_column = children[start_index - 1].loc.column
103
113
  children[start_index..-1].each do |child|
@@ -108,11 +118,20 @@ module RuboCop
108
118
  end
109
119
 
110
120
  def check_indented(children)
111
- base_column = children[0].source_range.source_line =~ /\S/
112
- @column_delta = base_column + configured_indentation_width - children[1].loc.column
121
+ @column_delta = base_column(children[0]) + configured_indentation_width -
122
+ children[1].loc.column
113
123
  add_offense_and_correction(children[1], MSG_INDENT) if @column_delta != 0
114
124
  end
115
125
 
126
+ def base_column(child)
127
+ grandparent = child.parent.parent
128
+ if grandparent&.type == :pair
129
+ grandparent.loc.column
130
+ else
131
+ child.source_range.source_line =~ /\S/
132
+ end
133
+ end
134
+
116
135
  def add_offense_and_correction(node, message)
117
136
  add_offense(node, message: message) { |corrector| autocorrect(corrector, node) }
118
137
  end
@@ -137,7 +137,7 @@ module RuboCop
137
137
  range = semicolon_token.pos
138
138
  end_pos = range.end_pos
139
139
  next_range = range_between(end_pos, end_pos + 1)
140
- return nil unless next_range.line == range.line
140
+ return nil unless same_line?(next_range, range)
141
141
 
142
142
  next_char = next_range.source
143
143
  return nil if /[\r\n]/.match?(next_char)
@@ -176,15 +176,15 @@ module RuboCop
176
176
  def ignored_line?(line, line_index)
177
177
  matches_ignored_pattern?(line) ||
178
178
  shebang?(line, line_index) ||
179
- heredocs && line_in_permitted_heredoc?(line_index.succ)
179
+ (heredocs && line_in_permitted_heredoc?(line_index.succ))
180
180
  end
181
181
 
182
182
  def shebang?(line, line_index)
183
183
  line_index.zero? && line.start_with?('#!')
184
184
  end
185
185
 
186
- def register_offense(loc, line, line_index)
187
- message = format(MSG, length: line_length(line), max: max)
186
+ def register_offense(loc, line, line_index, length: line_length(line))
187
+ message = format(MSG, length: length, max: max)
188
188
 
189
189
  self.breakable_range = breakable_range_by_line_index[line_index]
190
190
 
@@ -241,9 +241,10 @@ module RuboCop
241
241
  end
242
242
 
243
243
  def check_directive_line(line, line_index)
244
- return if line_length_without_directive(line) <= max
244
+ length_without_directive = line_length_without_directive(line)
245
+ return if length_without_directive <= max
245
246
 
246
- range = max..(line_length_without_directive(line) - 1)
247
+ range = max..(length_without_directive - 1)
247
248
  register_offense(
248
249
  source_range(
249
250
  processed_source.buffer,
@@ -251,7 +252,8 @@ module RuboCop
251
252
  range
252
253
  ),
253
254
  line,
254
- line_index
255
+ line_index,
256
+ length: length_without_directive
255
257
  )
256
258
  end
257
259