rubocop 0.70.0 → 0.75.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (274) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -10
  3. data/bin/console +1 -0
  4. data/config/default.yml +91 -494
  5. data/lib/rubocop.rb +16 -54
  6. data/lib/rubocop/ast/builder.rb +2 -0
  7. data/lib/rubocop/ast/node.rb +9 -15
  8. data/lib/rubocop/ast/node/float_node.rb +12 -0
  9. data/lib/rubocop/ast/node/int_node.rb +12 -0
  10. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +4 -4
  11. data/lib/rubocop/ast/node/mixin/numeric_node.rb +21 -0
  12. data/lib/rubocop/ast/node/resbody_node.rb +1 -6
  13. data/lib/rubocop/ast/traversal.rb +3 -3
  14. data/lib/rubocop/cached_data.rb +1 -1
  15. data/lib/rubocop/comment_config.rb +3 -2
  16. data/lib/rubocop/config.rb +21 -508
  17. data/lib/rubocop/config_loader.rb +22 -4
  18. data/lib/rubocop/config_loader_resolver.rb +2 -8
  19. data/lib/rubocop/config_obsoletion.rb +213 -0
  20. data/lib/rubocop/config_validator.rb +239 -0
  21. data/lib/rubocop/cop/autocorrect_logic.rb +71 -1
  22. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -1
  23. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  24. data/lib/rubocop/cop/commissioner.rb +3 -9
  25. data/lib/rubocop/cop/cop.rb +39 -12
  26. data/lib/rubocop/cop/corrector.rb +2 -3
  27. data/lib/rubocop/cop/correctors/alignment_corrector.rb +43 -17
  28. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +2 -2
  29. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  30. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  31. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  32. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +1 -1
  33. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +55 -0
  34. data/lib/rubocop/cop/generator.rb +4 -4
  35. data/lib/rubocop/cop/generator/configuration_injector.rb +9 -4
  36. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  37. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +2 -2
  38. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  39. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +2 -2
  40. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  41. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +2 -2
  42. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -2
  43. data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
  44. data/lib/rubocop/cop/layout/class_structure.rb +2 -2
  45. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
  46. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +3 -1
  47. data/lib/rubocop/cop/layout/extra_spacing.rb +14 -59
  48. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -0
  49. data/lib/rubocop/cop/layout/indent_assignment.rb +9 -1
  50. data/lib/rubocop/cop/layout/indent_first_argument.rb +7 -3
  51. data/lib/rubocop/cop/layout/indent_first_parameter.rb +7 -3
  52. data/lib/rubocop/cop/layout/indent_heredoc.rb +4 -4
  53. data/lib/rubocop/cop/layout/indentation_consistency.rb +13 -12
  54. data/lib/rubocop/cop/layout/indentation_width.rb +28 -10
  55. data/lib/rubocop/cop/layout/leading_comment_space.rb +28 -0
  56. data/lib/rubocop/cop/layout/multiline_block_layout.rb +24 -2
  57. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +2 -0
  58. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +18 -4
  59. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +5 -1
  60. data/lib/rubocop/cop/layout/space_around_operators.rb +42 -23
  61. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +1 -1
  62. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +21 -2
  63. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +24 -40
  64. data/lib/rubocop/cop/layout/tab.rb +10 -22
  65. data/lib/rubocop/cop/lint/assignment_in_condition.rb +17 -4
  66. data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -1
  67. data/lib/rubocop/cop/lint/debugger.rb +4 -6
  68. data/lib/rubocop/cop/lint/duplicate_methods.rb +3 -3
  69. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  70. data/lib/rubocop/cop/lint/empty_interpolation.rb +4 -4
  71. data/lib/rubocop/cop/lint/erb_new_arguments.rb +57 -1
  72. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -37
  73. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  74. data/lib/rubocop/cop/lint/inherit_exception.rb +1 -1
  75. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +7 -8
  76. data/lib/rubocop/cop/lint/multiple_compare.rb +1 -1
  77. data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -3
  78. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  79. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  80. data/lib/rubocop/cop/lint/number_conversion.rb +4 -4
  81. data/lib/rubocop/cop/lint/rand_one.rb +1 -1
  82. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  83. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  84. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +5 -5
  85. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -1
  86. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +91 -0
  87. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +6 -6
  88. data/lib/rubocop/cop/lint/unified_integer.rb +1 -1
  89. data/lib/rubocop/cop/lint/unneeded_cop_disable_directive.rb +1 -1
  90. data/lib/rubocop/cop/lint/unneeded_require_statement.rb +1 -1
  91. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +7 -2
  92. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  93. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -1
  94. data/lib/rubocop/cop/lint/uri_regexp.rb +2 -2
  95. data/lib/rubocop/cop/lint/useless_access_modifier.rb +6 -6
  96. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  97. data/lib/rubocop/cop/message_annotator.rb +16 -7
  98. data/lib/rubocop/cop/metrics/class_length.rb +1 -1
  99. data/lib/rubocop/cop/metrics/line_length.rb +6 -0
  100. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  101. data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
  102. data/lib/rubocop/cop/migration/department_name.rb +44 -0
  103. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  104. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  105. data/lib/rubocop/cop/mixin/documentation_comment.rb +0 -2
  106. data/lib/rubocop/cop/mixin/empty_parameter.rb +1 -1
  107. data/lib/rubocop/cop/mixin/enforce_superclass.rb +4 -4
  108. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  109. data/lib/rubocop/cop/mixin/hash_alignment.rb +4 -0
  110. data/lib/rubocop/cop/mixin/interpolation.rb +27 -0
  111. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  112. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -3
  113. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +87 -0
  114. data/lib/rubocop/cop/mixin/safe_mode.rb +2 -0
  115. data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -5
  116. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  117. data/lib/rubocop/cop/naming/constant_name.rb +2 -2
  118. data/lib/rubocop/cop/naming/method_name.rb +12 -1
  119. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  120. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +20 -22
  121. data/lib/rubocop/cop/naming/variable_name.rb +1 -0
  122. data/lib/rubocop/cop/offense.rb +18 -7
  123. data/lib/rubocop/cop/registry.rb +22 -1
  124. data/lib/rubocop/cop/security/eval.rb +1 -1
  125. data/lib/rubocop/cop/security/json_load.rb +1 -1
  126. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  127. data/lib/rubocop/cop/security/open.rb +1 -1
  128. data/lib/rubocop/cop/security/yaml_load.rb +1 -1
  129. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
  130. data/lib/rubocop/cop/style/alias.rb +1 -1
  131. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  132. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +29 -10
  133. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  134. data/lib/rubocop/cop/style/colon_method_call.rb +1 -1
  135. data/lib/rubocop/cop/style/commented_keyword.rb +16 -30
  136. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -9
  137. data/lib/rubocop/cop/style/constant_visibility.rb +14 -3
  138. data/lib/rubocop/cop/style/date_time.rb +3 -3
  139. data/lib/rubocop/cop/style/dir.rb +1 -1
  140. data/lib/rubocop/cop/style/documentation_method.rb +1 -1
  141. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +55 -0
  142. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  143. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  144. data/lib/rubocop/cop/style/eval_with_location.rb +2 -2
  145. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  146. data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -3
  147. data/lib/rubocop/cop/style/float_division.rb +94 -0
  148. data/lib/rubocop/cop/style/format_string.rb +13 -9
  149. data/lib/rubocop/cop/style/format_string_token.rb +10 -40
  150. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +18 -33
  151. data/lib/rubocop/cop/style/guard_clause.rb +39 -10
  152. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  153. data/lib/rubocop/cop/style/if_inside_else.rb +42 -0
  154. data/lib/rubocop/cop/style/if_unless_modifier.rb +51 -15
  155. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  156. data/lib/rubocop/cop/style/inverse_methods.rb +2 -2
  157. data/lib/rubocop/cop/style/lambda.rb +0 -2
  158. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +12 -6
  159. data/lib/rubocop/cop/style/min_max.rb +1 -1
  160. data/lib/rubocop/cop/style/mixin_usage.rb +12 -2
  161. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  162. data/lib/rubocop/cop/style/multiline_when_then.rb +55 -0
  163. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  164. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  165. data/lib/rubocop/cop/style/nested_modifier.rb +18 -2
  166. data/lib/rubocop/cop/style/numeric_predicate.rb +3 -3
  167. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  168. data/lib/rubocop/cop/style/or_assignment.rb +8 -3
  169. data/lib/rubocop/cop/style/parentheses_around_condition.rb +15 -1
  170. data/lib/rubocop/cop/style/random_with_offset.rb +6 -6
  171. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -2
  172. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  173. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  174. data/lib/rubocop/cop/style/redundant_parentheses.rb +15 -6
  175. data/lib/rubocop/cop/style/redundant_self.rb +18 -1
  176. data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -1
  177. data/lib/rubocop/cop/style/rescue_modifier.rb +24 -0
  178. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  179. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  180. data/lib/rubocop/cop/style/safe_navigation.rb +11 -2
  181. data/lib/rubocop/cop/style/sample.rb +1 -1
  182. data/lib/rubocop/cop/style/single_line_methods.rb +8 -1
  183. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  184. data/lib/rubocop/cop/style/string_hash_keys.rb +2 -2
  185. data/lib/rubocop/cop/style/strip.rb +1 -1
  186. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -3
  187. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  188. data/lib/rubocop/cop/style/ternary_parentheses.rb +32 -3
  189. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -0
  190. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +4 -6
  191. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  192. data/lib/rubocop/cop/style/unneeded_sort.rb +1 -1
  193. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  194. data/lib/rubocop/cop/style/variable_interpolation.rb +6 -16
  195. data/lib/rubocop/cop/style/word_array.rb +2 -2
  196. data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -6
  197. data/lib/rubocop/cop/team.rb +15 -14
  198. data/lib/rubocop/cop/utils/format_string.rb +128 -0
  199. data/lib/rubocop/cop/variable_force/variable.rb +15 -2
  200. data/lib/rubocop/core_ext/string.rb +0 -24
  201. data/lib/rubocop/error.rb +23 -0
  202. data/lib/rubocop/formatter/emacs_style_formatter.rb +8 -5
  203. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  204. data/lib/rubocop/formatter/pacman_formatter.rb +80 -0
  205. data/lib/rubocop/formatter/simple_text_formatter.rb +9 -1
  206. data/lib/rubocop/formatter/tap_formatter.rb +9 -1
  207. data/lib/rubocop/magic_comment.rb +4 -0
  208. data/lib/rubocop/node_pattern.rb +86 -7
  209. data/lib/rubocop/options.rb +18 -2
  210. data/lib/rubocop/path_util.rb +1 -1
  211. data/lib/rubocop/processed_source.rb +9 -1
  212. data/lib/rubocop/rspec/cop_helper.rb +0 -1
  213. data/lib/rubocop/rspec/expect_offense.rb +4 -1
  214. data/lib/rubocop/rspec/shared_contexts.rb +12 -17
  215. data/lib/rubocop/rspec/support.rb +0 -1
  216. data/lib/rubocop/runner.rb +20 -15
  217. data/lib/rubocop/target_finder.rb +6 -4
  218. data/lib/rubocop/version.rb +1 -1
  219. data/lib/rubocop/yaml_duplication_checker.rb +8 -2
  220. metadata +16 -70
  221. data/lib/rubocop/cop/mixin/ignored_method_patterns.rb +0 -19
  222. data/lib/rubocop/cop/mixin/target_rails_version.rb +0 -16
  223. data/lib/rubocop/cop/rails/action_filter.rb +0 -117
  224. data/lib/rubocop/cop/rails/active_record_aliases.rb +0 -48
  225. data/lib/rubocop/cop/rails/active_record_override.rb +0 -82
  226. data/lib/rubocop/cop/rails/active_support_aliases.rb +0 -69
  227. data/lib/rubocop/cop/rails/application_job.rb +0 -40
  228. data/lib/rubocop/cop/rails/application_record.rb +0 -40
  229. data/lib/rubocop/cop/rails/assert_not.rb +0 -44
  230. data/lib/rubocop/cop/rails/belongs_to.rb +0 -102
  231. data/lib/rubocop/cop/rails/blank.rb +0 -164
  232. data/lib/rubocop/cop/rails/bulk_change_table.rb +0 -289
  233. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +0 -91
  234. data/lib/rubocop/cop/rails/date.rb +0 -161
  235. data/lib/rubocop/cop/rails/delegate.rb +0 -132
  236. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +0 -37
  237. data/lib/rubocop/cop/rails/dynamic_find_by.rb +0 -91
  238. data/lib/rubocop/cop/rails/enum_uniqueness.rb +0 -45
  239. data/lib/rubocop/cop/rails/environment_comparison.rb +0 -68
  240. data/lib/rubocop/cop/rails/exit.rb +0 -67
  241. data/lib/rubocop/cop/rails/file_path.rb +0 -108
  242. data/lib/rubocop/cop/rails/find_by.rb +0 -55
  243. data/lib/rubocop/cop/rails/find_each.rb +0 -51
  244. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +0 -25
  245. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +0 -106
  246. data/lib/rubocop/cop/rails/http_positional_arguments.rb +0 -117
  247. data/lib/rubocop/cop/rails/http_status.rb +0 -179
  248. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +0 -94
  249. data/lib/rubocop/cop/rails/inverse_of.rb +0 -246
  250. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +0 -175
  251. data/lib/rubocop/cop/rails/link_to_blank.rb +0 -98
  252. data/lib/rubocop/cop/rails/not_null_column.rb +0 -67
  253. data/lib/rubocop/cop/rails/output.rb +0 -49
  254. data/lib/rubocop/cop/rails/output_safety.rb +0 -99
  255. data/lib/rubocop/cop/rails/pluralization_grammar.rb +0 -107
  256. data/lib/rubocop/cop/rails/presence.rb +0 -124
  257. data/lib/rubocop/cop/rails/present.rb +0 -153
  258. data/lib/rubocop/cop/rails/read_write_attribute.rb +0 -74
  259. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +0 -111
  260. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +0 -136
  261. data/lib/rubocop/cop/rails/reflection_class_name.rb +0 -37
  262. data/lib/rubocop/cop/rails/refute_methods.rb +0 -76
  263. data/lib/rubocop/cop/rails/relative_date_constant.rb +0 -93
  264. data/lib/rubocop/cop/rails/request_referer.rb +0 -56
  265. data/lib/rubocop/cop/rails/reversible_migration.rb +0 -286
  266. data/lib/rubocop/cop/rails/safe_navigation.rb +0 -87
  267. data/lib/rubocop/cop/rails/save_bang.rb +0 -316
  268. data/lib/rubocop/cop/rails/scope_args.rb +0 -29
  269. data/lib/rubocop/cop/rails/skips_model_validations.rb +0 -87
  270. data/lib/rubocop/cop/rails/time_zone.rb +0 -238
  271. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +0 -105
  272. data/lib/rubocop/cop/rails/unknown_env.rb +0 -63
  273. data/lib/rubocop/cop/rails/validation.rb +0 -109
  274. data/lib/rubocop/rspec/shared_examples.rb +0 -59
@@ -132,7 +132,7 @@ module RuboCop
132
132
  line, col = line_and_column_for(token)
133
133
  return true if col == -1
134
134
 
135
- processed_source.lines[line][0..col].delete(' ').empty?
135
+ processed_source.lines[line][0..col] !~ /\S/
136
136
  end
137
137
 
138
138
  def index_for(node, token)
@@ -84,6 +84,13 @@ module RuboCop
84
84
  def on_block(node)
85
85
  return if node.keywords?
86
86
 
87
+ # Do not register an offense for multi-line empty braces. That means
88
+ # preventing auto-correction to single-line empty braces. It will
89
+ # conflict with auto-correction by `Layout/SpaceInsideBlockBraces` cop
90
+ # if auto-corrected to a single-line empty braces.
91
+ # See: https://github.com/rubocop-hq/rubocop/issues/7363
92
+ return if node.body.nil? && node.multiline?
93
+
87
94
  left_brace = node.loc.begin
88
95
  right_brace = node.loc.end
89
96
 
@@ -130,7 +137,8 @@ module RuboCop
130
137
  args_delimiter = node.arguments.loc.begin # Can be ( | or nil.
131
138
 
132
139
  check_left_brace(inner, node.loc.begin, args_delimiter)
133
- check_right_brace(inner, node.loc.end, node.single_line?)
140
+ check_right_brace(inner, node.loc.begin, node.loc.end,
141
+ node.single_line?)
134
142
  end
135
143
 
136
144
  def check_left_brace(inner, left_brace, args_delimiter)
@@ -141,15 +149,26 @@ module RuboCop
141
149
  end
142
150
  end
143
151
 
144
- def check_right_brace(inner, right_brace, single_line)
152
+ def check_right_brace(inner, left_brace, right_brace, single_line)
145
153
  if single_line && inner =~ /\S$/
146
154
  no_space(right_brace.begin_pos, right_brace.end_pos,
147
155
  'Space missing inside }.')
148
156
  else
157
+ return if multiline_block?(left_brace, right_brace) &&
158
+ aligned_braces?(left_brace, right_brace)
159
+
149
160
  space_inside_right_brace(right_brace)
150
161
  end
151
162
  end
152
163
 
164
+ def multiline_block?(left_brace, right_brace)
165
+ left_brace.first_line != right_brace.first_line
166
+ end
167
+
168
+ def aligned_braces?(left_brace, right_brace)
169
+ left_brace.first_line == right_brace.last_column
170
+ end
171
+
153
172
  def no_space_inside_left_brace(left_brace, args_delimiter)
154
173
  if pipe?(args_delimiter)
155
174
  if left_brace.end_pos == args_delimiter.begin_pos &&
@@ -19,61 +19,45 @@ module RuboCop
19
19
  # # good
20
20
  # var = "This is the #{ space } example"
21
21
  class SpaceInsideStringInterpolation < Cop
22
+ include Interpolation
23
+ include SurroundingSpace
22
24
  include ConfigurableEnforcedStyle
23
25
  include RangeHelp
24
26
 
25
27
  NO_SPACE_MSG = 'Space inside string interpolation detected.'
26
- SPACE_MSG = 'Missing space around string interpolation detected.'
28
+ SPACE_MSG = 'Missing space inside string interpolation detected.'
27
29
 
28
- def on_dstr(node)
29
- each_style_violation(node) do |final_node|
30
- add_offense(final_node)
31
- end
32
- end
30
+ def on_interpolation(begin_node)
31
+ return if begin_node.multiline?
33
32
 
34
- def autocorrect(node)
35
- new_source = style == :no_space ? node.source : " #{node.source} "
36
- lambda do |corrector|
37
- corrector.replace(
38
- range_with_surrounding_space(range: node.source_range),
39
- new_source
40
- )
33
+ delims = delimiters(begin_node)
34
+ return if empty_brackets?(*delims)
35
+
36
+ if style == :no_space
37
+ no_space_offenses(begin_node, *delims, NO_SPACE_MSG)
38
+ else
39
+ space_offenses(begin_node, *delims, SPACE_MSG)
41
40
  end
42
41
  end
43
42
 
44
- private
45
-
46
- def each_style_violation(node)
47
- node.each_child_node(:begin) do |begin_node|
48
- final_node = begin_node.children.last
49
- next unless final_node
43
+ def autocorrect(begin_node)
44
+ lambda do |corrector|
45
+ delims = delimiters(begin_node)
50
46
 
51
- if style == :no_space && space_on_any_side?(final_node)
52
- yield final_node
53
- elsif style == :space && !space_on_each_side?(final_node)
54
- yield final_node
47
+ if style == :no_space
48
+ SpaceCorrector.remove_space(processed_source, corrector, *delims)
49
+ else
50
+ SpaceCorrector.add_space(processed_source, corrector, *delims)
55
51
  end
56
52
  end
57
53
  end
58
54
 
59
- def message(_node)
60
- style == :no_space ? NO_SPACE_MSG : SPACE_MSG
61
- end
62
-
63
- def space_on_any_side?(node)
64
- interp = node.source_range
65
- interp_with_surrounding_space =
66
- range_with_surrounding_space(range: interp)
67
-
68
- interp_with_surrounding_space != interp
69
- end
70
-
71
- def space_on_each_side?(node)
72
- interp = node.source_range
73
- interp_with_surrounding_space =
74
- range_with_surrounding_space(range: interp)
55
+ private
75
56
 
76
- interp_with_surrounding_space.source == " #{interp.source} "
57
+ def delimiters(begin_node)
58
+ left = processed_source.tokens[index_of_first_token(begin_node)]
59
+ right = processed_source.tokens[index_of_last_token(begin_node)]
60
+ [left, right]
77
61
  end
78
62
  end
79
63
  end
@@ -30,16 +30,13 @@ module RuboCop
30
30
  str_ranges = string_literal_ranges(processed_source.ast)
31
31
 
32
32
  processed_source.lines.each.with_index(1) do |line, lineno|
33
- match = line.match(/^([^\t]*)\t+/)
33
+ match = line.match(/\t+/)
34
34
  next unless match
35
35
 
36
- prefix = match.captures[0]
37
- col = prefix.length
38
- next if in_string_literal?(str_ranges, lineno, col)
39
-
40
36
  range = source_range(processed_source.buffer,
41
37
  lineno,
42
- col...match.end(0))
38
+ match.begin(0)...match.end(0))
39
+ next if in_string_literal?(str_ranges, range)
43
40
 
44
41
  add_offense(range, location: range)
45
42
  end
@@ -54,16 +51,9 @@ module RuboCop
54
51
 
55
52
  private
56
53
 
57
- # rubocop:disable Metrics/CyclomaticComplexity
58
- def in_string_literal?(ranges, line, col)
59
- ranges.any? do |range|
60
- (range.line == line && range.column <= col) ||
61
- (range.line < line && line < range.last_line) ||
62
- (range.line != line && range.last_line == line &&
63
- range.last_column >= col)
64
- end
54
+ def in_string_literal?(ranges, tabs_range)
55
+ ranges.any? { |range| range.contains?(tabs_range) }
65
56
  end
66
- # rubocop:enable Metrics/CyclomaticComplexity
67
57
 
68
58
  def string_literal_ranges(ast)
69
59
  # which lines start inside a string literal?
@@ -72,13 +62,11 @@ module RuboCop
72
62
  ast.each_node(:str, :dstr).each_with_object(Set.new) do |str, ranges|
73
63
  loc = str.location
74
64
 
75
- range = if str.heredoc?
76
- loc.heredoc_body
77
- else
78
- loc.expression
79
- end
80
-
81
- ranges << range
65
+ if str.heredoc?
66
+ ranges << loc.heredoc_body
67
+ elsif loc.respond_to?(:begin) && loc.begin
68
+ ranges << loc.expression
69
+ end
82
70
  end
83
71
  end
84
72
  end
@@ -6,21 +6,34 @@ module RuboCop
6
6
  # This cop checks for assignments in the conditions of
7
7
  # if/while/until.
8
8
  #
9
- # @example
9
+ # `AllowSafeAssignment` option for safe assignment.
10
+ # By safe assignment we mean putting parentheses around
11
+ # an assignment to indicate "I know I'm using an assignment
12
+ # as a condition. It's not a mistake."
10
13
  #
14
+ # @example
11
15
  # # bad
12
- #
13
16
  # if some_var = true
14
17
  # do_something
15
18
  # end
16
19
  #
17
- # @example
20
+ # # good
21
+ # if some_var == true
22
+ # do_something
23
+ # end
18
24
  #
25
+ # @example AllowSafeAssignment: true (default)
19
26
  # # good
27
+ # if (some_var = true)
28
+ # do_something
29
+ # end
20
30
  #
21
- # if some_var == true
31
+ # @example AllowSafeAssignment: false
32
+ # # bad
33
+ # if (some_var = true)
22
34
  # do_something
23
35
  # end
36
+ #
24
37
  class AssignmentInCondition < Cop
25
38
  include SafeAssignment
26
39
 
@@ -18,7 +18,7 @@ module RuboCop
18
18
  MSG = '`%<double_colon>sBigDecimal.new()` is deprecated. ' \
19
19
  'Use `%<double_colon>sBigDecimal()` instead.'
20
20
 
21
- def_node_matcher :big_decimal_new, <<-PATTERN
21
+ def_node_matcher :big_decimal_new, <<~PATTERN
22
22
  (send
23
23
  (const ${nil? cbase} :BigDecimal) :new ...)
24
24
  PATTERN
@@ -35,15 +35,15 @@ module RuboCop
35
35
  class Debugger < Cop
36
36
  MSG = 'Remove debugger entry point `%<source>s`.'
37
37
 
38
- def_node_matcher :kernel?, <<-PATTERN
38
+ def_node_matcher :kernel?, <<~PATTERN
39
39
  {
40
40
  (const nil? :Kernel)
41
41
  (const (cbase) :Kernel)
42
42
  }
43
43
  PATTERN
44
44
 
45
- def_node_matcher :debugger_call?, <<-PATTERN
46
- {(send {nil? #kernel?} {:debugger :byebug} ...)
45
+ def_node_matcher :debugger_call?, <<~PATTERN
46
+ {(send {nil? #kernel?} {:debugger :byebug :remote_byebug} ...)
47
47
  (send (send {#kernel? nil?} :binding)
48
48
  {:pry :remote_pry :pry_remote} ...)
49
49
  (send (const {nil? (cbase)} :Pry) :rescue ...)
@@ -52,12 +52,10 @@ module RuboCop
52
52
  :save_screenshot} ...)}
53
53
  PATTERN
54
54
 
55
- def_node_matcher :binding_irb_call?, <<-PATTERN
55
+ def_node_matcher :binding_irb_call?, <<~PATTERN
56
56
  (send (send {#kernel? nil?} :binding) :irb ...)
57
57
  PATTERN
58
58
 
59
- def_node_matcher :pry_rescue?, '(send (const nil? :Pry) :rescue ...)'
60
-
61
59
  def on_send(node)
62
60
  return unless debugger_call?(node) || binding_irb?(node)
63
61
 
@@ -79,7 +79,7 @@ module RuboCop
79
79
  end
80
80
  end
81
81
 
82
- def_node_matcher :method_alias?, <<-PATTERN
82
+ def_node_matcher :method_alias?, <<~PATTERN
83
83
  (alias (sym $_name) sym)
84
84
  PATTERN
85
85
 
@@ -91,11 +91,11 @@ module RuboCop
91
91
  found_instance_method(node, name)
92
92
  end
93
93
 
94
- def_node_matcher :alias_method?, <<-PATTERN
94
+ def_node_matcher :alias_method?, <<~PATTERN
95
95
  (send nil? :alias_method (sym $_name) _)
96
96
  PATTERN
97
97
 
98
- def_node_matcher :attr?, <<-PATTERN
98
+ def_node_matcher :attr?, <<~PATTERN
99
99
  (send nil? ${:attr_reader :attr_writer :attr_accessor :attr} $...)
100
100
  PATTERN
101
101
 
@@ -24,7 +24,7 @@ module RuboCop
24
24
  class EachWithObjectArgument < Cop
25
25
  MSG = 'The argument to each_with_object can not be immutable.'
26
26
 
27
- def_node_matcher :each_with_object?, <<-PATTERN
27
+ def_node_matcher :each_with_object?, <<~PATTERN
28
28
  ({send csend} _ :each_with_object $_)
29
29
  PATTERN
30
30
 
@@ -17,12 +17,12 @@ module RuboCop
17
17
  #
18
18
  # "result is #{some_result}"
19
19
  class EmptyInterpolation < Cop
20
+ include Interpolation
21
+
20
22
  MSG = 'Empty interpolation detected.'
21
23
 
22
- def on_dstr(node)
23
- node.each_child_node(:begin) do |begin_node|
24
- add_offense(begin_node) if begin_node.children.empty?
25
- end
24
+ def on_interpolation(begin_node)
25
+ add_offense(begin_node) if begin_node.children.empty?
26
26
  end
27
27
 
28
28
  def autocorrect(node)
@@ -61,6 +61,7 @@ module RuboCop
61
61
  #
62
62
  class ErbNewArguments < Cop
63
63
  extend TargetRubyVersion
64
+ include RangeHelp
64
65
 
65
66
  minimum_target_ruby_version 2.6
66
67
 
@@ -76,7 +77,7 @@ module RuboCop
76
77
  '`ERB.new(str, eoutvar: %<arg_value>s)` instead.'
77
78
  ].freeze
78
79
 
79
- def_node_matcher :erb_new_with_non_keyword_arguments, <<-PATTERN
80
+ def_node_matcher :erb_new_with_non_keyword_arguments, <<~PATTERN
80
81
  (send
81
82
  (const {nil? cbase} :ERB) :new $...)
82
83
  PATTERN
@@ -97,10 +98,65 @@ module RuboCop
97
98
  end
98
99
  end
99
100
 
101
+ def autocorrect(node)
102
+ str_arg = node.arguments[0].source
103
+
104
+ kwargs = build_kwargs(node)
105
+ overridden_kwargs = override_by_legacy_args(kwargs, node)
106
+
107
+ good_arguments = [
108
+ str_arg, overridden_kwargs
109
+ ].flatten.compact.join(', ')
110
+
111
+ lambda do |corrector|
112
+ corrector.replace(arguments_range(node), good_arguments)
113
+ end
114
+ end
115
+
116
+ private
117
+
100
118
  def correct_arguments?(arguments)
101
119
  arguments.size == 1 ||
102
120
  arguments.size == 2 && arguments[1].hash_type?
103
121
  end
122
+
123
+ def build_kwargs(node)
124
+ return [nil, nil] unless node.arguments.last.hash_type?
125
+
126
+ trim_mode_arg, eoutvar_arg = nil
127
+
128
+ node.arguments.last.pairs.each do |pair|
129
+ case pair.key.source
130
+ when 'trim_mode'
131
+ trim_mode_arg = "trim_mode: #{pair.value.source}"
132
+ when 'eoutvar'
133
+ eoutvar_arg = "eoutvar: #{pair.value.source}"
134
+ end
135
+ end
136
+
137
+ [trim_mode_arg, eoutvar_arg]
138
+ end
139
+
140
+ def override_by_legacy_args(kwargs, node)
141
+ overridden_kwargs = kwargs.dup
142
+
143
+ if node.arguments[2]
144
+ overridden_kwargs[0] = "trim_mode: #{node.arguments[2].source}"
145
+ end
146
+
147
+ if node.arguments[3] && !node.arguments[3].hash_type?
148
+ overridden_kwargs[1] = "eoutvar: #{node.arguments[3].source}"
149
+ end
150
+
151
+ overridden_kwargs
152
+ end
153
+
154
+ def arguments_range(node)
155
+ arguments = node.arguments
156
+
157
+ range_between(arguments.first.source_range.begin_pos,
158
+ arguments.last.source_range.end_pos)
159
+ end
104
160
  end
105
161
  end
106
162
  end
@@ -22,16 +22,10 @@ module RuboCop
22
22
  # http://rubular.com/r/CvpbxkcTzy
23
23
  MSG = "Number of arguments (%<arg_num>i) to `%<method>s` doesn't " \
24
24
  'match the number of fields (%<field_num>i).'
25
- FIELD_REGEX =
26
- /(%(([\s#+-0\*]*)(\d*)?(\.\d+)?[bBdiouxXeEfgGaAcps]|%))/.freeze
27
- NAMED_FIELD_REGEX = /%\{[_a-zA-Z][_a-zA-Z]+\}/.freeze
25
+
28
26
  KERNEL = 'Kernel'
29
27
  SHOVEL = '<<'
30
- PERCENT = '%'
31
- PERCENT_PERCENT = '%%'
32
- DIGIT_DOLLAR_FLAG = /%(\d+)\$/.freeze
33
28
  STRING_TYPES = %i[str dstr].freeze
34
- NAMED_INTERPOLATION = /%(?:<\w+>|\{\w+\})/.freeze
35
29
 
36
30
  def on_send(node)
37
31
  return unless offending_node?(node)
@@ -44,7 +38,7 @@ module RuboCop
44
38
  def offending_node?(node)
45
39
  return false unless called_on_string?(node)
46
40
  return false unless method_with_format_args?(node)
47
- return false if named_mode?(node) || splat_args?(node)
41
+ return false if splat_args?(node)
48
42
 
49
43
  num_of_format_args, num_of_expected_fields = count_matches(node)
50
44
 
@@ -61,7 +55,7 @@ module RuboCop
61
55
  end
62
56
  end
63
57
 
64
- def_node_matcher :called_on_string?, <<-PATTERN
58
+ def_node_matcher :called_on_string?, <<~PATTERN
65
59
  {(send {nil? const_type?} _ (str _) ...)
66
60
  (send (str ...) ...)}
67
61
  PATTERN
@@ -70,16 +64,6 @@ module RuboCop
70
64
  sprintf?(node) || format?(node) || percent?(node)
71
65
  end
72
66
 
73
- def named_mode?(node)
74
- relevant_node = if sprintf?(node) || format?(node)
75
- node.first_argument
76
- elsif percent?(node)
77
- node.receiver
78
- end
79
-
80
- !relevant_node.source.scan(NAMED_FIELD_REGEX).empty?
81
- end
82
-
83
67
  def splat_args?(node)
84
68
  return false if percent?(node)
85
69
 
@@ -127,27 +111,17 @@ module RuboCop
127
111
 
128
112
  def expected_fields_count(node)
129
113
  return :unknown unless node.str_type?
130
- return 1 if node.source =~ NAMED_INTERPOLATION
131
114
 
132
- max_digit_dollar_num = max_digit_dollar_num(node)
133
- return max_digit_dollar_num if max_digit_dollar_num&.nonzero?
115
+ format_string = RuboCop::Cop::Utils::FormatString.new(node.source)
116
+ return 1 if format_string.named_interpolation?
134
117
 
135
- node
136
- .source
137
- .scan(FIELD_REGEX)
138
- .reject { |x| x.first == PERCENT_PERCENT }
139
- .reduce(0) { |acc, elem| acc + arguments_count(elem[2]) }
140
- end
141
-
142
- def max_digit_dollar_num(node)
143
- node.source.scan(DIGIT_DOLLAR_FLAG).map do |digit_dollar_num|
144
- digit_dollar_num.first.to_i
145
- end.max
146
- end
118
+ max_digit_dollar_num = format_string.max_digit_dollar_num
119
+ return max_digit_dollar_num if max_digit_dollar_num&.nonzero?
147
120
 
148
- # number of arguments required for the format sequence
149
- def arguments_count(format)
150
- format.scan('*').count + 1
121
+ format_string
122
+ .format_sequences
123
+ .reject(&:percent?)
124
+ .reduce(0) { |acc, seq| acc + seq.arity }
151
125
  end
152
126
 
153
127
  def format?(node)