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
@@ -4,7 +4,31 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # This cop checks whether method definitions are
7
- # separated by empty lines.
7
+ # separated by one empty line.
8
+ #
9
+ # `NumberOfEmptyLines` can be and integer (e.g. 1 by default) or
10
+ # an array (e.g. [1, 2]) to specificy a minimum and a maximum of
11
+ # empty lines.
12
+ #
13
+ # `AllowAdjacentOneLineDefs` can be used to configure is adjacent
14
+ # one line methods definitions are an offense
15
+ #
16
+ # @example
17
+ #
18
+ # # bad
19
+ # def a
20
+ # end
21
+ # def b
22
+ # end
23
+ #
24
+ # @example
25
+ #
26
+ # # good
27
+ # def a
28
+ # end
29
+ #
30
+ # def b
31
+ # end
8
32
  class EmptyLineBetweenDefs < Cop
9
33
  MSG = 'Use empty lines between method definitions.'.freeze
10
34
 
@@ -22,6 +46,7 @@ module RuboCop
22
46
 
23
47
  def check_defs(nodes)
24
48
  return if blank_lines_between?(*nodes)
49
+ return if multiple_blank_lines_groups?(*nodes)
25
50
  return if nodes.all?(&:single_line?) &&
26
51
  cop_config['AllowAdjacentOneLineDefs']
27
52
 
@@ -35,8 +60,29 @@ module RuboCop
35
60
  node.def_type? || node.defs_type?
36
61
  end
37
62
 
63
+ def multiple_blank_lines_groups?(first_def_node, second_def_node)
64
+ lines = lines_between_defs(first_def_node, second_def_node)
65
+ blank_start = lines.each_index.select { |i| lines[i].blank? }.max
66
+ non_blank_end = lines.each_index.reject { |i| lines[i].blank? }.min
67
+ return false if blank_start.nil? || non_blank_end.nil?
68
+ blank_start > non_blank_end
69
+ end
70
+
38
71
  def blank_lines_between?(first_def_node, second_def_node)
39
- lines_between_defs(first_def_node, second_def_node).any?(&:blank?)
72
+ count = blank_lines_count_between(first_def_node, second_def_node)
73
+ (minimum_empty_lines..maximum_empty_lines).cover?(count)
74
+ end
75
+
76
+ def blank_lines_count_between(first_def_node, second_def_node)
77
+ lines_between_defs(first_def_node, second_def_node).count(&:blank?)
78
+ end
79
+
80
+ def minimum_empty_lines
81
+ Array(cop_config['NumberOfEmptyLines']).first
82
+ end
83
+
84
+ def maximum_empty_lines
85
+ Array(cop_config['NumberOfEmptyLines']).last
40
86
  end
41
87
 
42
88
  def prev_node(node)
@@ -61,11 +107,35 @@ module RuboCop
61
107
 
62
108
  def autocorrect(node)
63
109
  prev_def = prev_node(node)
110
+
111
+ # finds position of first newline
64
112
  end_pos = prev_def.loc.end.end_pos
65
113
  source_buffer = prev_def.loc.end.source_buffer
66
114
  newline_pos = source_buffer.source.index("\n", end_pos)
67
- newline = range_between(newline_pos, newline_pos + 1)
68
- ->(corrector) { corrector.insert_after(newline, "\n") }
115
+
116
+ count = blank_lines_count_between(prev_def, node)
117
+
118
+ if count > maximum_empty_lines
119
+ autocorrect_remove_lines(newline_pos, count)
120
+ else
121
+ autocorrect_insert_lines(newline_pos, count)
122
+ end
123
+ end
124
+
125
+ def autocorrect_remove_lines(newline_pos, count)
126
+ difference = count - maximum_empty_lines
127
+ range_to_remove = range_between(newline_pos, newline_pos + difference)
128
+ lambda do |corrector|
129
+ corrector.remove(range_to_remove)
130
+ end
131
+ end
132
+
133
+ def autocorrect_insert_lines(newline_pos, count)
134
+ difference = minimum_empty_lines - count
135
+ where_to_insert = range_between(newline_pos, newline_pos + 1)
136
+ lambda do |corrector|
137
+ corrector.insert_after(where_to_insert, "\n" * difference)
138
+ end
69
139
  end
70
140
  end
71
141
  end
@@ -0,0 +1,42 @@
1
+
2
+ # frozen_string_literal: true
3
+
4
+ module RuboCop
5
+ module Cop
6
+ module Style
7
+ # This cops checks if empty lines exist around the bodies of begin-end
8
+ # blocks.
9
+ #
10
+ # @example
11
+ #
12
+ # # good
13
+ #
14
+ # begin
15
+ # ...
16
+ # end
17
+ #
18
+ # # bad
19
+ #
20
+ # begin
21
+ #
22
+ # ...
23
+ #
24
+ # end
25
+ class EmptyLinesAroundBeginBody < Cop
26
+ include EmptyLinesAroundBody
27
+
28
+ KIND = '`begin`'.freeze
29
+
30
+ def on_kwbegin(node)
31
+ check(node, nil)
32
+ end
33
+
34
+ private
35
+
36
+ def style
37
+ :no_empty_lines
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # This cops checks if empty lines exist around the bodies of `begin`
7
+ # sections. This cop doesn't check empty lines at `begin` body
8
+ # beginning/end and around method definition body.
9
+ # `Style/EmptyLinesAroundBeginBody` or `Style/EmptyLinesAroundMethodBody`
10
+ # can be used for this purpose.
11
+ #
12
+ # @example
13
+ #
14
+ # # good
15
+ #
16
+ # begin
17
+ # do_something
18
+ # rescue
19
+ # do_something2
20
+ # else
21
+ # do_something3
22
+ # ensure
23
+ # do_something4
24
+ # end
25
+ #
26
+ # # good
27
+ #
28
+ # def foo
29
+ # do_something
30
+ # rescue
31
+ # do_something2
32
+ # end
33
+ #
34
+ # # bad
35
+ #
36
+ # begin
37
+ # do_something
38
+ #
39
+ # rescue
40
+ #
41
+ # do_something2
42
+ #
43
+ # else
44
+ #
45
+ # do_something3
46
+ #
47
+ # ensure
48
+ #
49
+ # do_something4
50
+ # end
51
+ #
52
+ # # bad
53
+ #
54
+ # def foo
55
+ # do_something
56
+ #
57
+ # rescue
58
+ #
59
+ # do_something2
60
+ # end
61
+ class EmptyLinesAroundExceptionHandlingKeywords < Cop
62
+ include EmptyLinesAroundBody
63
+ include OnMethodDef
64
+
65
+ MSG = 'Extra empty line detected %s the `%s`.'.freeze
66
+
67
+ def on_method_def(_node, _method_name, _args, body)
68
+ check_body(body)
69
+ end
70
+
71
+ def on_kwbegin(node)
72
+ body, = *node
73
+ check_body(body)
74
+ end
75
+
76
+ private
77
+
78
+ def check_body(node)
79
+ locations = keyword_locations(node)
80
+ locations.each do |loc|
81
+ line = loc.line
82
+ keyword = loc.source
83
+ # below the keyword
84
+ check_line(style, line, format(MSG, 'after', keyword), &:empty?)
85
+ # above the keyword
86
+ check_line(style,
87
+ line - 2,
88
+ format(MSG, 'before', keyword),
89
+ &:empty?)
90
+ end
91
+ end
92
+
93
+ def style
94
+ :no_empty_lines
95
+ end
96
+
97
+ def keyword_locations(node)
98
+ return [] unless node
99
+ case node.type
100
+ when :rescue
101
+ keyword_locations_in_rescue(node)
102
+ when :ensure
103
+ keyword_locations_in_ensure(node)
104
+ else
105
+ []
106
+ end
107
+ end
108
+
109
+ def keyword_locations_in_rescue(node)
110
+ _begin_body, *resbodies, _else_body = *node
111
+ [
112
+ node.loc.else,
113
+ *resbodies.map { |body| body.loc.keyword }
114
+ ].compact
115
+ end
116
+
117
+ def keyword_locations_in_ensure(node)
118
+ ensure_body, = *node
119
+ [
120
+ node.loc.keyword,
121
+ *keyword_locations(ensure_body)
122
+ ]
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -15,16 +15,15 @@ module RuboCop
15
15
  def_node_matcher :array_node, '(send (const nil :Array) :new)'
16
16
  def_node_matcher :hash_node, '(send (const nil :Hash) :new)'
17
17
  def_node_matcher :str_node, '(send (const nil :String) :new)'
18
+ def_node_matcher :array_with_block,
19
+ '(block (send (const nil :Array) :new) args _)'
20
+ def_node_matcher :hash_with_block,
21
+ '(block (send (const nil :Hash) :new) args _)'
18
22
 
19
23
  def on_send(node)
20
- array_node(node) { add_offense(node, :expression, ARR_MSG) }
24
+ add_offense(node, :expression, ARR_MSG) if offense_array_node?(node)
21
25
 
22
- hash_node(node) do
23
- # If Hash.new takes a block, it can't be changed to {}.
24
- return if node.parent && node.parent.block_type?
25
-
26
- add_offense(node, :expression, HASH_MSG)
27
- end
26
+ add_offense(node, :expression, HASH_MSG) if offense_hash_node?(node)
28
27
 
29
28
  str_node(node) do
30
29
  return if frozen_string_literals_enabled?
@@ -77,12 +76,21 @@ module RuboCop
77
76
  end
78
77
  end
79
78
 
79
+ def offense_array_node?(node)
80
+ array_node(node) && !array_with_block(node.parent)
81
+ end
82
+
83
+ def offense_hash_node?(node)
84
+ # If Hash.new takes a block, it can't be changed to {}.
85
+ hash_node(node) && !hash_with_block(node.parent)
86
+ end
87
+
80
88
  def correction(node)
81
- if array_node(node)
89
+ if offense_array_node?(node)
82
90
  '[]'
83
91
  elsif str_node(node)
84
92
  preferred_string_literal
85
- elsif hash_node(node)
93
+ elsif offense_hash_node?(node)
86
94
  if first_argument_unparenthesized?(node)
87
95
  # `some_method {}` is not same as `some_method Hash.new`
88
96
  # because the braces are interpreted as a block. We will have
@@ -5,7 +5,10 @@ module RuboCop
5
5
  module Style
6
6
  # This cop checks for Windows-style line endings in the source code.
7
7
  class EndOfLine < Cop
8
- MSG = 'Carriage return character detected.'.freeze
8
+ include ConfigurableEnforcedStyle
9
+
10
+ MSG_DETECTED = 'Carriage return character detected.'.freeze
11
+ MSG_MISSING = 'Carriage return character missing.'.freeze
9
12
 
10
13
  def investigate(processed_source)
11
14
  last_token = processed_source.tokens.last
@@ -14,16 +17,35 @@ module RuboCop
14
17
 
15
18
  processed_source.raw_source.each_line.with_index do |line, index|
16
19
  break if index >= last_line
17
- next unless line =~ /\r$/
20
+ msg = offense_message(line)
21
+ next unless msg
22
+ next if unimportant_missing_cr?(index, last_line, line)
18
23
 
19
24
  range =
20
25
  source_range(processed_source.buffer, index + 1, 0, line.length)
21
- add_offense(nil, range, MSG)
26
+ add_offense(nil, range, msg)
22
27
  # Usually there will be carriage return characters on all or none
23
28
  # of the lines in a file, so we report only one offense.
24
29
  break
25
30
  end
26
31
  end
32
+
33
+ # If there is no LF on the last line, we don't care if there's no CR.
34
+ def unimportant_missing_cr?(index, last_line, line)
35
+ style == :crlf && index == last_line - 1 && line !~ /\n$/
36
+ end
37
+
38
+ def offense_message(line)
39
+ effective_style = if style == :native
40
+ Platform.windows? ? :crlf : :lf
41
+ else
42
+ style
43
+ end
44
+ case effective_style
45
+ when :lf then MSG_DETECTED if line =~ /\r$/
46
+ else MSG_MISSING if line !~ /\r$/
47
+ end
48
+ end
27
49
  end
28
50
  end
29
51
  end
@@ -91,7 +91,7 @@ module RuboCop
91
91
  return nil if node.nil?
92
92
  name = namespace.pop
93
93
 
94
- on_node([:class, :module, :casgn], node) do |child|
94
+ on_node(%i(class module casgn), node) do |child|
95
95
  next unless (const = child.defined_module)
96
96
 
97
97
  const_namespace, const_name = *const
@@ -27,7 +27,7 @@ module RuboCop
27
27
  'multi-line method argument list.'.freeze
28
28
 
29
29
  def on_send(node)
30
- _receiver, _name, *args = *node
30
+ args = node.arguments
31
31
 
32
32
  # If there is a trailing hash arg without explicit braces, like this:
33
33
  #
@@ -23,23 +23,17 @@ module RuboCop
23
23
  include ConfigurableEnforcedStyle
24
24
 
25
25
  def on_send(node)
26
- _receiver, method_name, *args = *node
27
- return if args.empty?
28
- return if operator?(method_name)
29
-
30
- base_indentation = if special_inner_call_indentation?(node)
31
- column_of(base_range(node, args.first))
32
- else
33
- previous_code_line(args.first.loc.line) =~ /\S/
34
- end
35
- check_alignment([args.first],
36
- base_indentation + configured_indentation_width)
26
+ return if !node.arguments? || node.operator_method?
27
+
28
+ indent = base_indentation(node) + configured_indentation_width
29
+
30
+ check_alignment([node.first_argument], indent)
37
31
  end
38
32
 
39
33
  private
40
34
 
41
35
  def message(arg_node)
42
- return 'Bad indentation of the first parameter.' if arg_node.nil?
36
+ return 'Bad indentation of the first parameter.' unless arg_node
43
37
 
44
38
  send_node = arg_node.parent
45
39
  text = base_range(send_node, arg_node).source.strip
@@ -53,18 +47,22 @@ module RuboCop
53
47
  format('Indent the first parameter one step more than %s.', base)
54
48
  end
55
49
 
50
+ def base_indentation(node)
51
+ if special_inner_call_indentation?(node)
52
+ column_of(base_range(node, node.first_argument))
53
+ else
54
+ previous_code_line(node.first_argument.loc.line) =~ /\S/
55
+ end
56
+ end
57
+
56
58
  def special_inner_call_indentation?(node)
57
59
  return false if style == :consistent
58
60
 
59
61
  parent = node.parent
60
- return false unless parent
61
- return false unless parent.send_type?
62
-
63
- _receiver, method_name, *_args = *parent
64
- # :[]= is a send node, but we want to treat it as an assignment.
65
- return false if method_name == :[]=
66
62
 
67
- return false if !parentheses?(parent) &&
63
+ return false unless parent && parent.send_type? &&
64
+ !parent.method?(:[]=)
65
+ return false if !parent.parenthesized? &&
68
66
  style == :special_for_inner_method_call_in_parentheses
69
67
 
70
68
  # The node must begin inside the parent, otherwise node is the first