rubocop 0.49.1 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -3
  3. data/bin/rubocop +1 -1
  4. data/config/default.yml +160 -99
  5. data/config/disabled.yml +4 -5
  6. data/config/enabled.yml +149 -47
  7. data/lib/rubocop.rb +41 -14
  8. data/lib/rubocop/ast/builder.rb +4 -1
  9. data/lib/rubocop/ast/node.rb +36 -42
  10. data/lib/rubocop/ast/node/args_node.rb +1 -13
  11. data/lib/rubocop/ast/node/array_node.rb +9 -0
  12. data/lib/rubocop/ast/node/block_node.rb +9 -0
  13. data/lib/rubocop/ast/node/def_node.rb +71 -0
  14. data/lib/rubocop/ast/node/for_node.rb +8 -0
  15. data/lib/rubocop/ast/node/if_node.rb +10 -2
  16. data/lib/rubocop/ast/node/mixin/collection_node.rb +15 -0
  17. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +174 -0
  18. data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +89 -0
  19. data/lib/rubocop/ast/node/mixin/parameterized_node.rb +18 -31
  20. data/lib/rubocop/ast/node/regexp_node.rb +35 -0
  21. data/lib/rubocop/ast/node/send_node.rb +1 -154
  22. data/lib/rubocop/ast/node/super_node.rb +3 -24
  23. data/lib/rubocop/ast/node/yield_node.rb +21 -0
  24. data/lib/rubocop/ast/traversal.rb +6 -6
  25. data/lib/rubocop/cli.rb +7 -3
  26. data/lib/rubocop/config.rb +45 -8
  27. data/lib/rubocop/config_loader.rb +7 -5
  28. data/lib/rubocop/cop/bundler/duplicated_gem.rb +3 -3
  29. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +64 -0
  30. data/lib/rubocop/cop/bundler/ordered_gems.rb +12 -12
  31. data/lib/rubocop/cop/commissioner.rb +8 -2
  32. data/lib/rubocop/cop/cop.rb +3 -1
  33. data/lib/rubocop/cop/generator.rb +94 -21
  34. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  35. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +14 -3
  36. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +43 -0
  37. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +46 -0
  38. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +49 -0
  39. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
  40. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +2 -3
  41. data/lib/rubocop/cop/layout/align_array.rb +2 -2
  42. data/lib/rubocop/cop/layout/align_hash.rb +2 -2
  43. data/lib/rubocop/cop/layout/align_parameters.rb +5 -11
  44. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  45. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  46. data/lib/rubocop/cop/layout/dot_position.rb +9 -0
  47. data/lib/rubocop/cop/layout/else_alignment.rb +30 -13
  48. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +4 -0
  49. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +20 -4
  50. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +3 -3
  51. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +3 -3
  52. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +3 -3
  53. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +5 -2
  54. data/lib/rubocop/cop/layout/indent_heredoc.rb +19 -24
  55. data/lib/rubocop/cop/layout/indentation_consistency.rb +1 -2
  56. data/lib/rubocop/cop/layout/indentation_width.rb +12 -8
  57. data/lib/rubocop/cop/layout/leading_comment_space.rb +33 -18
  58. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +20 -17
  59. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +3 -3
  60. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -0
  61. data/lib/rubocop/cop/layout/space_after_colon.rb +7 -0
  62. data/lib/rubocop/cop/layout/space_after_comma.rb +10 -0
  63. data/lib/rubocop/cop/layout/space_after_method_name.rb +5 -3
  64. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  65. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +13 -4
  66. data/lib/rubocop/cop/layout/space_around_keyword.rb +9 -5
  67. data/lib/rubocop/cop/layout/space_before_block_braces.rb +54 -5
  68. data/lib/rubocop/cop/layout/space_before_comment.rb +7 -0
  69. data/lib/rubocop/cop/layout/space_before_semicolon.rb +7 -0
  70. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +1 -1
  71. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
  72. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  73. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +8 -4
  74. data/lib/rubocop/cop/layout/tab.rb +1 -1
  75. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +4 -2
  76. data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
  77. data/lib/rubocop/cop/lint/block_alignment.rb +15 -6
  78. data/lib/rubocop/cop/lint/boolean_symbol.rb +38 -0
  79. data/lib/rubocop/cop/lint/condition_position.rb +5 -1
  80. data/lib/rubocop/cop/lint/debugger.rb +16 -9
  81. data/lib/rubocop/cop/lint/def_end_alignment.rb +4 -4
  82. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +3 -3
  83. data/lib/rubocop/cop/lint/duplicate_methods.rb +73 -5
  84. data/lib/rubocop/cop/lint/duplicated_key.rb +1 -1
  85. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  86. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  87. data/lib/rubocop/cop/lint/empty_expression.rb +1 -1
  88. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  89. data/lib/rubocop/cop/lint/empty_when.rb +1 -1
  90. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  91. data/lib/rubocop/cop/lint/float_out_of_range.rb +5 -5
  92. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +35 -40
  93. data/lib/rubocop/cop/lint/handle_exceptions.rb +1 -1
  94. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +18 -13
  95. data/lib/rubocop/cop/lint/inherit_exception.rb +8 -7
  96. data/lib/rubocop/cop/lint/interpolation_check.rb +36 -0
  97. data/lib/rubocop/cop/lint/literal_in_condition.rb +3 -3
  98. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  99. data/lib/rubocop/cop/lint/multiple_compare.rb +1 -1
  100. data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -7
  101. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  102. data/lib/rubocop/cop/lint/percent_string_array.rb +3 -12
  103. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  104. data/lib/rubocop/cop/lint/rand_one.rb +7 -1
  105. data/lib/rubocop/cop/lint/redundant_with_index.rb +77 -0
  106. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  107. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  108. data/lib/rubocop/cop/lint/rescue_type.rb +13 -6
  109. data/lib/rubocop/cop/lint/rescue_without_error_class.rb +38 -0
  110. data/lib/rubocop/cop/lint/return_in_void_context.rb +63 -0
  111. data/lib/rubocop/cop/lint/script_permission.rb +6 -0
  112. data/lib/rubocop/cop/lint/syntax.rb +17 -20
  113. data/lib/rubocop/cop/lint/unified_integer.rb +3 -2
  114. data/lib/rubocop/cop/lint/unneeded_disable.rb +1 -1
  115. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +1 -1
  116. data/lib/rubocop/cop/lint/unreachable_code.rb +53 -8
  117. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +74 -0
  118. data/lib/rubocop/cop/lint/uri_regexp.rb +73 -0
  119. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -8
  120. data/lib/rubocop/cop/lint/useless_setter_call.rb +10 -11
  121. data/lib/rubocop/cop/lint/void.rb +29 -23
  122. data/lib/rubocop/cop/metrics/line_length.rb +2 -2
  123. data/lib/rubocop/cop/metrics/method_length.rb +8 -3
  124. data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
  125. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +1 -1
  126. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -2
  127. data/lib/rubocop/cop/mixin/first_element_line_break.rb +12 -3
  128. data/lib/rubocop/cop/mixin/heredoc.rb +28 -0
  129. data/lib/rubocop/cop/mixin/method_complexity.rb +9 -6
  130. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +68 -31
  131. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +18 -0
  132. data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
  133. data/lib/rubocop/cop/mixin/percent_array.rb +52 -0
  134. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  135. data/lib/rubocop/cop/{style → naming}/accessor_method_name.rb +11 -12
  136. data/lib/rubocop/cop/{style → naming}/ascii_identifiers.rb +1 -1
  137. data/lib/rubocop/cop/{style/op_method.rb → naming/binary_operator_parameter_name.rb} +2 -2
  138. data/lib/rubocop/cop/{style → naming}/class_and_module_camel_case.rb +1 -1
  139. data/lib/rubocop/cop/{style → naming}/constant_name.rb +1 -1
  140. data/lib/rubocop/cop/{style → naming}/file_name.rb +8 -4
  141. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +68 -0
  142. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +58 -0
  143. data/lib/rubocop/cop/{style → naming}/method_name.rb +1 -1
  144. data/lib/rubocop/cop/{style → naming}/predicate_name.rb +6 -7
  145. data/lib/rubocop/cop/{style → naming}/variable_name.rb +11 -15
  146. data/lib/rubocop/cop/{style → naming}/variable_number.rb +1 -1
  147. data/lib/rubocop/cop/performance/caller.rb +39 -11
  148. data/lib/rubocop/cop/performance/casecmp.rb +4 -4
  149. data/lib/rubocop/cop/performance/compare_with_block.rb +4 -4
  150. data/lib/rubocop/cop/performance/double_start_end_with.rb +4 -4
  151. data/lib/rubocop/cop/performance/end_with.rb +3 -3
  152. data/lib/rubocop/cop/performance/fixed_size.rb +1 -1
  153. data/lib/rubocop/cop/performance/hash_each_methods.rb +66 -25
  154. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +2 -2
  155. data/lib/rubocop/cop/performance/range_include.rb +2 -2
  156. data/lib/rubocop/cop/performance/redundant_block_call.rb +6 -6
  157. data/lib/rubocop/cop/performance/redundant_match.rb +5 -5
  158. data/lib/rubocop/cop/performance/redundant_merge.rb +39 -23
  159. data/lib/rubocop/cop/performance/redundant_sort_by.rb +2 -2
  160. data/lib/rubocop/cop/performance/regexp_match.rb +13 -5
  161. data/lib/rubocop/cop/performance/size.rb +1 -1
  162. data/lib/rubocop/cop/performance/start_with.rb +3 -3
  163. data/lib/rubocop/cop/performance/times_map.rb +23 -12
  164. data/lib/rubocop/cop/performance/unfreeze_string.rb +50 -0
  165. data/lib/rubocop/cop/performance/uri_default_parser.rb +47 -0
  166. data/lib/rubocop/cop/rails/active_support_aliases.rb +1 -1
  167. data/lib/rubocop/cop/rails/delegate.rb +36 -7
  168. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +1 -1
  169. data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -2
  170. data/lib/rubocop/cop/rails/file_path.rb +3 -4
  171. data/lib/rubocop/cop/rails/find_each.rb +1 -1
  172. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +48 -0
  173. data/lib/rubocop/cop/rails/http_positional_arguments.rb +5 -5
  174. data/lib/rubocop/cop/rails/not_null_column.rb +1 -1
  175. data/lib/rubocop/cop/rails/pluralization_grammar.rb +2 -2
  176. data/lib/rubocop/cop/rails/relative_date_constant.rb +1 -1
  177. data/lib/rubocop/cop/rails/request_referer.rb +2 -2
  178. data/lib/rubocop/cop/rails/reversible_migration.rb +12 -12
  179. data/lib/rubocop/cop/rails/save_bang.rb +8 -6
  180. data/lib/rubocop/cop/rails/scope_args.rb +1 -1
  181. data/lib/rubocop/cop/security/eval.rb +2 -2
  182. data/lib/rubocop/cop/security/json_load.rb +2 -2
  183. data/lib/rubocop/cop/security/marshal_load.rb +2 -2
  184. data/lib/rubocop/cop/security/yaml_load.rb +2 -2
  185. data/lib/rubocop/cop/style/alias.rb +44 -20
  186. data/lib/rubocop/cop/style/and_or.rb +48 -34
  187. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +1 -1
  188. data/lib/rubocop/cop/style/block_comments.rb +3 -1
  189. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  190. data/lib/rubocop/cop/style/command_literal.rb +20 -9
  191. data/lib/rubocop/cop/style/conditional_assignment.rb +30 -28
  192. data/lib/rubocop/cop/style/copyright.rb +10 -10
  193. data/lib/rubocop/cop/style/def_with_parentheses.rb +6 -5
  194. data/lib/rubocop/cop/style/dir.rb +52 -0
  195. data/lib/rubocop/cop/style/documentation_method.rb +2 -6
  196. data/lib/rubocop/cop/style/empty_case_condition.rb +1 -1
  197. data/lib/rubocop/cop/style/empty_else.rb +3 -2
  198. data/lib/rubocop/cop/style/empty_literal.rb +1 -2
  199. data/lib/rubocop/cop/style/empty_method.rb +27 -17
  200. data/lib/rubocop/cop/style/flip_flop.rb +2 -2
  201. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  202. data/lib/rubocop/cop/style/guard_clause.rb +4 -2
  203. data/lib/rubocop/cop/style/hash_syntax.rb +10 -10
  204. data/lib/rubocop/cop/style/identical_conditional_branches.rb +5 -1
  205. data/lib/rubocop/cop/style/if_with_semicolon.rb +1 -1
  206. data/lib/rubocop/cop/style/implicit_runtime_error.rb +4 -3
  207. data/lib/rubocop/cop/style/inline_comment.rb +1 -1
  208. data/lib/rubocop/cop/style/inverse_methods.rb +20 -8
  209. data/lib/rubocop/cop/style/lambda.rb +19 -9
  210. data/lib/rubocop/cop/style/lambda_call.rb +22 -1
  211. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +4 -20
  212. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +6 -4
  213. data/lib/rubocop/cop/style/method_def_parentheses.rb +18 -26
  214. data/lib/rubocop/cop/style/method_missing.rb +5 -18
  215. data/lib/rubocop/cop/style/min_max.rb +67 -0
  216. data/lib/rubocop/cop/style/missing_else.rb +16 -3
  217. data/lib/rubocop/cop/style/mixin_grouping.rb +2 -2
  218. data/lib/rubocop/cop/style/module_function.rb +8 -4
  219. data/lib/rubocop/cop/style/multiline_if_modifier.rb +5 -1
  220. data/lib/rubocop/cop/style/multiline_memoization.rb +25 -3
  221. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  222. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  223. data/lib/rubocop/cop/style/mutable_constant.rb +2 -6
  224. data/lib/rubocop/cop/style/negated_if.rb +8 -4
  225. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +8 -8
  226. data/lib/rubocop/cop/style/nested_ternary_operator.rb +1 -1
  227. data/lib/rubocop/cop/style/non_nil_check.rb +14 -14
  228. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +6 -2
  229. data/lib/rubocop/cop/style/numeric_literals.rb +2 -2
  230. data/lib/rubocop/cop/style/numeric_predicate.rb +8 -4
  231. data/lib/rubocop/cop/style/one_line_conditional.rb +8 -3
  232. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  233. data/lib/rubocop/cop/style/optional_arguments.rb +1 -2
  234. data/lib/rubocop/cop/style/or_assignment.rb +88 -0
  235. data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
  236. data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -11
  237. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  238. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  239. data/lib/rubocop/cop/style/perl_backrefs.rb +1 -1
  240. data/lib/rubocop/cop/style/proc.rb +1 -1
  241. data/lib/rubocop/cop/style/raise_args.rb +16 -17
  242. data/lib/rubocop/cop/style/redundant_begin.rb +6 -5
  243. data/lib/rubocop/cop/style/redundant_conditional.rb +95 -0
  244. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  245. data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -11
  246. data/lib/rubocop/cop/style/redundant_return.rb +23 -11
  247. data/lib/rubocop/cop/style/redundant_self.rb +18 -9
  248. data/lib/rubocop/cop/style/regexp_literal.rb +12 -4
  249. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  250. data/lib/rubocop/cop/style/return_nil.rb +98 -0
  251. data/lib/rubocop/cop/style/safe_navigation.rb +80 -43
  252. data/lib/rubocop/cop/style/single_line_block_params.rb +14 -13
  253. data/lib/rubocop/cop/style/single_line_methods.rb +9 -13
  254. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  255. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +17 -39
  256. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +22 -1
  257. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  258. data/lib/rubocop/cop/style/symbol_array.rb +5 -25
  259. data/lib/rubocop/cop/style/symbol_literal.rb +1 -1
  260. data/lib/rubocop/cop/style/symbol_proc.rb +3 -18
  261. data/lib/rubocop/cop/style/ternary_parentheses.rb +14 -10
  262. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +28 -9
  263. data/lib/rubocop/cop/style/trivial_accessors.rb +39 -56
  264. data/lib/rubocop/cop/style/unless_else.rb +1 -1
  265. data/lib/rubocop/cop/style/unneeded_capital_w.rb +1 -1
  266. data/lib/rubocop/cop/style/unneeded_interpolation.rb +1 -1
  267. data/lib/rubocop/cop/style/unneeded_percent_q.rb +1 -1
  268. data/lib/rubocop/cop/style/variable_interpolation.rb +8 -3
  269. data/lib/rubocop/cop/style/word_array.rb +7 -24
  270. data/lib/rubocop/cop/style/yoda_condition.rb +49 -14
  271. data/lib/rubocop/cop/style/zero_length_predicate.rb +25 -18
  272. data/lib/rubocop/cop/team.rb +16 -8
  273. data/lib/rubocop/cop/util.rb +11 -0
  274. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  275. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  276. data/lib/rubocop/formatter/offense_count_formatter.rb +2 -0
  277. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  278. data/lib/rubocop/formatter/tap_formatter.rb +71 -0
  279. data/lib/rubocop/formatter/worst_offenders_formatter.rb +2 -0
  280. data/lib/rubocop/node_pattern.rb +44 -26
  281. data/lib/rubocop/options.rb +1 -0
  282. data/lib/rubocop/processed_source.rb +3 -1
  283. data/lib/rubocop/remote_config.rb +5 -1
  284. data/lib/rubocop/result_cache.rb +1 -0
  285. data/lib/rubocop/rspec/cop_helper.rb +10 -10
  286. data/lib/rubocop/rspec/expect_offense.rb +6 -8
  287. data/lib/rubocop/rspec/shared_examples.rb +8 -8
  288. data/lib/rubocop/string_util.rb +2 -0
  289. data/lib/rubocop/version.rb +1 -1
  290. metadata +51 -18
  291. data/lib/rubocop/cop/mixin/access_modifier_node.rb +0 -41
  292. data/lib/rubocop/cop/mixin/on_method_def.rb +0 -44
@@ -36,7 +36,7 @@ module RuboCop
36
36
  nodes[1..-1].each do |node|
37
37
  register_offense(
38
38
  node,
39
- node.method_args.first.to_a.first,
39
+ node.first_argument.to_a.first,
40
40
  nodes.first.loc.line
41
41
  )
42
42
  end
@@ -49,9 +49,9 @@ module RuboCop
49
49
 
50
50
  def duplicated_gem_nodes
51
51
  gem_declarations(processed_source.ast)
52
- .group_by { |e| e.method_args.first }
53
- .keep_if { |_, nodes| nodes.length > 1 }
52
+ .group_by(&:first_argument)
54
53
  .values
54
+ .select { |nodes| nodes.size > 1 }
55
55
  end
56
56
 
57
57
  def register_offense(node, gem_name, line_of_first_occurrence)
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Bundler
6
+ # The symbol argument `:gemcutter`, `:rubygems` and `:rubyforge`
7
+ # are deprecated. So please change your source to URL string that
8
+ # 'https://rubygems.org' if possible, or 'http://rubygems.org' if not.
9
+ #
10
+ # This autocorrect will replace these symbols with 'https://rubygems.org'.
11
+ # Because it is secure, HTTPS request is strongly recommended. And in
12
+ # most use cases HTTPS will be fine.
13
+ #
14
+ # However, it don't replace all `sources` of `http://` with `https://`.
15
+ # For example, when specifying an internal gem server using HTTP on the
16
+ # intranet, a use case where HTTPS can not be specified was considered.
17
+ # Consider using HTTP only if you can not use HTTPS.
18
+ #
19
+ # @example
20
+ # # bad
21
+ # source :gemcutter
22
+ # source :rubygems
23
+ # source :rubyforge
24
+ #
25
+ # # good
26
+ # source 'https://rubygems.org' # strongly recommended
27
+ # source 'http://rubygems.org'
28
+ class InsecureProtocolSource < Cop
29
+ MSG = 'The source `:%s` is deprecated because HTTP requests are ' \
30
+ "insecure. Please change your source to 'https://rubygems.org' " \
31
+ "if possible, or 'http://rubygems.org' if not.".freeze
32
+
33
+ def_node_matcher :insecure_protocol_source?, <<-PATTERN
34
+ (send nil :source
35
+ (sym ${:gemcutter :rubygems :rubyforge}))
36
+ PATTERN
37
+
38
+ def on_send(node)
39
+ insecure_protocol_source?(node) do |source|
40
+ message = format(MSG, source)
41
+
42
+ add_offense(
43
+ node, source_range(node.first_argument.loc.expression), message
44
+ )
45
+ end
46
+ end
47
+
48
+ def autocorrect(node)
49
+ lambda do |corrector|
50
+ corrector.replace(
51
+ node.first_argument.loc.expression, "'https://rubygems.org'"
52
+ )
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def source_range(node)
59
+ range_between(node.begin_pos, node.end_pos)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -30,19 +30,22 @@ module RuboCop
30
30
  MSG = 'Gems should be sorted in an alphabetical order within their '\
31
31
  'section of the Gemfile. '\
32
32
  'Gem `%s` should appear before `%s`.'.freeze
33
+
33
34
  def investigate(processed_source)
34
35
  return if processed_source.ast.nil?
35
36
  gem_declarations(processed_source.ast)
36
37
  .each_cons(2) do |previous, current|
37
38
  next unless consecutive_lines(previous, current)
38
39
  next unless case_insensitive_out_of_order?(
39
- current.children[2].children.first.to_s,
40
- previous.children[2].children.first.to_s
40
+ gem_name(current),
41
+ gem_name(previous)
41
42
  )
42
43
  register_offense(previous, current)
43
44
  end
44
45
  end
45
46
 
47
+ private
48
+
46
49
  def case_insensitive_out_of_order?(string_a, string_b)
47
50
  string_a.downcase < string_b.downcase
48
51
  end
@@ -53,15 +56,12 @@ module RuboCop
53
56
  end
54
57
 
55
58
  def register_offense(previous, current)
56
- add_offense(
57
- current,
58
- current.source_range,
59
- format(
60
- MSG,
61
- current.children[2].children.first,
62
- previous.children[2].children.first
63
- )
64
- )
59
+ add_offense(current, :expression,
60
+ format(MSG, gem_name(current), gem_name(previous)))
61
+ end
62
+
63
+ def gem_name(declaration_node)
64
+ declaration_node.first_argument.str_content
65
65
  end
66
66
 
67
67
  def autocorrect(node)
@@ -105,7 +105,7 @@ module RuboCop
105
105
  end
106
106
 
107
107
  def_node_search :gem_declarations, <<-PATTERN
108
- (:send, nil, :gem, ...)
108
+ (:send nil :gem ...)
109
109
  PATTERN
110
110
  end
111
111
  end
@@ -34,7 +34,7 @@ module RuboCop
34
34
 
35
35
  callback_methods.each do |callback|
36
36
  next unless method_defined?(callback)
37
- class_eval <<-EOS, __FILE__, __LINE__ + 1
37
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
38
38
  def #{callback}(node)
39
39
  @callbacks[:"#{callback}"] ||= @cops.select do |cop|
40
40
  cop.respond_to?(:"#{callback}")
@@ -47,7 +47,7 @@ module RuboCop
47
47
 
48
48
  #{!no_child_callbacks.include?(callback) && 'super'}
49
49
  end
50
- EOS
50
+ RUBY
51
51
  end
52
52
 
53
53
  def investigate(processed_source)
@@ -102,6 +102,11 @@ module RuboCop
102
102
  end
103
103
  end
104
104
 
105
+ # Allow blind rescues here, since we're absorbing and packaging or
106
+ # re-raising exceptions that can be raised from within the individual
107
+ # cops' `#investigate` methods.
108
+ #
109
+ # rubocop:disable Lint/RescueWithoutErrorClass
105
110
  def with_cop_error_handling(cop, node = nil)
106
111
  yield
107
112
  rescue => e
@@ -113,6 +118,7 @@ module RuboCop
113
118
  error = CopError.new(e, line, column)
114
119
  @errors[cop] << error
115
120
  end
121
+ # rubocop:enable Lint/RescueWithoutErrorClass
116
122
  end
117
123
  end
118
124
  end
@@ -112,7 +112,8 @@ module RuboCop
112
112
  self.class::MSG
113
113
  end
114
114
 
115
- def add_offense(node, loc, message = nil, severity = nil)
115
+ # rubocop:disable Metrics/CyclomaticComplexity
116
+ def add_offense(node, loc = :expression, message = nil, severity = nil)
116
117
  location = find_location(node, loc)
117
118
 
118
119
  return if duplicate_location?(location)
@@ -127,6 +128,7 @@ module RuboCop
127
128
  @offenses << Offense.new(severity, location, message, name, status)
128
129
  yield if block_given? && status != :disabled
129
130
  end
131
+ # rubocop:enable Metrics/CyclomaticComplexity
130
132
 
131
133
  def find_location(node, loc)
132
134
  # Location can be provided as a symbol, e.g.: `:keyword`
@@ -43,7 +43,7 @@ module RuboCop
43
43
 
44
44
  def on_send(node)
45
45
  return unless bad_method?(node)
46
- add_offense(node, :expression)
46
+ add_offense(node)
47
47
  end
48
48
  end
49
49
  end
@@ -51,7 +51,7 @@ module RuboCop
51
51
  end
52
52
  RUBY
53
53
 
54
- SPEC_TEMPLATE = <<-RUBY.strip_indent
54
+ SPEC_TEMPLATE = <<-SPEC.strip_indent
55
55
  # frozen_string_literal: true
56
56
 
57
57
  describe RuboCop::Cop::%<department>s::%<cop_name>s do
@@ -61,19 +61,20 @@ module RuboCop
61
61
  # TODO: Write test code
62
62
  #
63
63
  # For example
64
- it 'registers an offense for offending code' do
65
- inspect_source(cop, 'bad_method')
66
- expect(cop.offenses.size).to eq(1)
67
- expect(cop.messages)
68
- .to eq(['Message of %<cop_name>s'])
64
+ it 'registers an offense when using `#bad_method`' do
65
+ expect_offense(<<-RUBY.strip_indent)
66
+ bad_method
67
+ ^^^^^^^^^^ Use `#good_method` instead of `#bad_method`.
68
+ RUBY
69
69
  end
70
70
 
71
- it 'accepts' do
72
- inspect_source(cop, 'good_method')
73
- expect(cop.offenses).to be_empty
71
+ it 'does not register an offense when using `#good_method`' do
72
+ expect_no_offenses(<<-RUBY.strip_indent)
73
+ good_method
74
+ RUBY
74
75
  end
75
76
  end
76
- RUBY
77
+ SPEC
77
78
 
78
79
  def initialize(name)
79
80
  @badge = Badge.parse(name)
@@ -91,18 +92,21 @@ module RuboCop
91
92
  write_unless_file_exists(spec_path, generated_spec)
92
93
  end
93
94
 
95
+ def inject_require
96
+ RequireFileInjector.new(require_path).inject
97
+ end
98
+
94
99
  def todo
95
100
  <<-TODO.strip_indent
96
- created
97
- - #{source_path}
98
- - #{spec_path}
99
-
100
- Do 4 steps
101
- - Add an entry to `New feature` section in CHANGELOG.md
102
- - e.g. Add new `#{badge.cop_name}` cop. ([@your_id][])
103
- - Add `require '#{require_path}'` into lib/rubocop.rb
104
- - Add an entry into config/enabled.yml or config/disabled.yml
105
- - Implement a new cop to the generated file!
101
+ Files created:
102
+ - #{source_path}
103
+ - #{spec_path}
104
+
105
+ Do 3 steps:
106
+ 1. Add an entry to the "New features" section in CHANGELOG.md,
107
+ e.g. "Add new `#{badge}` cop. ([@your_id][])"
108
+ 2. Add an entry into config/enabled.yml or config/disabled.yml
109
+ 3. Implement your new cop in the generated file!
106
110
  TODO
107
111
  end
108
112
 
@@ -113,6 +117,9 @@ module RuboCop
113
117
  def write_unless_file_exists(path, contents)
114
118
  raise "#{path} already exists!" if File.exist?(path)
115
119
 
120
+ dir = File.dirname(path)
121
+ FileUtils.mkdir_p(dir) unless File.exist?(dir)
122
+
116
123
  File.write(path, contents)
117
124
  end
118
125
 
@@ -158,6 +165,72 @@ module RuboCop
158
165
  .gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
159
166
  .downcase
160
167
  end
168
+
169
+ # A class that injects a require directive into the root RuboCop file.
170
+ # It looks for other directives that require files in the same (cop)
171
+ # namespace and injects the provided one in alpha
172
+ class RequireFileInjector
173
+ REQUIRE_PATH = /require ['"](.+)['"]/
174
+
175
+ def initialize(require_path)
176
+ @require_path = require_path
177
+ @require_entries = File.readlines(rubocop_root_file_path)
178
+ end
179
+
180
+ def inject
181
+ return if require_exists? || !target_line
182
+
183
+ File.write(rubocop_root_file_path, updated_directives)
184
+ end
185
+
186
+ private
187
+
188
+ attr_reader :require_path, :require_entries
189
+
190
+ def rubocop_root_file_path
191
+ File.join('lib', 'rubocop.rb')
192
+ end
193
+
194
+ def require_exists?
195
+ require_entries.any? do |entry|
196
+ entry == injectable_require_directive
197
+ end
198
+ end
199
+
200
+ def updated_directives
201
+ require_entries.insert(target_line,
202
+ injectable_require_directive).join
203
+ end
204
+
205
+ def target_line
206
+ @target_line ||= begin
207
+ in_the_same_department = false
208
+ inject_parts = require_path_fragments(injectable_require_directive)
209
+
210
+ require_entries.find.with_index do |entry, index|
211
+ current_entry_parts = require_path_fragments(entry)
212
+
213
+ if inject_parts[0..-2] == current_entry_parts[0..-2]
214
+ in_the_same_department = true
215
+
216
+ break index if inject_parts.last < current_entry_parts.last
217
+ elsif in_the_same_department
218
+ break index
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ def require_path_fragments(require_directove)
225
+ path = require_directove.match(REQUIRE_PATH)
226
+
227
+ path ? path.captures.first.split('/') : []
228
+ end
229
+
230
+ def injectable_require_directive
231
+ "require '#{require_path}'\n"
232
+ end
233
+ end
161
234
  end
162
235
  end
163
236
  end
@@ -1,4 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rubocop/cop/internal_affairs/node_type_predicate'
4
+ require 'rubocop/cop/internal_affairs/offense_location_keyword'
5
+ require 'rubocop/cop/internal_affairs/redundant_message_argument'
6
+ require 'rubocop/cop/internal_affairs/redundant_location_argument'
4
7
  require 'rubocop/cop/internal_affairs/useless_message_assertion'
@@ -16,17 +16,28 @@ module RuboCop
16
16
  class NodeTypePredicate < Cop
17
17
  MSG = 'Use `#%s_type?` to check node type.'.freeze
18
18
 
19
- def_node_search :node_type_check, <<-PATTERN
20
- (send (send _ :type) :== (sym $_))
19
+ def_node_matcher :node_type_check, <<-PATTERN
20
+ (send (send $_ :type) :== (sym $_))
21
21
  PATTERN
22
22
 
23
23
  def on_send(node)
24
- node_type_check(node) do |node_type|
24
+ node_type_check(node) do |_receiver, node_type|
25
25
  return unless Parser::Meta::NODE_TYPES.include?(node_type)
26
26
 
27
27
  add_offense(node, :expression, format(MSG, node_type))
28
28
  end
29
29
  end
30
+
31
+ def autocorrect(node)
32
+ receiver, node_type = node_type_check(node)
33
+ range = Parser::Source::Range.new(node.source_range.source_buffer,
34
+ receiver.loc.expression.end_pos + 1,
35
+ node.loc.expression.end_pos)
36
+
37
+ lambda do |corrector|
38
+ corrector.replace(range, "#{node_type}_type?")
39
+ end
40
+ end
30
41
  end
31
42
  end
32
43
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for potential uses of the location keywords which can be used as
7
+ # shortcut arguments to `#add_offense`.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # add_offense(node, node.loc.selector)
13
+ #
14
+ # # good
15
+ # add_offense(node, :selector)
16
+ class OffenseLocationKeyword < Cop
17
+ MSG = 'Use `:%s` as the location argument to `#add_offense`.'.freeze
18
+
19
+ def on_send(node)
20
+ offense_location(node) do |location_argument, keyword|
21
+ add_offense(node, location_argument.loc.expression,
22
+ format(MSG, keyword))
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def_node_matcher :offense_location, <<-PATTERN
29
+ (send nil :add_offense _offender
30
+ $(send (send _offender :loc) $_) ...)
31
+ PATTERN
32
+
33
+ def autocorrect(node)
34
+ lambda do |corrector|
35
+ offense_location(node) do |location_argument, keyword|
36
+ corrector.replace(location_argument.loc.expression, ":#{keyword}")
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks for redundant `location` argument to `#add_offense`. `location`
7
+ # argument has a default value of `:expression` and this method will
8
+ # automatically use it.
9
+ #
10
+ # @example
11
+ #
12
+ # # bad
13
+ # add_offense(node, :expression)
14
+ #
15
+ # # good
16
+ # add_offense(node)
17
+ # add_offense(node, :selector)
18
+ # add_offense(node, :expression, 'message')
19
+ #
20
+ class RedundantLocationArgument < Cop
21
+ MSG = 'Redundant location argument to `#add_offense`.'.freeze
22
+
23
+ def_node_matcher :node_type_check, <<-PATTERN
24
+ (send nil :add_offense _ (sym :expression))
25
+ PATTERN
26
+
27
+ def on_send(node)
28
+ node_type_check(node) do
29
+ add_offense(node.last_argument)
30
+ end
31
+ end
32
+
33
+ def autocorrect(node)
34
+ first, second = node.parent.arguments
35
+
36
+ range = range_between(
37
+ first.loc.expression.end_pos,
38
+ second.loc.expression.end_pos
39
+ )
40
+
41
+ ->(corrector) { corrector.remove(range) }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end