rubocop 0.58.2 → 0.59.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.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +22 -7
  4. data/config/disabled.yml +33 -4
  5. data/config/enabled.yml +4 -11
  6. data/lib/rubocop.rb +5 -0
  7. data/lib/rubocop/ast/builder.rb +1 -0
  8. data/lib/rubocop/ast/node.rb +11 -33
  9. data/lib/rubocop/ast/node/block_node.rb +8 -1
  10. data/lib/rubocop/ast/node/defined_node.rb +13 -0
  11. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +16 -5
  12. data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +21 -0
  13. data/lib/rubocop/ast/node/send_node.rb +3 -12
  14. data/lib/rubocop/ast/traversal.rb +10 -0
  15. data/lib/rubocop/cli.rb +4 -1
  16. data/lib/rubocop/config.rb +21 -5
  17. data/lib/rubocop/config_loader.rb +2 -0
  18. data/lib/rubocop/config_loader_resolver.rb +3 -1
  19. data/lib/rubocop/cop/autocorrect_logic.rb +1 -0
  20. data/lib/rubocop/cop/bundler/gem_comment.rb +64 -0
  21. data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -0
  22. data/lib/rubocop/cop/commissioner.rb +2 -0
  23. data/lib/rubocop/cop/cop.rb +3 -0
  24. data/lib/rubocop/cop/corrector.rb +2 -0
  25. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -0
  26. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
  27. data/lib/rubocop/cop/correctors/space_corrector.rb +2 -0
  28. data/lib/rubocop/cop/force.rb +1 -0
  29. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -0
  30. data/lib/rubocop/cop/generator.rb +1 -0
  31. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -0
  32. data/lib/rubocop/cop/layout/class_structure.rb +4 -0
  33. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +5 -4
  34. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +35 -0
  35. data/lib/rubocop/cop/layout/else_alignment.rb +1 -0
  36. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -0
  37. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +1 -0
  38. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +5 -2
  39. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -0
  40. data/lib/rubocop/cop/layout/end_of_line.rb +1 -0
  41. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -0
  42. data/lib/rubocop/cop/layout/indent_array.rb +1 -0
  43. data/lib/rubocop/cop/layout/indent_heredoc.rb +3 -0
  44. data/lib/rubocop/cop/layout/indentation_width.rb +2 -0
  45. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -0
  46. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -1
  47. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +34 -11
  48. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -0
  49. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  50. data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -1
  51. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -0
  52. data/lib/rubocop/cop/layout/space_before_comment.rb +1 -0
  53. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +16 -8
  54. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +2 -0
  55. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  56. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +2 -0
  57. data/lib/rubocop/cop/layout/tab.rb +1 -0
  58. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -0
  59. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -0
  60. data/lib/rubocop/cop/lint/duplicate_methods.rb +9 -1
  61. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -0
  62. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -0
  63. data/lib/rubocop/cop/lint/interpolation_check.rb +2 -0
  64. data/lib/rubocop/cop/lint/literal_as_condition.rb +3 -6
  65. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -0
  66. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -0
  67. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -0
  68. data/lib/rubocop/cop/lint/rescue_type.rb +1 -0
  69. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +2 -2
  70. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -0
  71. data/lib/rubocop/cop/lint/script_permission.rb +1 -0
  72. data/lib/rubocop/cop/lint/shadowed_argument.rb +3 -0
  73. data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -0
  74. data/lib/rubocop/cop/lint/unneeded_cop_disable_directive.rb +1 -0
  75. data/lib/rubocop/cop/lint/unneeded_cop_enable_directive.rb +1 -0
  76. data/lib/rubocop/cop/lint/unneeded_require_statement.rb +1 -0
  77. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +1 -1
  78. data/lib/rubocop/cop/lint/unreachable_code.rb +2 -0
  79. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -0
  80. data/lib/rubocop/cop/lint/useless_setter_call.rb +3 -0
  81. data/lib/rubocop/cop/lint/void.rb +1 -0
  82. data/lib/rubocop/cop/message_annotator.rb +1 -0
  83. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  84. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -0
  85. data/lib/rubocop/cop/metrics/line_length.rb +6 -1
  86. data/lib/rubocop/cop/metrics/method_length.rb +1 -0
  87. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -0
  88. data/lib/rubocop/cop/mixin/classish_length.rb +1 -0
  89. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -0
  90. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
  91. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -6
  92. data/lib/rubocop/cop/mixin/empty_parameter.rb +1 -0
  93. data/lib/rubocop/cop/mixin/ignored_methods.rb +19 -0
  94. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +25 -1
  95. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +5 -3
  96. data/lib/rubocop/cop/mixin/percent_literal.rb +2 -0
  97. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +2 -0
  98. data/lib/rubocop/cop/mixin/safe_assignment.rb +2 -1
  99. data/lib/rubocop/cop/mixin/statement_modifier.rb +6 -1
  100. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -0
  101. data/lib/rubocop/cop/mixin/surrounding_space.rb +4 -0
  102. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -0
  103. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +2 -0
  104. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -0
  105. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -0
  106. data/lib/rubocop/cop/naming/file_name.rb +4 -1
  107. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -0
  108. data/lib/rubocop/cop/naming/predicate_name.rb +1 -0
  109. data/lib/rubocop/cop/naming/uncommunicative_block_param_name.rb +1 -0
  110. data/lib/rubocop/cop/naming/uncommunicative_method_param_name.rb +1 -0
  111. data/lib/rubocop/cop/naming/variable_name.rb +1 -0
  112. data/lib/rubocop/cop/performance/case_when_splat.rb +11 -7
  113. data/lib/rubocop/cop/performance/casecmp.rb +33 -42
  114. data/lib/rubocop/cop/performance/chain_array_allocation.rb +77 -0
  115. data/lib/rubocop/cop/performance/compare_with_block.rb +3 -0
  116. data/lib/rubocop/cop/performance/regexp_match.rb +1 -0
  117. data/lib/rubocop/cop/performance/sample.rb +2 -0
  118. data/lib/rubocop/cop/performance/size.rb +8 -2
  119. data/lib/rubocop/cop/performance/string_replacement.rb +1 -0
  120. data/lib/rubocop/cop/rails/active_support_aliases.rb +1 -0
  121. data/lib/rubocop/cop/rails/bulk_change_table.rb +9 -2
  122. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +1 -0
  123. data/lib/rubocop/cop/rails/delegate.rb +7 -2
  124. data/lib/rubocop/cop/rails/dynamic_find_by.rb +1 -0
  125. data/lib/rubocop/cop/rails/find_each.rb +7 -2
  126. data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
  127. data/lib/rubocop/cop/rails/http_status.rb +2 -0
  128. data/lib/rubocop/cop/rails/inverse_of.rb +4 -0
  129. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +1 -0
  130. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -0
  131. data/lib/rubocop/cop/rails/reversible_migration.rb +1 -0
  132. data/lib/rubocop/cop/rails/save_bang.rb +189 -38
  133. data/lib/rubocop/cop/rails/time_zone.rb +1 -0
  134. data/lib/rubocop/cop/security/eval.rb +1 -0
  135. data/lib/rubocop/cop/security/json_load.rb +2 -2
  136. data/lib/rubocop/cop/security/open.rb +6 -3
  137. data/lib/rubocop/cop/severity.rb +1 -0
  138. data/lib/rubocop/cop/style/and_or.rb +3 -3
  139. data/lib/rubocop/cop/style/ascii_comments.rb +1 -0
  140. data/lib/rubocop/cop/style/block_delimiters.rb +2 -4
  141. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +2 -3
  142. data/lib/rubocop/cop/style/class_and_module_children.rb +3 -0
  143. data/lib/rubocop/cop/style/class_vars.rb +1 -1
  144. data/lib/rubocop/cop/style/colon_method_definition.rb +1 -0
  145. data/lib/rubocop/cop/style/commented_keyword.rb +2 -0
  146. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -0
  147. data/lib/rubocop/cop/style/copyright.rb +7 -2
  148. data/lib/rubocop/cop/style/date_time.rb +40 -7
  149. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  150. data/lib/rubocop/cop/style/empty_case_condition.rb +8 -0
  151. data/lib/rubocop/cop/style/empty_else.rb +2 -0
  152. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -0
  153. data/lib/rubocop/cop/style/eval_with_location.rb +2 -0
  154. data/lib/rubocop/cop/style/for.rb +56 -10
  155. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  156. data/lib/rubocop/cop/style/if_with_semicolon.rb +1 -0
  157. data/lib/rubocop/cop/style/inverse_methods.rb +1 -0
  158. data/lib/rubocop/cop/style/lambda.rb +1 -0
  159. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +3 -5
  160. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +3 -5
  161. data/lib/rubocop/cop/style/method_def_parentheses.rb +2 -2
  162. data/lib/rubocop/cop/style/missing_else.rb +1 -0
  163. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -0
  164. data/lib/rubocop/cop/style/multiline_method_signature.rb +65 -0
  165. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -0
  166. data/lib/rubocop/cop/style/nil_comparison.rb +45 -5
  167. data/lib/rubocop/cop/style/not.rb +1 -1
  168. data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
  169. data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
  170. data/lib/rubocop/cop/style/or_assignment.rb +2 -0
  171. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  172. data/lib/rubocop/cop/style/random_with_offset.rb +1 -0
  173. data/lib/rubocop/cop/style/redundant_begin.rb +13 -0
  174. data/lib/rubocop/cop/style/redundant_conditional.rb +1 -0
  175. data/lib/rubocop/cop/style/redundant_parentheses.rb +6 -1
  176. data/lib/rubocop/cop/style/redundant_return.rb +1 -0
  177. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -0
  178. data/lib/rubocop/cop/style/rescue_standard_error.rb +1 -0
  179. data/lib/rubocop/cop/style/safe_navigation.rb +4 -0
  180. data/lib/rubocop/cop/style/semicolon.rb +4 -0
  181. data/lib/rubocop/cop/style/signal_exception.rb +1 -0
  182. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  183. data/lib/rubocop/cop/style/symbol_proc.rb +1 -8
  184. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +1 -0
  185. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
  186. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -0
  187. data/lib/rubocop/cop/style/unneeded_condition.rb +13 -2
  188. data/lib/rubocop/cop/style/unneeded_percent_q.rb +2 -0
  189. data/lib/rubocop/cop/style/word_array.rb +13 -1
  190. data/lib/rubocop/cop/team.rb +1 -0
  191. data/lib/rubocop/cop/variable_force.rb +5 -0
  192. data/lib/rubocop/cop/variable_force/assignment.rb +4 -0
  193. data/lib/rubocop/cop/variable_force/branch.rb +4 -0
  194. data/lib/rubocop/cop/variable_force/branchable.rb +2 -0
  195. data/lib/rubocop/cop/variable_force/scope.rb +6 -0
  196. data/lib/rubocop/cop/variable_force/variable_table.rb +1 -0
  197. data/lib/rubocop/file_finder.rb +2 -0
  198. data/lib/rubocop/formatter/disabled_config_formatter.rb +4 -4
  199. data/lib/rubocop/formatter/file_list_formatter.rb +1 -0
  200. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -0
  201. data/lib/rubocop/options.rb +16 -0
  202. data/lib/rubocop/path_util.rb +16 -1
  203. data/lib/rubocop/processed_source.rb +4 -0
  204. data/lib/rubocop/remote_config.rb +6 -1
  205. data/lib/rubocop/result_cache.rb +1 -0
  206. data/lib/rubocop/rspec/cop_helper.rb +3 -5
  207. data/lib/rubocop/rspec/shared_examples.rb +1 -9
  208. data/lib/rubocop/runner.rb +4 -0
  209. data/lib/rubocop/target_finder.rb +2 -0
  210. data/lib/rubocop/version.rb +1 -1
  211. metadata +7 -2
@@ -66,6 +66,7 @@ module RuboCop
66
66
  unless supported_styles.include?(s)
67
67
  raise "Unknown style #{s} selected!"
68
68
  end
69
+
69
70
  s
70
71
  end
71
72
  end
@@ -35,6 +35,7 @@ module RuboCop
35
35
  # the method has the same name as a class defined in the class/module.
36
36
  def class_emitter_method?(node, name)
37
37
  return false unless node.parent && node.defs_type?
38
+
38
39
  # a class emitter method may be defined inside `def self.included`,
39
40
  # `def self.extended`, etc.
40
41
  node = node.parent while node.parent.defs_type?
@@ -21,14 +21,11 @@ module RuboCop
21
21
  def_node_matcher :constant_definition?, '{class module}'
22
22
  def_node_matcher :empty_line_required?, '{def defs class module}'
23
23
 
24
- def check(node, body)
25
- # When style is `empty_lines`, if the body is empty, we don't enforce
26
- # the presence OR absence of an empty line
27
- # But if style is `no_empty_lines`, there must not be an empty line
28
- return unless body || style == :no_empty_lines
24
+ def check(node, body, adjusted_first_line: nil)
25
+ return if valid_body_style?(body)
29
26
  return if node.single_line?
30
27
 
31
- first_line = node.source_range.first_line
28
+ first_line = adjusted_first_line || node.source_range.first_line
32
29
  last_line = node.source_range.last_line
33
30
 
34
31
  case style
@@ -51,6 +48,7 @@ module RuboCop
51
48
 
52
49
  def check_empty_lines_special(body, first_line, last_line)
53
50
  return unless body
51
+
54
52
  if namespace?(body, with_one_child: true)
55
53
  check_both(:no_empty_lines, first_line, last_line)
56
54
  else
@@ -124,6 +122,7 @@ module RuboCop
124
122
  def namespace?(body, with_one_child: false)
125
123
  if body.begin_type?
126
124
  return false if with_one_child
125
+
127
126
  body.children.all? { |child| constant_definition?(child) }
128
127
  else
129
128
  constant_definition?(body)
@@ -160,6 +159,13 @@ module RuboCop
160
159
  def deferred_message(node)
161
160
  format(MSG_DEFERRED, type: node.type)
162
161
  end
162
+
163
+ def valid_body_style?(body)
164
+ # When style is `empty_lines`, if the body is empty, we don't enforce
165
+ # the presence OR absence of an empty line
166
+ # But if style is `no_empty_lines`, there must not be an empty line
167
+ body.nil? && style != :no_empty_lines
168
+ end
163
169
  end
164
170
  end
165
171
  end
@@ -15,6 +15,7 @@ module RuboCop
15
15
  def check(node)
16
16
  empty_arguments?(node) do |args|
17
17
  return if args.empty_and_without_delimiters?
18
+
18
19
  add_offense(args)
19
20
  end
20
21
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module encapsulates the ability to ignore certain methods when
6
+ # parsing.
7
+ module IgnoredMethods
8
+ private
9
+
10
+ def ignored_method?(name)
11
+ ignored_methods.include?(name.to_s)
12
+ end
13
+
14
+ def ignored_methods
15
+ cop_config.fetch('IgnoredMethods', [])
16
+ end
17
+ end
18
+ end
19
+ end
@@ -56,8 +56,25 @@ module RuboCop
56
56
  end
57
57
  end
58
58
 
59
+ # The correct indentation of `node` is usually `IndentationWidth`, with
60
+ # one exception: prefix keywords.
61
+ #
62
+ # ```
63
+ # while foo && # Here, `while` is called a "prefix keyword"
64
+ # bar # This is called "special indentation"
65
+ # baz
66
+ # end
67
+ # ```
68
+ #
69
+ # Note that *postfix conditionals* do *not* get "special indentation".
70
+ #
71
+ # ```
72
+ # next if foo &&
73
+ # bar # normal indentation, not special
74
+ # ```
59
75
  def correct_indentation(node)
60
- if kw_node_with_special_indentation(node)
76
+ kw_node = kw_node_with_special_indentation(node)
77
+ if kw_node && !postfix_conditional?(kw_node)
61
78
  # This cop could have its own IndentationWidth configuration
62
79
  configured_indentation_width +
63
80
  @config.for_cop('Layout/IndentationWidth')['Width']
@@ -115,6 +132,7 @@ module RuboCop
115
132
  keyword_node =
116
133
  node.each_ancestor(*KEYWORD_ANCESTOR_TYPES).find do |ancestor|
117
134
  next if ancestor.if_type? && ancestor.ternary?
135
+
118
136
  within_node?(node, indented_keyword_expression(ancestor))
119
137
  end
120
138
 
@@ -222,6 +240,12 @@ module RuboCop
222
240
  node.source_range.end_pos < ancestor.loc.end.end_pos
223
241
  end
224
242
 
243
+ # Returns true if `node` is a conditional whose `body` and `condition`
244
+ # begin on the same line.
245
+ def postfix_conditional?(node)
246
+ node.if_type? && node.modifier_form?
247
+ end
248
+
225
249
  def within_node?(inner, outer)
226
250
  o = outer.is_a?(AST::Node) ? outer.source_range : outer
227
251
  i = inner.is_a?(AST::Node) ? inner.source_range : inner
@@ -24,11 +24,13 @@ module RuboCop
24
24
  # b # comment
25
25
  # ].some_method
26
26
  def new_line_needed_before_closing_brace?(node)
27
- return unless node.chained?
28
-
29
27
  last_element_line =
30
28
  last_element_range_with_trailing_comma(node).last_line
31
- processed_source.comments.any? { |c| c.loc.line == last_element_line }
29
+
30
+ last_element_commented =
31
+ processed_source.comments.any? { |c| c.loc.line == last_element_line }
32
+
33
+ last_element_commented && (node.chained? || node.argument?)
32
34
  end
33
35
 
34
36
  def check(node)
@@ -12,11 +12,13 @@ module RuboCop
12
12
 
13
13
  def percent_literal?(node)
14
14
  return unless (begin_source = begin_source(node))
15
+
15
16
  begin_source.start_with?('%')
16
17
  end
17
18
 
18
19
  def process(node, *types)
19
20
  return unless percent_literal?(node) && types.include?(type(node))
21
+
20
22
  on_percent_literal(node)
21
23
  end
22
24
 
@@ -46,10 +46,12 @@ module RuboCop
46
46
  def aligned_with_line?(line_nos, range, indent = nil)
47
47
  line_nos.each do |lineno|
48
48
  next if aligned_comment_lines.include?(lineno + 1)
49
+
49
50
  line = processed_source.lines[lineno]
50
51
  index = line =~ /\S/
51
52
  next unless index
52
53
  next if indent && indent != index
54
+
53
55
  return yield(range, line)
54
56
  end
55
57
  false
@@ -11,8 +11,9 @@ module RuboCop
11
11
  private
12
12
 
13
13
  def_node_matcher :empty_condition?, '(begin)'
14
+ def_node_matcher :setter_method?, '[(send ...) setter_method?]'
14
15
  def_node_matcher :safe_assignment?,
15
- '(begin {equals_asgn? asgn_method_call?})'
16
+ '(begin {equals_asgn? #setter_method?})'
16
17
 
17
18
  def safe_assignment_allowed?
18
19
  cop_config['AllowSafeAssignment']
@@ -52,7 +52,12 @@ module RuboCop
52
52
 
53
53
  def indentation_multiplier
54
54
  return 1 if config.for_cop('Layout/Tab')['Enabled']
55
- config.for_cop('Layout/Tab')['IndentationWidth']
55
+
56
+ default_configuration = RuboCop::ConfigLoader.default_configuration
57
+ config.for_cop('Layout/Tab')['IndentationWidth'] ||
58
+ config.for_cop('Layout/IndentationWidth')['Width'] ||
59
+ default_configuration.for_cop('Layout/Tab')['IndentationWidth'] ||
60
+ default_configuration.for_cop('Layout/IndentationWidth')['Width']
56
61
  end
57
62
  end
58
63
  end
@@ -11,6 +11,7 @@ module RuboCop
11
11
  def wrong_quotes?(node)
12
12
  src = node.source
13
13
  return false if src.start_with?('%', '?')
14
+
14
15
  if style == :single_quotes
15
16
  !double_quotes_required?(src)
16
17
  else
@@ -63,6 +63,7 @@ module RuboCop
63
63
  space_offense(node, left_token, :right, message, NO_SPACE_COMMAND)
64
64
  end
65
65
  return if !extra_space?(right_token, :right) || end_ok
66
+
66
67
  space_offense(node, right_token, :left, message, NO_SPACE_COMMAND)
67
68
  end
68
69
 
@@ -76,11 +77,13 @@ module RuboCop
76
77
  space_offense(node, left_token, :none, message, SPACE_COMMAND)
77
78
  end
78
79
  return if extra_space?(right_token, :right) || end_ok
80
+
79
81
  space_offense(node, right_token, :none, message, SPACE_COMMAND)
80
82
  end
81
83
 
82
84
  def extra_space?(token, side)
83
85
  return false unless token
86
+
84
87
  if side == :left
85
88
  String(token.space_after?) == ' '
86
89
  else
@@ -106,6 +109,7 @@ module RuboCop
106
109
  empty_offense(node, range, message, 'Use one')
107
110
  end
108
111
  return unless offending_empty_no_space?(empty_config, left, right)
112
+
109
113
  empty_offense(node, range, message, 'Do not use')
110
114
  end
111
115
 
@@ -97,6 +97,7 @@ module RuboCop
97
97
 
98
98
  items = elements(node).map(&:source_range)
99
99
  return false if items.empty?
100
+
100
101
  items << node.loc.begin << node.loc.end
101
102
  (items.map(&:first_line) + items.map(&:last_line)).uniq.size > 1
102
103
  end
@@ -16,6 +16,7 @@ module RuboCop
16
16
  name = arg.children.first.to_s
17
17
  next if (arg.restarg_type? || arg.kwrestarg_type?) && name.empty?
18
18
  next if allowed_names.include?(name)
19
+
19
20
  range = arg_range(arg, name.size)
20
21
  issue_offenses(node, range, name)
21
22
  end
@@ -28,6 +29,7 @@ module RuboCop
28
29
  case_offense(node, range) if uppercase?(name)
29
30
  length_offense(node, range) unless long_enough?(name)
30
31
  return if allow_nums
32
+
31
33
  num_offense(node, range) if ends_with_num?(name)
32
34
  end
33
35
 
@@ -44,6 +44,7 @@ module RuboCop
44
44
  def investigate(processed_source)
45
45
  processed_source.each_token do |token|
46
46
  next unless token.type == :tIDENTIFIER && !token.text.ascii_only?
47
+
47
48
  add_offense(token, location: first_offense_range(token))
48
49
  end
49
50
  end
@@ -34,6 +34,7 @@ module RuboCop
34
34
 
35
35
  def op_method?(name)
36
36
  return false if BLACKLISTED.include?(name)
37
+
37
38
  name !~ /\A\w/ || OP_LIKE_METHODS.include?(name)
38
39
  end
39
40
  end
@@ -32,7 +32,8 @@ module RuboCop
32
32
 
33
33
  def investigate(processed_source)
34
34
  file_path = processed_source.file_path
35
- return if config.file_to_include?(file_path)
35
+ return if config.file_to_exclude?(file_path) ||
36
+ config.allowed_camel_case_file?(file_path)
36
37
 
37
38
  for_bad_filename(file_path) do |range, msg|
38
39
  add_offense(nil, location: range, message: msg)
@@ -52,6 +53,7 @@ module RuboCop
52
53
  else
53
54
  return if ignore_executable_scripts? &&
54
55
  processed_source.start_with?('#!')
56
+
55
57
  other_message(basename)
56
58
  end
57
59
 
@@ -121,6 +123,7 @@ module RuboCop
121
123
 
122
124
  node.each_ancestor(:class, :module, :sclass, :casgn) do |ancestor|
123
125
  return false if ancestor.sclass_type?
126
+
124
127
  match_partial.call(ancestor.defined_module)
125
128
  end
126
129
 
@@ -127,6 +127,7 @@ module RuboCop
127
127
 
128
128
  def matches?(method_name, ivar_assign)
129
129
  return true if ivar_assign.nil? || method_name == :initialize
130
+
130
131
  method_name = method_name.to_s.delete('!?')
131
132
  variable = ivar_assign.children.first
132
133
  variable_name = variable.to_s.sub('@', '')
@@ -63,6 +63,7 @@ module RuboCop
63
63
  def allowed_method_name?(method_name, prefix)
64
64
  !method_name.start_with?(prefix) ||
65
65
  method_name == expected_name(method_name, prefix) ||
66
+ method_name.end_with?('=') ||
66
67
  predicate_whitelist.include?(method_name)
67
68
  end
68
69
 
@@ -40,6 +40,7 @@ module RuboCop
40
40
 
41
41
  def on_block(node)
42
42
  return unless node.arguments?
43
+
43
44
  check(node, node.arguments)
44
45
  end
45
46
  end
@@ -48,6 +48,7 @@ module RuboCop
48
48
 
49
49
  def on_def(node)
50
50
  return unless node.arguments?
51
+
51
52
  check(node, node.arguments)
52
53
  end
53
54
  alias on_defs on_def
@@ -27,6 +27,7 @@ module RuboCop
27
27
  def on_lvasgn(node)
28
28
  name, = *node
29
29
  return unless name
30
+
30
31
  check_name(node, name, node.loc.name)
31
32
  end
32
33
  alias on_ivasgn on_lvasgn
@@ -3,16 +3,19 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Performance
6
- # Place `when` conditions that use splat at the end
7
- # of the list of `when` branches.
6
+ # Reordering `when` conditions with a splat to the end
7
+ # of the `when` branches can improve performance.
8
8
  #
9
9
  # Ruby has to allocate memory for the splat expansion every time
10
10
  # that the `case` `when` statement is run. Since Ruby does not support
11
11
  # fall through inside of `case` `when`, like some other languages do,
12
- # the order of the `when` branches does not matter. By placing any
12
+ # the order of the `when` branches should not matter. By placing any
13
13
  # splat expansions at the end of the list of `when` branches we will
14
14
  # reduce the number of times that memory has to be allocated for
15
- # the expansion.
15
+ # the expansion. The exception to this is if multiple of your `when`
16
+ # conditions can be true for any given condition. A likely scenario for
17
+ # this defining a higher level when condition to override a condition
18
+ # that is inside of the splat expansion.
16
19
  #
17
20
  # This is not a guaranteed performance improvement. If the data being
18
21
  # processed by the `case` condition is normalized in a manner that favors
@@ -54,9 +57,10 @@ module RuboCop
54
57
  include Alignment
55
58
  include RangeHelp
56
59
 
57
- MSG = 'Place `when` conditions with a splat ' \
58
- 'at the end of the `when` branches.'.freeze
59
- ARRAY_MSG = 'Do not expand array literals in `when` conditions.'.freeze
60
+ MSG = 'Reordering `when` conditions with a splat to the end ' \
61
+ 'of the `when` branches can improve performance.'.freeze
62
+ ARRAY_MSG = 'Pass the contents of array literals ' \
63
+ 'directly to `when` conditions.'.freeze
60
64
 
61
65
  def on_case(case_node)
62
66
  when_conditions = case_node.when_branches.flat_map(&:conditions)
@@ -18,7 +18,7 @@ module RuboCop
18
18
  # str.casecmp('ABC').zero?
19
19
  # 'abc'.casecmp(str).zero?
20
20
  class Casecmp < Cop
21
- MSG = 'Use `casecmp` instead of `%<methods>s`.'.freeze
21
+ MSG = 'Use `%<good>s` instead of `%<bad>s`.'.freeze
22
22
  CASE_METHODS = %i[downcase upcase].freeze
23
23
 
24
24
  def_node_matcher :downcase_eq, <<-PATTERN
@@ -43,16 +43,29 @@ module RuboCop
43
43
  PATTERN
44
44
 
45
45
  def on_send(node)
46
- return if part_of_ignored_node?(node)
46
+ return unless downcase_eq(node) || eq_downcase(node)
47
+ return unless (parts = take_method_apart(node))
47
48
 
48
- inefficient_comparison(node) do |range, is_other_part, *methods|
49
- ignore_node(node) if is_other_part
50
- add_offense(node, location: range,
51
- message: format(MSG, methods: methods.join(' ')))
52
- end
49
+ _, _, arg, variable = parts
50
+ good_method = build_good_method(arg, variable)
51
+
52
+ add_offense(
53
+ node,
54
+ message: format(MSG, good: good_method, bad: node.source)
55
+ )
53
56
  end
54
57
 
55
58
  def autocorrect(node)
59
+ return unless (parts = take_method_apart(node))
60
+
61
+ receiver, method, arg, variable = parts
62
+
63
+ correction(node, receiver, method, arg, variable)
64
+ end
65
+
66
+ private
67
+
68
+ def take_method_apart(node)
56
69
  if downcase_downcase(node)
57
70
  receiver, method, rhs = *node
58
71
  arg, = *rhs
@@ -65,52 +78,30 @@ module RuboCop
65
78
  end
66
79
 
67
80
  variable, = *receiver
68
- correction(node, receiver, method, arg, variable)
69
- end
70
-
71
- private
72
-
73
- def inefficient_comparison(node)
74
- loc = node.loc
75
81
 
76
- downcase_eq(node) do |send_downcase, case_method, eq_method, other|
77
- *_, method = *other
78
- range, is_other_part = downcase_eq_range(method, loc, send_downcase)
79
-
80
- yield range, is_other_part, case_method, eq_method
81
- return
82
- end
83
-
84
- eq_downcase(node) do |eq_method, send_downcase, case_method|
85
- range = loc.selector.join(send_downcase.loc.selector)
86
- yield range, false, eq_method, case_method
87
- end
88
- end
89
-
90
- def downcase_eq_range(method, loc, send_downcase)
91
- if CASE_METHODS.include?(method)
92
- [loc.expression, true]
93
- else
94
- [loc.selector.join(send_downcase.loc.selector), false]
95
- end
82
+ [receiver, method, arg, variable]
96
83
  end
97
84
 
98
85
  def correction(node, _receiver, method, arg, variable)
99
86
  lambda do |corrector|
100
87
  corrector.insert_before(node.loc.expression, '!') if method == :!=
101
88
 
102
- # we want resulting call to be parenthesized
103
- # if arg already includes one or more sets of parens, don't add more
104
- # or if method call already used parens, again, don't add more
105
- replacement = if arg.send_type? || !parentheses?(arg)
106
- "#{variable.source}.casecmp(#{arg.source}).zero?"
107
- else
108
- "#{variable.source}.casecmp#{arg.source}.zero?"
109
- end
89
+ replacement = build_good_method(arg, variable)
110
90
 
111
91
  corrector.replace(node.loc.expression, replacement)
112
92
  end
113
93
  end
94
+
95
+ def build_good_method(arg, variable)
96
+ # We want resulting call to be parenthesized
97
+ # if arg already includes one or more sets of parens, don't add more
98
+ # or if method call already used parens, again, don't add more
99
+ if arg.send_type? || !parentheses?(arg)
100
+ "#{variable.source}.casecmp(#{arg.source}).zero?"
101
+ else
102
+ "#{variable.source}.casecmp#{arg.source}.zero?"
103
+ end
104
+ end
114
105
  end
115
106
  end
116
107
  end