rubocop 0.47.1 → 0.48.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.

Potentially problematic release.


This version of rubocop might be problematic. Click here for more details.

Files changed (242) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +28 -16
  3. data/config/default.yml +203 -115
  4. data/config/disabled.yml +0 -5
  5. data/config/enabled.yml +92 -8
  6. data/lib/rubocop.rb +24 -1
  7. data/lib/rubocop/ast/builder.rb +7 -2
  8. data/lib/rubocop/ast/node.rb +23 -20
  9. data/lib/rubocop/ast/node/and_node.rb +37 -0
  10. data/lib/rubocop/ast/node/array_node.rb +4 -1
  11. data/lib/rubocop/ast/node/case_node.rb +1 -0
  12. data/lib/rubocop/ast/node/ensure_node.rb +25 -0
  13. data/lib/rubocop/ast/node/hash_node.rb +10 -3
  14. data/lib/rubocop/ast/node/if_node.rb +2 -0
  15. data/lib/rubocop/ast/node/mixin/binary_operator_node.rb +23 -0
  16. data/lib/rubocop/ast/node/mixin/predicate_operator_node.rb +35 -0
  17. data/lib/rubocop/ast/node/or_node.rb +37 -0
  18. data/lib/rubocop/ast/node/resbody_node.rb +25 -0
  19. data/lib/rubocop/ast/node/send_node.rb +190 -0
  20. data/lib/rubocop/ast/node/when_node.rb +1 -1
  21. data/lib/rubocop/ast/traversal.rb +15 -15
  22. data/lib/rubocop/comment_config.rb +1 -1
  23. data/lib/rubocop/config.rb +39 -15
  24. data/lib/rubocop/config_loader.rb +34 -13
  25. data/lib/rubocop/cop/bundler/ordered_gems.rb +23 -4
  26. data/lib/rubocop/cop/commissioner.rb +4 -0
  27. data/lib/rubocop/cop/cop.rb +5 -0
  28. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +53 -0
  29. data/lib/rubocop/cop/lint/debugger.rb +8 -1
  30. data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -1
  31. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +2 -4
  32. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -1
  33. data/lib/rubocop/cop/lint/each_with_object_argument.rb +3 -1
  34. data/lib/rubocop/cop/lint/empty_ensure.rb +6 -2
  35. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  36. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +20 -18
  37. data/lib/rubocop/cop/lint/handle_exceptions.rb +1 -3
  38. data/lib/rubocop/cop/lint/literal_in_condition.rb +1 -1
  39. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  40. data/lib/rubocop/cop/lint/multiple_compare.rb +5 -3
  41. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +26 -18
  42. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +7 -8
  43. data/lib/rubocop/cop/lint/require_parentheses.rb +7 -13
  44. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +7 -3
  45. data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -6
  46. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +7 -8
  47. data/lib/rubocop/cop/lint/unneeded_disable.rb +35 -11
  48. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +1 -1
  49. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -2
  50. data/lib/rubocop/cop/lint/unused_block_argument.rb +6 -6
  51. data/lib/rubocop/cop/lint/useless_assignment.rb +2 -1
  52. data/lib/rubocop/cop/lint/useless_comparison.rb +5 -4
  53. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  54. data/lib/rubocop/cop/message_annotator.rb +7 -3
  55. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  56. data/lib/rubocop/cop/metrics/block_nesting.rb +4 -4
  57. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +2 -2
  58. data/lib/rubocop/cop/metrics/line_length.rb +2 -9
  59. data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -3
  60. data/lib/rubocop/cop/metrics/perceived_complexity.rb +2 -2
  61. data/lib/rubocop/cop/mixin/access_modifier_node.rb +1 -1
  62. data/lib/rubocop/cop/mixin/array_hash_indentation.rb +2 -2
  63. data/lib/rubocop/cop/mixin/check_assignment.rb +6 -6
  64. data/lib/rubocop/cop/mixin/duplication.rb +1 -1
  65. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  66. data/lib/rubocop/cop/mixin/ignored_pattern.rb +27 -0
  67. data/lib/rubocop/cop/mixin/method_preference.rb +2 -0
  68. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +17 -29
  69. data/lib/rubocop/cop/mixin/on_method_def.rb +3 -3
  70. data/lib/rubocop/cop/mixin/percent_literal.rb +27 -0
  71. data/lib/rubocop/cop/mixin/rescue_node.rb +21 -0
  72. data/lib/rubocop/cop/mixin/safe_mode.rb +1 -1
  73. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  74. data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -1
  75. data/lib/rubocop/cop/mixin/target_rails_version.rb +16 -0
  76. data/lib/rubocop/cop/mixin/unused_argument.rb +1 -1
  77. data/lib/rubocop/cop/offense.rb +3 -3
  78. data/lib/rubocop/cop/performance/casecmp.rb +1 -1
  79. data/lib/rubocop/cop/performance/detect.rb +2 -1
  80. data/lib/rubocop/cop/performance/double_start_end_with.rb +35 -1
  81. data/lib/rubocop/cop/performance/end_with.rb +3 -1
  82. data/lib/rubocop/cop/performance/flat_map.rb +6 -6
  83. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +2 -2
  84. data/lib/rubocop/cop/performance/range_include.rb +3 -1
  85. data/lib/rubocop/cop/performance/redundant_match.rb +6 -5
  86. data/lib/rubocop/cop/performance/regexp_match.rb +10 -3
  87. data/lib/rubocop/cop/performance/reverse_each.rb +2 -1
  88. data/lib/rubocop/cop/performance/size.rb +6 -11
  89. data/lib/rubocop/cop/performance/start_with.rb +3 -1
  90. data/lib/rubocop/cop/performance/string_replacement.rb +13 -18
  91. data/lib/rubocop/cop/performance/times_map.rb +4 -4
  92. data/lib/rubocop/cop/rails/action_filter.rb +42 -42
  93. data/lib/rubocop/cop/rails/active_support_aliases.rb +68 -0
  94. data/lib/rubocop/cop/rails/blank.rb +131 -0
  95. data/lib/rubocop/cop/rails/date.rb +25 -28
  96. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +5 -7
  97. data/lib/rubocop/cop/rails/dynamic_find_by.rb +7 -3
  98. data/lib/rubocop/cop/rails/exit.rb +9 -9
  99. data/lib/rubocop/cop/rails/file_path.rb +5 -14
  100. data/lib/rubocop/cop/rails/find_by.rb +8 -10
  101. data/lib/rubocop/cop/rails/find_each.rb +6 -9
  102. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +1 -0
  103. data/lib/rubocop/cop/rails/http_positional_arguments.rb +15 -7
  104. data/lib/rubocop/cop/rails/output.rb +3 -5
  105. data/lib/rubocop/cop/rails/output_safety.rb +4 -8
  106. data/lib/rubocop/cop/rails/pluralization_grammar.rb +25 -24
  107. data/lib/rubocop/cop/rails/present.rb +137 -0
  108. data/lib/rubocop/cop/rails/read_write_attribute.rb +9 -18
  109. data/lib/rubocop/cop/rails/relative_date_constant.rb +53 -0
  110. data/lib/rubocop/cop/rails/request_referer.rb +7 -4
  111. data/lib/rubocop/cop/rails/reversible_migration.rb +1 -2
  112. data/lib/rubocop/cop/rails/safe_navigation.rb +2 -1
  113. data/lib/rubocop/cop/rails/save_bang.rb +10 -10
  114. data/lib/rubocop/cop/rails/skips_model_validations.rb +23 -6
  115. data/lib/rubocop/cop/rails/time_zone.rb +20 -18
  116. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +3 -2
  117. data/lib/rubocop/cop/rails/validation.rb +8 -11
  118. data/lib/rubocop/cop/registry.rb +3 -3
  119. data/lib/rubocop/cop/security/json_load.rb +1 -1
  120. data/lib/rubocop/cop/security/marshal_load.rb +5 -1
  121. data/lib/rubocop/cop/security/yaml_load.rb +3 -3
  122. data/lib/rubocop/cop/severity.rb +1 -1
  123. data/lib/rubocop/cop/style/alias.rb +5 -5
  124. data/lib/rubocop/cop/style/align_hash.rb +1 -1
  125. data/lib/rubocop/cop/style/align_parameters.rb +5 -5
  126. data/lib/rubocop/cop/style/and_or.rb +16 -31
  127. data/lib/rubocop/cop/style/attr.rb +14 -8
  128. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +8 -11
  129. data/lib/rubocop/cop/style/block_delimiters.rb +11 -13
  130. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +19 -23
  131. data/lib/rubocop/cop/style/case_indentation.rb +2 -0
  132. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  133. data/lib/rubocop/cop/style/class_check.rb +5 -7
  134. data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +5 -4
  135. data/lib/rubocop/cop/style/collection_methods.rb +8 -8
  136. data/lib/rubocop/cop/style/colon_method_call.rb +2 -9
  137. data/lib/rubocop/cop/style/conditional_assignment.rb +38 -45
  138. data/lib/rubocop/cop/style/constant_name.rb +1 -1
  139. data/lib/rubocop/cop/style/documentation_method.rb +1 -0
  140. data/lib/rubocop/cop/style/dot_position.rb +3 -7
  141. data/lib/rubocop/cop/style/double_negation.rb +2 -1
  142. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  143. data/lib/rubocop/cop/style/empty_else.rb +2 -2
  144. data/lib/rubocop/cop/style/empty_line_after_magic_comment.rb +63 -0
  145. data/lib/rubocop/cop/style/empty_line_between_defs.rb +74 -4
  146. data/lib/rubocop/cop/style/empty_lines_around_begin_body.rb +42 -0
  147. data/lib/rubocop/cop/style/empty_lines_around_exception_handling_keywords.rb +127 -0
  148. data/lib/rubocop/cop/style/empty_literal.rb +17 -9
  149. data/lib/rubocop/cop/style/end_of_line.rb +25 -3
  150. data/lib/rubocop/cop/style/file_name.rb +1 -1
  151. data/lib/rubocop/cop/style/first_method_argument_line_break.rb +1 -1
  152. data/lib/rubocop/cop/style/first_parameter_indentation.rb +17 -19
  153. data/lib/rubocop/cop/style/for.rb +2 -4
  154. data/lib/rubocop/cop/style/format_string.rb +5 -4
  155. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  156. data/lib/rubocop/cop/style/identical_conditional_branches.rb +27 -1
  157. data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -2
  158. data/lib/rubocop/cop/style/indent_assignment.rb +2 -2
  159. data/lib/rubocop/cop/style/indent_hash.rb +2 -1
  160. data/lib/rubocop/cop/style/indent_heredoc.rb +173 -0
  161. data/lib/rubocop/cop/style/indentation_width.rb +61 -29
  162. data/lib/rubocop/cop/style/inverse_methods.rb +130 -0
  163. data/lib/rubocop/cop/style/lambda_call.rb +15 -11
  164. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -4
  165. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +26 -14
  166. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +6 -16
  167. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
  168. data/lib/rubocop/cop/style/missing_else.rb +4 -3
  169. data/lib/rubocop/cop/style/mixin_grouping.rb +97 -0
  170. data/lib/rubocop/cop/style/multiline_memoization.rb +38 -5
  171. data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +2 -3
  172. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +38 -19
  173. data/lib/rubocop/cop/style/mutable_constant.rb +5 -1
  174. data/lib/rubocop/cop/style/negated_if.rb +73 -1
  175. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +21 -19
  176. data/lib/rubocop/cop/style/next.rb +5 -5
  177. data/lib/rubocop/cop/style/non_nil_check.rb +7 -10
  178. data/lib/rubocop/cop/style/not.rb +3 -4
  179. data/lib/rubocop/cop/style/numeric_literals.rb +25 -3
  180. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  181. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -2
  182. data/lib/rubocop/cop/style/op_method.rb +2 -2
  183. data/lib/rubocop/cop/style/parallel_assignment.rb +6 -3
  184. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +52 -6
  185. data/lib/rubocop/cop/style/perl_backrefs.rb +1 -1
  186. data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -9
  187. data/lib/rubocop/cop/style/raise_args.rb +28 -24
  188. data/lib/rubocop/cop/style/redundant_freeze.rb +5 -7
  189. data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -3
  190. data/lib/rubocop/cop/style/redundant_self.rb +17 -35
  191. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -14
  192. data/lib/rubocop/cop/style/self_assignment.rb +3 -3
  193. data/lib/rubocop/cop/style/send.rb +4 -5
  194. data/lib/rubocop/cop/style/space_after_not.rb +7 -8
  195. data/lib/rubocop/cop/style/space_around_keyword.rb +8 -9
  196. data/lib/rubocop/cop/style/space_around_operators.rb +19 -15
  197. data/lib/rubocop/cop/style/space_before_first_arg.rb +17 -14
  198. data/lib/rubocop/cop/style/space_inside_brackets.rb +1 -1
  199. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +3 -3
  200. data/lib/rubocop/cop/style/space_inside_parens.rb +1 -1
  201. data/lib/rubocop/cop/style/special_global_vars.rb +14 -14
  202. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -1
  203. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  204. data/lib/rubocop/cop/style/string_methods.rb +10 -5
  205. data/lib/rubocop/cop/style/struct_inheritance.rb +4 -15
  206. data/lib/rubocop/cop/style/symbol_array.rb +31 -35
  207. data/lib/rubocop/cop/style/symbol_proc.rb +2 -2
  208. data/lib/rubocop/cop/style/ternary_parentheses.rb +41 -13
  209. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +6 -9
  210. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -1
  211. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  212. data/lib/rubocop/cop/style/unneeded_capital_w.rb +1 -2
  213. data/lib/rubocop/cop/style/unneeded_percent_q.rb +1 -1
  214. data/lib/rubocop/cop/style/word_array.rb +12 -34
  215. data/lib/rubocop/cop/style/zero_length_predicate.rb +11 -4
  216. data/lib/rubocop/cop/team.rb +4 -1
  217. data/lib/rubocop/cop/util.rb +33 -26
  218. data/lib/rubocop/cop/variable_force.rb +13 -13
  219. data/lib/rubocop/cop/variable_force/assignment.rb +1 -8
  220. data/lib/rubocop/cop/variable_force/branch.rb +318 -0
  221. data/lib/rubocop/cop/variable_force/branchable.rb +21 -0
  222. data/lib/rubocop/cop/variable_force/reference.rb +1 -3
  223. data/lib/rubocop/cop/variable_force/scope.rb +36 -20
  224. data/lib/rubocop/cop/variable_force/variable.rb +9 -8
  225. data/lib/rubocop/formatter/colorizable.rb +10 -10
  226. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  227. data/lib/rubocop/formatter/html_formatter.rb +2 -1
  228. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -2
  229. data/lib/rubocop/magic_comment.rb +20 -6
  230. data/lib/rubocop/options.rb +1 -1
  231. data/lib/rubocop/platform.rb +11 -0
  232. data/lib/rubocop/processed_source.rb +1 -1
  233. data/lib/rubocop/remote_config.rb +18 -6
  234. data/lib/rubocop/result_cache.rb +8 -8
  235. data/lib/rubocop/rspec/cop_helper.rb +2 -0
  236. data/lib/rubocop/rspec/shared_contexts.rb +20 -0
  237. data/lib/rubocop/rspec/shared_examples.rb +1 -1
  238. data/lib/rubocop/runner.rb +2 -2
  239. data/lib/rubocop/target_finder.rb +64 -6
  240. data/lib/rubocop/version.rb +2 -4
  241. metadata +27 -4
  242. data/lib/rubocop/cop/variable_force/locatable.rb +0 -200
@@ -30,14 +30,11 @@ module RuboCop
30
30
  include TrailingComma
31
31
 
32
32
  def on_send(node)
33
- _receiver, _method_name, *args = *node
34
- return if args.empty?
35
- # It's impossible for a method call without parentheses to have
36
- # a trailing comma.
37
- return unless brackets?(node)
33
+ return unless node.arguments? && node.parenthesized?
38
34
 
39
- check(node, args, 'parameter of %s method call',
40
- args.last.source_range.end_pos, node.source_range.end_pos)
35
+ check(node, node.arguments, 'parameter of %s method call',
36
+ node.last_argument.source_range.end_pos,
37
+ node.source_range.end_pos)
41
38
  end
42
39
 
43
40
  private
@@ -51,7 +48,7 @@ module RuboCop
51
48
  # of the last argument.
52
49
  def braces_will_be_removed?(args)
53
50
  brace_config = config.for_cop('Style/BracesAroundHashParameters')
54
- return false unless brace_config['Enabled']
51
+ return false unless brace_config.fetch('Enabled')
55
52
  return false if brace_config['AutoCorrect'] == false
56
53
 
57
54
  brace_style = brace_config['EnforcedStyle']
@@ -59,7 +56,7 @@ module RuboCop
59
56
 
60
57
  return false unless brace_style == 'context_dependent'
61
58
 
62
- args.size == 1 || !args[-2].hash_type?
59
+ args.one? || !args[-2].hash_type?
63
60
  end
64
61
  end
65
62
  end
@@ -12,11 +12,14 @@ module RuboCop
12
12
  # a, _, _ = foo()
13
13
  # a, _, _, = foo()
14
14
  #
15
- # #good
15
+ # # good
16
16
  # a, b, = foo()
17
17
  # a, = foo()
18
18
  # *a, b, _ = foo() => We need to know to not include 2 variables in a
19
19
  # a, *b, _ = foo() => The correction `a, *b, = foo()` is a syntax error
20
+ #
21
+ # # good if AllowNamedUnderscoreVariables is true
22
+ # a, b, _something = foo()
20
23
  class TrailingUnderscoreVariable < Cop
21
24
  include SurroundingSpace
22
25
 
@@ -95,7 +95,7 @@ module RuboCop
95
95
 
96
96
  def looks_like_trivial_writer?(args, body)
97
97
  args.children.one? &&
98
- ![:restarg, :blockarg].include?(args.children[0].type) &&
98
+ !%i(restarg blockarg).include?(args.children[0].type) &&
99
99
  body && body.ivasgn_type? &&
100
100
  body.children[1] && body.children[1].lvar_type?
101
101
  end
@@ -25,8 +25,7 @@ module RuboCop
25
25
  def requires_interpolation?(node)
26
26
  node.child_nodes.any? do |string|
27
27
  string.dstr_type? ||
28
- double_quotes_acceptable?(string.str_content) ||
29
- string.source == '\s'
28
+ double_quotes_required?(string.source)
30
29
  end
31
30
  end
32
31
 
@@ -88,7 +88,7 @@ module RuboCop
88
88
  src = node.source
89
89
  src.include?(QUOTE) &&
90
90
  (src =~ STRING_INTERPOLATION_REGEXP ||
91
- (node.str_type? && double_quotes_acceptable?(node.str_content)))
91
+ (node.str_type? && double_quotes_required?(src)))
92
92
  end
93
93
  end
94
94
  end
@@ -10,11 +10,17 @@ module RuboCop
10
10
  # which do not want to include that syntax.
11
11
  class WordArray < Cop
12
12
  include ArraySyntax
13
+ include ConfigurableEnforcedStyle
14
+ include PercentLiteral
13
15
 
14
16
  PERCENT_MSG = 'Use `%w` or `%W` for an array of words.'.freeze
15
17
  ARRAY_MSG = 'Use `[]` for an array of words.'.freeze
16
18
  QUESTION_MARK_SIZE = '?'.size
17
19
 
20
+ class << self
21
+ attr_accessor :largest_brackets
22
+ end
23
+
18
24
  def on_array(node)
19
25
  if bracketed_array_of?(:str, node)
20
26
  check_bracketed(node)
@@ -25,7 +31,7 @@ module RuboCop
25
31
 
26
32
  def autocorrect(node)
27
33
  if style == :percent
28
- correct_percent(node)
34
+ correct_percent(node, 'w')
29
35
  else
30
36
  correct_bracketed(node)
31
37
  end
@@ -68,27 +74,12 @@ module RuboCop
68
74
  end
69
75
  end
70
76
 
71
- def style
72
- cop_config['EnforcedStyle'].to_sym
73
- end
74
-
75
77
  def min_size
76
78
  cop_config['MinSize']
77
79
  end
78
80
 
79
81
  def word_regex
80
- cop_config['WordRegex']
81
- end
82
-
83
- def correct_percent(node)
84
- words = node.children
85
- escape = words.any? { |w| needs_escaping?(w.children[0]) }
86
- char = escape ? 'W' : 'w'
87
- contents = autocorrect_words(words, escape, node.loc.line)
88
-
89
- lambda do |corrector|
90
- corrector.replace(node.source_range, "%#{char}(#{contents})")
91
- end
82
+ Regexp.new(cop_config['WordRegex'])
92
83
  end
93
84
 
94
85
  def correct_bracketed(node)
@@ -99,19 +90,6 @@ module RuboCop
99
90
  end
100
91
  end
101
92
 
102
- def autocorrect_words(word_nodes, escape, base_line_number)
103
- previous_node_line_number = base_line_number
104
- word_nodes.map do |node|
105
- number_of_line_breaks = node.loc.line - previous_node_line_number
106
- line_breaks = "\n" * number_of_line_breaks
107
- previous_node_line_number = node.loc.line
108
- content = node.children.first
109
- content = escape ? escape_string(content) : content
110
- content.gsub!(/\)/, '\\)')
111
- line_breaks + content
112
- end.join(' ')
113
- end
114
-
115
93
  def style_detected(style, ary_size)
116
94
  cfg = config_to_allow_offenses
117
95
  return if cfg['Enabled'] == false
@@ -132,13 +110,13 @@ module RuboCop
132
110
  end
133
111
 
134
112
  def largest_brackets_size(style, ary_size)
135
- @largest_brackets ||= -Float::INFINITY
113
+ self.class.largest_brackets ||= -Float::INFINITY
136
114
 
137
- if style == :brackets && ary_size > @largest_brackets
138
- @largest_brackets = ary_size
115
+ if style == :brackets && ary_size > self.class.largest_brackets
116
+ self.class.largest_brackets = ary_size
139
117
  end
140
118
 
141
- @largest_brackets
119
+ self.class.largest_brackets
142
120
  end
143
121
 
144
122
  def smallest_percent_size(style, ary_size)
@@ -3,21 +3,28 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop checks for receiver.length == 0 predicates and the
7
- # negated versions receiver.length > 0 and receiver.length != 0.
8
- # These can be replaced with receiver.empty? and
9
- # !receiver.empty? respectively.
6
+ # This cop checks for numeric comparisons that can be replaced
7
+ # by a predicate method, such as receiver.length == 0,
8
+ # receiver.length > 0, receiver.length != 0,
9
+ # receiver.length < 1 and receiver.size == 0 that can be
10
+ # replaced by receiver.empty? and !receiver.empty.
10
11
  #
11
12
  # @example
12
13
  #
13
14
  # @bad
14
15
  # [1, 2, 3].length == 0
15
16
  # 0 == "foobar".length
17
+ # array.length < 1
18
+ # {a: 1, b: 2}.length != 0
19
+ # string.length > 0
16
20
  # hash.size > 0
17
21
  #
18
22
  # @good
19
23
  # [1, 2, 3].empty?
20
24
  # "foobar".empty?
25
+ # array.empty?
26
+ # !{a: 1, b: 2}.empty?
27
+ # !string.empty?
21
28
  # !hash.empty?
22
29
  class ZeroLengthPredicate < Cop
23
30
  ZERO_MSG = 'Use `empty?` instead of `%s %s %s`.'.freeze
@@ -10,7 +10,10 @@ module RuboCop
10
10
  Style::SymbolProc => [Style::SpaceBeforeBlockBraces],
11
11
  Style::SpaceBeforeBlockBraces => [Style::SymbolProc],
12
12
  Style::LineEndConcatenation => [Style::UnneededInterpolation],
13
- Style::UnneededInterpolation => [Style::LineEndConcatenation]
13
+ Style::UnneededInterpolation => [Style::LineEndConcatenation],
14
+ Style::SelfAssignment => [Style::SpaceAroundOperators],
15
+ Style::SpaceAroundOperators => [Style::SelfAssignment],
16
+ Style::BracesAroundHashParameters => [Style::MultilineHashBraceLayout]
14
17
  }.freeze
15
18
 
16
19
  DEFAULT_OPTIONS = {
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
- # rubocop:disable Metrics/ModuleLength
3
2
 
3
+ # rubocop:disable Metrics/ModuleLength
4
4
  module RuboCop
5
5
  module Cop
6
6
  # This module contains a collection of useful utility methods.
@@ -10,14 +10,14 @@ module RuboCop
10
10
 
11
11
  BYTE_ORDER_MARK = 0xfeff # The Unicode codepoint
12
12
 
13
- EQUALS_ASGN_NODES = [:lvasgn, :ivasgn, :cvasgn, :gvasgn,
14
- :casgn, :masgn].freeze
15
- SHORTHAND_ASGN_NODES = [:op_asgn, :or_asgn, :and_asgn].freeze
13
+ EQUALS_ASGN_NODES = %i(lvasgn ivasgn cvasgn gvasgn
14
+ casgn masgn).freeze
15
+ SHORTHAND_ASGN_NODES = %i(op_asgn or_asgn and_asgn).freeze
16
16
  ASGN_NODES = (EQUALS_ASGN_NODES + SHORTHAND_ASGN_NODES).freeze
17
17
 
18
- MODIFIER_NODES = [:if, :while, :until].freeze
18
+ MODIFIER_NODES = %i(if while until).freeze
19
19
  CONDITIONAL_NODES = (MODIFIER_NODES + [:case]).freeze
20
- LOGICAL_OPERATOR_NODES = [:and, :or].freeze
20
+ LOGICAL_OPERATOR_NODES = %i(and or).freeze
21
21
 
22
22
  # http://phrogz.net/programmingruby/language.html#table_18.4
23
23
  # Backtick is added last just to help editors parse this code.
@@ -90,7 +90,7 @@ module RuboCop
90
90
  def source_range(source_buffer, line_number, column, length = 1)
91
91
  if column.is_a?(Range)
92
92
  column_index = column.begin
93
- length = numeric_range_size(column)
93
+ length = column.size
94
94
  else
95
95
  column_index = column
96
96
  end
@@ -199,14 +199,6 @@ module RuboCop
199
199
  node
200
200
  end
201
201
 
202
- # Range#size is not available prior to Ruby 2.0.
203
- def numeric_range_size(range)
204
- size = range.end - range.begin
205
- size += 1 unless range.exclude_end?
206
- size = 0 if size < 0
207
- size
208
- end
209
-
210
202
  # If converting a string to Ruby string literal source code, must
211
203
  # double quotes be used?
212
204
  def double_quotes_required?(string)
@@ -219,16 +211,6 @@ module RuboCop
219
211
  string =~ /'|(?<! \\) \\{2}* \\ (?![\\"])/x
220
212
  end
221
213
 
222
- # If double quoted string literals are found in Ruby code, and they are
223
- # not the preferred style, should they be flagged?
224
- def double_quotes_acceptable?(string)
225
- needs_escaping?(string) || hard_to_type?(string)
226
- end
227
-
228
- def hard_to_type?(string)
229
- string.codepoints.any? { |cp| cp < 32 || cp > 126 }
230
- end
231
-
232
214
  def needs_escaping?(string)
233
215
  double_quotes_required?(escape_string(string))
234
216
  end
@@ -246,7 +228,32 @@ module RuboCop
246
228
  end
247
229
 
248
230
  def to_symbol_literal(string)
249
- ":#{string.to_sym}"
231
+ if symbol_without_quote?(string)
232
+ ":#{string}"
233
+ else
234
+ ":#{to_string_literal(string)}"
235
+ end
236
+ end
237
+
238
+ def symbol_without_quote?(string)
239
+ special_gvars = %w(
240
+ $! $" $$ $& $' $* $+ $, $/ $; $: $. $< $= $> $? $@ $\\ $_ $` $~ $0
241
+ $-0 $-F $-I $-K $-W $-a $-d $-i $-l $-p $-v $-w
242
+ )
243
+ redefinable_operators = %w(
244
+ | ^ & <=> == === =~ > >= < <= << >>
245
+ + - * / % ** ~ +@ -@ [] []= ` ! != !~
246
+ )
247
+
248
+ # method name
249
+ string =~ /\A[a-zA-Z_]\w*[!?]?\z/ ||
250
+ # instance / class variable
251
+ string =~ /\A\@\@?[a-zA-Z_]\w*\z/ ||
252
+ # global variable
253
+ string =~ /\A\$[1-9]\d*\z/ ||
254
+ string =~ /\A\$[a-zA-Z_]\w*\z/ ||
255
+ special_gvars.include?(string) ||
256
+ redefinable_operators.include?(string)
250
257
  end
251
258
 
252
259
  def interpret_string_escapes(string)
@@ -35,7 +35,7 @@ module RuboCop
35
35
  :shadowarg # This means block local variable (obj.each { |arg; this| }).
36
36
  ].freeze
37
37
 
38
- LOGICAL_OPERATOR_ASSIGNMENT_TYPES = [:or_asgn, :and_asgn].freeze
38
+ LOGICAL_OPERATOR_ASSIGNMENT_TYPES = %i(or_asgn and_asgn).freeze
39
39
  OPERATOR_ASSIGNMENT_TYPES =
40
40
  (LOGICAL_OPERATOR_ASSIGNMENT_TYPES + [:op_asgn]).freeze
41
41
 
@@ -43,15 +43,15 @@ module RuboCop
43
43
 
44
44
  VARIABLE_REFERENCE_TYPE = :lvar
45
45
 
46
- POST_CONDITION_LOOP_TYPES = [:while_post, :until_post].freeze
47
- LOOP_TYPES = (POST_CONDITION_LOOP_TYPES + [:while, :until, :for]).freeze
46
+ POST_CONDITION_LOOP_TYPES = %i(while_post until_post).freeze
47
+ LOOP_TYPES = (POST_CONDITION_LOOP_TYPES + %i(while until for)).freeze
48
48
 
49
49
  RESCUE_TYPE = :rescue
50
50
 
51
51
  ZERO_ARITY_SUPER_TYPE = :zsuper
52
52
 
53
- TWISTED_SCOPE_TYPES = [:block, :class, :sclass, :defs].freeze
54
- SCOPE_TYPES = (TWISTED_SCOPE_TYPES + [:module, :def]).freeze
53
+ TWISTED_SCOPE_TYPES = %i(block class sclass defs).freeze
54
+ SCOPE_TYPES = (TWISTED_SCOPE_TYPES + %i(module def)).freeze
55
55
 
56
56
  SEND_TYPE = :send
57
57
 
@@ -376,14 +376,14 @@ module RuboCop
376
376
  end
377
377
 
378
378
  # Hooks invoked by VariableTable.
379
- [
380
- :before_entering_scope,
381
- :after_entering_scope,
382
- :before_leaving_scope,
383
- :after_leaving_scope,
384
- :before_declaring_variable,
385
- :after_declaring_variable
386
- ].each do |hook|
379
+ %i(
380
+ before_entering_scope
381
+ after_entering_scope
382
+ before_leaving_scope
383
+ after_leaving_scope
384
+ before_declaring_variable
385
+ after_declaring_variable
386
+ ).each do |hook|
387
387
  define_method(hook) do |arg|
388
388
  # Invoke hook in cops.
389
389
  run_hook(hook, arg, variable_table)
@@ -5,10 +5,9 @@ module RuboCop
5
5
  class VariableForce
6
6
  # This class represents each assignment of a variable.
7
7
  class Assignment
8
- include Locatable
8
+ include Branchable
9
9
 
10
10
  MULTIPLE_LEFT_HAND_SIDE_TYPE = :mlhs
11
- REFERENCE_PENETRABLE_BRANCH_TYPES = %w(rescue_main ensure_main).freeze
12
11
 
13
12
  attr_reader :node, :variable, :referenced
14
13
  alias referenced? referenced
@@ -23,8 +22,6 @@ module RuboCop
23
22
  @node = node
24
23
  @variable = variable
25
24
  @referenced = false
26
-
27
- super
28
25
  end
29
26
 
30
27
  def name
@@ -43,10 +40,6 @@ module RuboCop
43
40
  @variable.captured_by_block? || @referenced
44
41
  end
45
42
 
46
- def reference_penetrable?
47
- REFERENCE_PENETRABLE_BRANCH_TYPES.include?(branch_type)
48
- end
49
-
50
43
  def regexp_named_capture?
51
44
  @node.type == REGEXP_NAMED_CAPTURE_TYPE
52
45
  end
@@ -0,0 +1,318 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ class VariableForce
6
+ # Namespace for branch classes for each control structure.
7
+ module Branch
8
+ def self.of(target_node, scope: nil)
9
+ ([target_node] + target_node.ancestors).each do |node|
10
+ return nil unless node.parent
11
+ return nil unless scope.include?(node)
12
+ klass = CLASSES_BY_TYPE[node.parent.type]
13
+ next unless klass
14
+ branch = klass.new(node, scope)
15
+ return branch if branch.branched?
16
+ end
17
+
18
+ nil
19
+ end
20
+
21
+ # rubocop:disable Metrics/BlockLength
22
+
23
+ # Abstract base class for branch classes.
24
+ # A branch represents a conditional branch in a scope.
25
+ #
26
+ # @example
27
+ # def some_scope
28
+ # do_something # no branch
29
+ #
30
+ # if foo
31
+ # do_something # branch A
32
+ # do_something # branch A
33
+ # else
34
+ # do_something # branch B
35
+ # if bar
36
+ # do_something # branch C (whose parent is branch B)
37
+ # end
38
+ # end
39
+ #
40
+ # do_something # no branch
41
+ # end
42
+ Base = Struct.new(:child_node, :scope) do
43
+ # rubocop:enable Metrics/BlockLength
44
+
45
+ def self.classes
46
+ @classes ||= []
47
+ end
48
+
49
+ def self.inherited(subclass)
50
+ classes << subclass
51
+ end
52
+
53
+ def self.type
54
+ name.split('::').last.gsub(/(.)([A-Z])/, '\1_\2').downcase.to_sym
55
+ end
56
+
57
+ def self.define_predicate(name, child_index: nil)
58
+ define_method(name) do
59
+ target_node = control_node.children[child_index]
60
+
61
+ # We don't use Kernel#Array here
62
+ # because it invokes Node#to_a rather than wrapping with an array.
63
+ if target_node.is_a?(Array)
64
+ target_node.any? { |node| node.equal?(child_node) }
65
+ else
66
+ target_node.equal?(child_node)
67
+ end
68
+ end
69
+ end
70
+
71
+ def control_node
72
+ child_node.parent
73
+ end
74
+
75
+ def parent
76
+ return @parent if instance_variable_defined?(:@parent)
77
+ @branch = Branch.of(control_node, scope: scope)
78
+ end
79
+
80
+ def each_ancestor(include_self: false, &block)
81
+ unless block_given?
82
+ return to_enum(__method__, include_self: include_self)
83
+ end
84
+
85
+ yield self if include_self
86
+ scan_ancestors(&block)
87
+ self
88
+ end
89
+
90
+ def branched?
91
+ !always_run?
92
+ end
93
+
94
+ def always_run?
95
+ raise NotImplementedError
96
+ end
97
+
98
+ def may_jump_to_other_branch?
99
+ false
100
+ end
101
+
102
+ def may_run_incompletely?
103
+ false
104
+ end
105
+
106
+ def exclusive_with?(other)
107
+ return false unless other
108
+ return false if may_jump_to_other_branch?
109
+
110
+ other.each_ancestor(include_self: true) do |other_ancestor|
111
+ if control_node.equal?(other_ancestor.control_node)
112
+ return !child_node.equal?(other_ancestor.child_node)
113
+ end
114
+ end
115
+
116
+ if parent
117
+ parent.exclusive_with?(other)
118
+ else
119
+ false
120
+ end
121
+ end
122
+
123
+ def ==(other)
124
+ return false unless other
125
+ control_node.equal?(other.control_node) &&
126
+ child_node.equal?(other.child_node)
127
+ end
128
+
129
+ alias_method :eql?, :==
130
+
131
+ def hash
132
+ control_node.object_id.hash ^ child_node.object_id.hash
133
+ end
134
+
135
+ private
136
+
137
+ def scan_ancestors
138
+ branch = self
139
+
140
+ while (branch = branch.parent)
141
+ yield branch
142
+ end
143
+ end
144
+ end
145
+
146
+ # Mix-in module for simple conditional control structures.
147
+ module SimpleConditional
148
+ def conditional_clause?
149
+ raise NotImplementedError
150
+ end
151
+
152
+ def always_run?
153
+ conditional_clause?
154
+ end
155
+ end
156
+
157
+ # if conditional_clause
158
+ # truthy_body
159
+ # else
160
+ # falsey_body
161
+ # end
162
+ #
163
+ # unless conditional_clause
164
+ # falsey_body
165
+ # else
166
+ # truthy_body
167
+ # end
168
+ class If < Base
169
+ include SimpleConditional
170
+
171
+ define_predicate :conditional_clause?, child_index: 0
172
+ define_predicate :truthy_body?, child_index: 1
173
+ define_predicate :falsey_body?, child_index: 2
174
+ end
175
+
176
+ # while conditional_clause
177
+ # loop_body
178
+ # end
179
+ class While < Base
180
+ include SimpleConditional
181
+
182
+ define_predicate :conditional_clause?, child_index: 0
183
+ define_predicate :loop_body?, child_index: 1
184
+ end
185
+
186
+ # until conditional_clause
187
+ # loop_body
188
+ # end
189
+ class Until < Base
190
+ include SimpleConditional
191
+
192
+ define_predicate :conditional_clause?, child_index: 0
193
+ define_predicate :loop_body?, child_index: 1
194
+ end
195
+
196
+ # begin
197
+ # loop_body
198
+ # end while conditional_clause
199
+ class WhilePost < Base
200
+ include SimpleConditional
201
+
202
+ define_predicate :conditional_clause?, child_index: 0
203
+ define_predicate :loop_body?, child_index: 1
204
+ end
205
+
206
+ # begin
207
+ # loop_body
208
+ # end until conditional_clause
209
+ class UntilPost < Base
210
+ include SimpleConditional
211
+
212
+ define_predicate :conditional_clause?, child_index: 0
213
+ define_predicate :loop_body?, child_index: 1
214
+ end
215
+
216
+ # case target
217
+ # when /pattern/ # when_clause
218
+ # else
219
+ # else_body
220
+ # end
221
+ class Case < Base
222
+ define_predicate :target?, child_index: 0
223
+ define_predicate :when_clause?, child_index: 1..-2
224
+ define_predicate :else_body?, child_index: -1
225
+
226
+ def always_run?
227
+ target?
228
+ end
229
+ end
230
+
231
+ # for element in collection
232
+ # loop_body
233
+ # end
234
+ class For < Base
235
+ define_predicate :element?, child_index: 0
236
+ define_predicate :collection?, child_index: 1
237
+ define_predicate :loop_body?, child_index: 2
238
+
239
+ def always_run?
240
+ element? || collection?
241
+ end
242
+ end
243
+
244
+ # Mix-in module for logical operator control structures.
245
+ module LogicalOperator
246
+ def always_run?
247
+ left_body?
248
+ end
249
+ end
250
+
251
+ # left_body && right_body
252
+ class And < Base
253
+ include LogicalOperator
254
+
255
+ define_predicate :left_body?, child_index: 0
256
+ define_predicate :right_body?, child_index: 1
257
+ end
258
+
259
+ # left_body || right_body
260
+ class Or < Base
261
+ include LogicalOperator
262
+
263
+ define_predicate :left_body?, child_index: 0
264
+ define_predicate :right_body?, child_index: 1
265
+ end
266
+
267
+ # Mix-in module for exception handling control structures.
268
+ module ExceptionHandler
269
+ def may_jump_to_other_branch?
270
+ main_body?
271
+ end
272
+
273
+ def may_run_incompletely?
274
+ main_body?
275
+ end
276
+ end
277
+
278
+ # begin
279
+ # main_body
280
+ # rescue StandardError => error # rescue_clause
281
+ # else
282
+ # else_body
283
+ # end
284
+ class Rescue < Base
285
+ include ExceptionHandler
286
+
287
+ define_predicate :main_body?, child_index: 0
288
+ define_predicate :rescue_clause?, child_index: 1..-2
289
+ define_predicate :else_body?, child_index: -1
290
+
291
+ def always_run?
292
+ false
293
+ end
294
+ end
295
+
296
+ # begin
297
+ # main_body
298
+ # ensure
299
+ # ensure_body
300
+ # end
301
+ class Ensure < Base
302
+ include ExceptionHandler
303
+
304
+ define_predicate :main_body?, child_index: 0
305
+ define_predicate :ensure_body?, child_index: -1
306
+
307
+ def always_run?
308
+ ensure_body?
309
+ end
310
+ end
311
+
312
+ CLASSES_BY_TYPE = Base.classes.each_with_object({}) do |klass, classes|
313
+ classes[klass.type] = klass
314
+ end
315
+ end
316
+ end
317
+ end
318
+ end