rubbycop 0.49.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 (499) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +211 -0
  4. data/assets/logo.png +0 -0
  5. data/assets/output.html.erb +261 -0
  6. data/bin/rubbycop +17 -0
  7. data/config/default.yml +1548 -0
  8. data/config/disabled.yml +119 -0
  9. data/config/enabled.yml +1734 -0
  10. data/lib/rubbycop.rb +510 -0
  11. data/lib/rubbycop/ast/builder.rb +64 -0
  12. data/lib/rubbycop/ast/node.rb +610 -0
  13. data/lib/rubbycop/ast/node/and_node.rb +37 -0
  14. data/lib/rubbycop/ast/node/array_node.rb +48 -0
  15. data/lib/rubbycop/ast/node/case_node.rb +64 -0
  16. data/lib/rubbycop/ast/node/ensure_node.rb +25 -0
  17. data/lib/rubbycop/ast/node/for_node.rb +53 -0
  18. data/lib/rubbycop/ast/node/hash_node.rb +109 -0
  19. data/lib/rubbycop/ast/node/if_node.rb +138 -0
  20. data/lib/rubbycop/ast/node/keyword_splat_node.rb +45 -0
  21. data/lib/rubbycop/ast/node/mixin/binary_operator_node.rb +23 -0
  22. data/lib/rubbycop/ast/node/mixin/conditional_node.rb +45 -0
  23. data/lib/rubbycop/ast/node/mixin/hash_element_node.rb +125 -0
  24. data/lib/rubbycop/ast/node/mixin/modifier_node.rb +17 -0
  25. data/lib/rubbycop/ast/node/mixin/predicate_operator_node.rb +35 -0
  26. data/lib/rubbycop/ast/node/or_node.rb +37 -0
  27. data/lib/rubbycop/ast/node/pair_node.rb +64 -0
  28. data/lib/rubbycop/ast/node/resbody_node.rb +25 -0
  29. data/lib/rubbycop/ast/node/send_node.rb +209 -0
  30. data/lib/rubbycop/ast/node/until_node.rb +43 -0
  31. data/lib/rubbycop/ast/node/when_node.rb +61 -0
  32. data/lib/rubbycop/ast/node/while_node.rb +43 -0
  33. data/lib/rubbycop/ast/sexp.rb +16 -0
  34. data/lib/rubbycop/ast/traversal.rb +171 -0
  35. data/lib/rubbycop/cached_data.rb +63 -0
  36. data/lib/rubbycop/cli.rb +199 -0
  37. data/lib/rubbycop/comment_config.rb +155 -0
  38. data/lib/rubbycop/config.rb +444 -0
  39. data/lib/rubbycop/config_loader.rb +244 -0
  40. data/lib/rubbycop/config_loader_resolver.rb +43 -0
  41. data/lib/rubbycop/config_store.rb +48 -0
  42. data/lib/rubbycop/cop/autocorrect_logic.rb +26 -0
  43. data/lib/rubbycop/cop/badge.rb +73 -0
  44. data/lib/rubbycop/cop/bundler/duplicated_gem.rb +69 -0
  45. data/lib/rubbycop/cop/bundler/ordered_gems.rb +113 -0
  46. data/lib/rubbycop/cop/commissioner.rb +118 -0
  47. data/lib/rubbycop/cop/cop.rb +222 -0
  48. data/lib/rubbycop/cop/corrector.rb +135 -0
  49. data/lib/rubbycop/cop/force.rb +41 -0
  50. data/lib/rubbycop/cop/ignored_node.rb +38 -0
  51. data/lib/rubbycop/cop/layout/access_modifier_indentation.rb +109 -0
  52. data/lib/rubbycop/cop/layout/align_array.rb +35 -0
  53. data/lib/rubbycop/cop/layout/align_hash.rb +235 -0
  54. data/lib/rubbycop/cop/layout/align_parameters.rb +97 -0
  55. data/lib/rubbycop/cop/layout/block_end_newline.rb +56 -0
  56. data/lib/rubbycop/cop/layout/case_indentation.rb +163 -0
  57. data/lib/rubbycop/cop/layout/closing_parenthesis_indentation.rb +88 -0
  58. data/lib/rubbycop/cop/layout/comment_indentation.rb +71 -0
  59. data/lib/rubbycop/cop/layout/dot_position.rb +84 -0
  60. data/lib/rubbycop/cop/layout/else_alignment.rb +105 -0
  61. data/lib/rubbycop/cop/layout/empty_line_after_magic_comment.rb +63 -0
  62. data/lib/rubbycop/cop/layout/empty_line_between_defs.rb +143 -0
  63. data/lib/rubbycop/cop/layout/empty_lines.rb +60 -0
  64. data/lib/rubbycop/cop/layout/empty_lines_around_access_modifier.rb +90 -0
  65. data/lib/rubbycop/cop/layout/empty_lines_around_begin_body.rb +42 -0
  66. data/lib/rubbycop/cop/layout/empty_lines_around_block_body.rb +41 -0
  67. data/lib/rubbycop/cop/layout/empty_lines_around_class_body.rb +39 -0
  68. data/lib/rubbycop/cop/layout/empty_lines_around_exception_handling_keywords.rb +127 -0
  69. data/lib/rubbycop/cop/layout/empty_lines_around_method_body.rb +41 -0
  70. data/lib/rubbycop/cop/layout/empty_lines_around_module_body.rb +44 -0
  71. data/lib/rubbycop/cop/layout/end_of_line.rb +52 -0
  72. data/lib/rubbycop/cop/layout/extra_spacing.rb +237 -0
  73. data/lib/rubbycop/cop/layout/first_array_element_line_break.rb +41 -0
  74. data/lib/rubbycop/cop/layout/first_hash_element_line_break.rb +33 -0
  75. data/lib/rubbycop/cop/layout/first_method_argument_line_break.rb +49 -0
  76. data/lib/rubbycop/cop/layout/first_method_parameter_line_break.rb +42 -0
  77. data/lib/rubbycop/cop/layout/first_parameter_indentation.rb +109 -0
  78. data/lib/rubbycop/cop/layout/indent_array.rb +114 -0
  79. data/lib/rubbycop/cop/layout/indent_assignment.rb +42 -0
  80. data/lib/rubbycop/cop/layout/indent_hash.rb +134 -0
  81. data/lib/rubbycop/cop/layout/indent_heredoc.rb +173 -0
  82. data/lib/rubbycop/cop/layout/indentation_consistency.rb +51 -0
  83. data/lib/rubbycop/cop/layout/indentation_width.rb +303 -0
  84. data/lib/rubbycop/cop/layout/initial_indentation.rb +42 -0
  85. data/lib/rubbycop/cop/layout/leading_comment_space.rb +43 -0
  86. data/lib/rubbycop/cop/layout/multiline_array_brace_layout.rb +81 -0
  87. data/lib/rubbycop/cop/layout/multiline_assignment_layout.rb +88 -0
  88. data/lib/rubbycop/cop/layout/multiline_block_layout.rb +134 -0
  89. data/lib/rubbycop/cop/layout/multiline_hash_brace_layout.rb +81 -0
  90. data/lib/rubbycop/cop/layout/multiline_method_call_brace_layout.rb +97 -0
  91. data/lib/rubbycop/cop/layout/multiline_method_call_indentation.rb +215 -0
  92. data/lib/rubbycop/cop/layout/multiline_method_definition_brace_layout.rb +82 -0
  93. data/lib/rubbycop/cop/layout/multiline_operation_indentation.rb +89 -0
  94. data/lib/rubbycop/cop/layout/rescue_ensure_alignment.rb +86 -0
  95. data/lib/rubbycop/cop/layout/space_after_colon.rb +40 -0
  96. data/lib/rubbycop/cop/layout/space_after_comma.rb +21 -0
  97. data/lib/rubbycop/cop/layout/space_after_method_name.rb +37 -0
  98. data/lib/rubbycop/cop/layout/space_after_not.rb +38 -0
  99. data/lib/rubbycop/cop/layout/space_after_semicolon.rb +21 -0
  100. data/lib/rubbycop/cop/layout/space_around_block_parameters.rb +109 -0
  101. data/lib/rubbycop/cop/layout/space_around_equals_in_parameter_default.rb +68 -0
  102. data/lib/rubbycop/cop/layout/space_around_keyword.rb +224 -0
  103. data/lib/rubbycop/cop/layout/space_around_operators.rb +142 -0
  104. data/lib/rubbycop/cop/layout/space_before_block_braces.rb +54 -0
  105. data/lib/rubbycop/cop/layout/space_before_comma.rb +16 -0
  106. data/lib/rubbycop/cop/layout/space_before_comment.rb +27 -0
  107. data/lib/rubbycop/cop/layout/space_before_first_arg.rb +64 -0
  108. data/lib/rubbycop/cop/layout/space_before_semicolon.rb +16 -0
  109. data/lib/rubbycop/cop/layout/space_in_lambda_literal.rb +87 -0
  110. data/lib/rubbycop/cop/layout/space_inside_array_percent_literal.rb +53 -0
  111. data/lib/rubbycop/cop/layout/space_inside_block_braces.rb +158 -0
  112. data/lib/rubbycop/cop/layout/space_inside_brackets.rb +20 -0
  113. data/lib/rubbycop/cop/layout/space_inside_hash_literal_braces.rb +150 -0
  114. data/lib/rubbycop/cop/layout/space_inside_parens.rb +16 -0
  115. data/lib/rubbycop/cop/layout/space_inside_percent_literal_delimiters.rb +64 -0
  116. data/lib/rubbycop/cop/layout/space_inside_range_literal.rb +63 -0
  117. data/lib/rubbycop/cop/layout/space_inside_string_interpolation.rb +65 -0
  118. data/lib/rubbycop/cop/layout/tab.rb +57 -0
  119. data/lib/rubbycop/cop/layout/trailing_blank_lines.rb +78 -0
  120. data/lib/rubbycop/cop/layout/trailing_whitespace.rb +28 -0
  121. data/lib/rubbycop/cop/lint/ambiguous_block_association.rb +66 -0
  122. data/lib/rubbycop/cop/lint/ambiguous_operator.rb +55 -0
  123. data/lib/rubbycop/cop/lint/ambiguous_regexp_literal.rb +43 -0
  124. data/lib/rubbycop/cop/lint/assignment_in_condition.rb +80 -0
  125. data/lib/rubbycop/cop/lint/block_alignment.rb +229 -0
  126. data/lib/rubbycop/cop/lint/circular_argument_reference.rb +83 -0
  127. data/lib/rubbycop/cop/lint/condition_position.rb +52 -0
  128. data/lib/rubbycop/cop/lint/debugger.rb +72 -0
  129. data/lib/rubbycop/cop/lint/def_end_alignment.rb +78 -0
  130. data/lib/rubbycop/cop/lint/deprecated_class_methods.rb +90 -0
  131. data/lib/rubbycop/cop/lint/duplicate_case_condition.rb +53 -0
  132. data/lib/rubbycop/cop/lint/duplicate_methods.rb +151 -0
  133. data/lib/rubbycop/cop/lint/duplicated_key.rb +38 -0
  134. data/lib/rubbycop/cop/lint/each_with_object_argument.rb +39 -0
  135. data/lib/rubbycop/cop/lint/else_layout.rb +65 -0
  136. data/lib/rubbycop/cop/lint/empty_ensure.rb +60 -0
  137. data/lib/rubbycop/cop/lint/empty_expression.rb +42 -0
  138. data/lib/rubbycop/cop/lint/empty_interpolation.rb +36 -0
  139. data/lib/rubbycop/cop/lint/empty_when.rb +38 -0
  140. data/lib/rubbycop/cop/lint/end_alignment.rb +157 -0
  141. data/lib/rubbycop/cop/lint/end_in_method.rb +40 -0
  142. data/lib/rubbycop/cop/lint/ensure_return.rb +43 -0
  143. data/lib/rubbycop/cop/lint/float_out_of_range.rb +35 -0
  144. data/lib/rubbycop/cop/lint/format_parameter_mismatch.rb +182 -0
  145. data/lib/rubbycop/cop/lint/handle_exceptions.rb +56 -0
  146. data/lib/rubbycop/cop/lint/implicit_string_concatenation.rb +95 -0
  147. data/lib/rubbycop/cop/lint/ineffective_access_modifier.rb +143 -0
  148. data/lib/rubbycop/cop/lint/inherit_exception.rb +83 -0
  149. data/lib/rubbycop/cop/lint/invalid_character_literal.rb +41 -0
  150. data/lib/rubbycop/cop/lint/literal_in_condition.rb +127 -0
  151. data/lib/rubbycop/cop/lint/literal_in_interpolation.rb +76 -0
  152. data/lib/rubbycop/cop/lint/loop.rb +63 -0
  153. data/lib/rubbycop/cop/lint/multiple_compare.rb +48 -0
  154. data/lib/rubbycop/cop/lint/nested_method_definition.rb +105 -0
  155. data/lib/rubbycop/cop/lint/next_without_accumulator.rb +50 -0
  156. data/lib/rubbycop/cop/lint/non_local_exit_from_iterator.rb +85 -0
  157. data/lib/rubbycop/cop/lint/parentheses_as_grouped_expression.rb +60 -0
  158. data/lib/rubbycop/cop/lint/percent_string_array.rb +84 -0
  159. data/lib/rubbycop/cop/lint/percent_symbol_array.rb +66 -0
  160. data/lib/rubbycop/cop/lint/rand_one.rb +39 -0
  161. data/lib/rubbycop/cop/lint/require_parentheses.rb +61 -0
  162. data/lib/rubbycop/cop/lint/rescue_exception.rb +45 -0
  163. data/lib/rubbycop/cop/lint/safe_navigation_chain.rb +70 -0
  164. data/lib/rubbycop/cop/lint/shadowed_exception.rb +132 -0
  165. data/lib/rubbycop/cop/lint/shadowing_outer_local_variable.rb +53 -0
  166. data/lib/rubbycop/cop/lint/string_conversion_in_interpolation.rb +58 -0
  167. data/lib/rubbycop/cop/lint/syntax.rb +55 -0
  168. data/lib/rubbycop/cop/lint/underscore_prefixed_variable_name.rb +62 -0
  169. data/lib/rubbycop/cop/lint/unified_integer.rb +42 -0
  170. data/lib/rubbycop/cop/lint/unneeded_disable.rb +231 -0
  171. data/lib/rubbycop/cop/lint/unneeded_splat_expansion.rb +141 -0
  172. data/lib/rubbycop/cop/lint/unreachable_code.rb +52 -0
  173. data/lib/rubbycop/cop/lint/unused_block_argument.rb +145 -0
  174. data/lib/rubbycop/cop/lint/unused_method_argument.rb +61 -0
  175. data/lib/rubbycop/cop/lint/useless_access_modifier.rb +229 -0
  176. data/lib/rubbycop/cop/lint/useless_assignment.rb +132 -0
  177. data/lib/rubbycop/cop/lint/useless_comparison.rb +28 -0
  178. data/lib/rubbycop/cop/lint/useless_else_without_rescue.rb +46 -0
  179. data/lib/rubbycop/cop/lint/useless_setter_call.rb +162 -0
  180. data/lib/rubbycop/cop/lint/void.rb +108 -0
  181. data/lib/rubbycop/cop/message_annotator.rb +116 -0
  182. data/lib/rubbycop/cop/metrics/abc_size.rb +39 -0
  183. data/lib/rubbycop/cop/metrics/block_length.rb +32 -0
  184. data/lib/rubbycop/cop/metrics/block_nesting.rb +64 -0
  185. data/lib/rubbycop/cop/metrics/class_length.rb +24 -0
  186. data/lib/rubbycop/cop/metrics/cyclomatic_complexity.rb +31 -0
  187. data/lib/rubbycop/cop/metrics/line_length.rb +168 -0
  188. data/lib/rubbycop/cop/metrics/method_length.rb +27 -0
  189. data/lib/rubbycop/cop/metrics/module_length.rb +24 -0
  190. data/lib/rubbycop/cop/metrics/parameter_lists.rb +45 -0
  191. data/lib/rubbycop/cop/metrics/perceived_complexity.rb +61 -0
  192. data/lib/rubbycop/cop/mixin/access_modifier_node.rb +41 -0
  193. data/lib/rubbycop/cop/mixin/annotation_comment.rb +36 -0
  194. data/lib/rubbycop/cop/mixin/array_hash_indentation.rb +82 -0
  195. data/lib/rubbycop/cop/mixin/array_min_size.rb +59 -0
  196. data/lib/rubbycop/cop/mixin/array_syntax.rb +15 -0
  197. data/lib/rubbycop/cop/mixin/autocorrect_alignment.rb +149 -0
  198. data/lib/rubbycop/cop/mixin/check_assignment.rb +40 -0
  199. data/lib/rubbycop/cop/mixin/classish_length.rb +36 -0
  200. data/lib/rubbycop/cop/mixin/code_length.rb +32 -0
  201. data/lib/rubbycop/cop/mixin/configurable_enforced_style.rb +97 -0
  202. data/lib/rubbycop/cop/mixin/configurable_formatting.rb +48 -0
  203. data/lib/rubbycop/cop/mixin/configurable_max.rb +19 -0
  204. data/lib/rubbycop/cop/mixin/configurable_naming.rb +16 -0
  205. data/lib/rubbycop/cop/mixin/configurable_numbering.rb +17 -0
  206. data/lib/rubbycop/cop/mixin/def_node.rb +27 -0
  207. data/lib/rubbycop/cop/mixin/documentation_comment.rb +46 -0
  208. data/lib/rubbycop/cop/mixin/duplication.rb +46 -0
  209. data/lib/rubbycop/cop/mixin/empty_lines_around_body.rb +161 -0
  210. data/lib/rubbycop/cop/mixin/end_keyword_alignment.rb +85 -0
  211. data/lib/rubbycop/cop/mixin/enforce_superclass.rb +36 -0
  212. data/lib/rubbycop/cop/mixin/first_element_line_break.rb +41 -0
  213. data/lib/rubbycop/cop/mixin/frozen_string_literal.rb +37 -0
  214. data/lib/rubbycop/cop/mixin/hash_alignment.rb +116 -0
  215. data/lib/rubbycop/cop/mixin/ignored_pattern.rb +27 -0
  216. data/lib/rubbycop/cop/mixin/integer_node.rb +12 -0
  217. data/lib/rubbycop/cop/mixin/match_range.rb +22 -0
  218. data/lib/rubbycop/cop/mixin/method_complexity.rb +30 -0
  219. data/lib/rubbycop/cop/mixin/method_preference.rb +30 -0
  220. data/lib/rubbycop/cop/mixin/min_body_length.rb +19 -0
  221. data/lib/rubbycop/cop/mixin/multiline_expression_indentation.rb +183 -0
  222. data/lib/rubbycop/cop/mixin/multiline_literal_brace_layout.rb +152 -0
  223. data/lib/rubbycop/cop/mixin/negative_conditional.rb +43 -0
  224. data/lib/rubbycop/cop/mixin/on_method_def.rb +44 -0
  225. data/lib/rubbycop/cop/mixin/on_normal_if_unless.rb +14 -0
  226. data/lib/rubbycop/cop/mixin/parentheses.rb +22 -0
  227. data/lib/rubbycop/cop/mixin/parser_diagnostic.rb +34 -0
  228. data/lib/rubbycop/cop/mixin/percent_literal.rb +100 -0
  229. data/lib/rubbycop/cop/mixin/preceding_following_alignment.rb +89 -0
  230. data/lib/rubbycop/cop/mixin/rescue_node.rb +21 -0
  231. data/lib/rubbycop/cop/mixin/safe_assignment.rb +20 -0
  232. data/lib/rubbycop/cop/mixin/safe_mode.rb +22 -0
  233. data/lib/rubbycop/cop/mixin/space_after_punctuation.rb +55 -0
  234. data/lib/rubbycop/cop/mixin/space_before_punctuation.rb +48 -0
  235. data/lib/rubbycop/cop/mixin/space_inside.rb +76 -0
  236. data/lib/rubbycop/cop/mixin/statement_modifier.rb +69 -0
  237. data/lib/rubbycop/cop/mixin/string_help.rb +33 -0
  238. data/lib/rubbycop/cop/mixin/string_literals_help.rb +33 -0
  239. data/lib/rubbycop/cop/mixin/surrounding_space.rb +40 -0
  240. data/lib/rubbycop/cop/mixin/target_rails_version.rb +16 -0
  241. data/lib/rubbycop/cop/mixin/target_ruby_version.rb +16 -0
  242. data/lib/rubbycop/cop/mixin/too_many_lines.rb +39 -0
  243. data/lib/rubbycop/cop/mixin/trailing_comma.rb +161 -0
  244. data/lib/rubbycop/cop/mixin/unused_argument.rb +42 -0
  245. data/lib/rubbycop/cop/offense.rb +188 -0
  246. data/lib/rubbycop/cop/performance/caller.rb +41 -0
  247. data/lib/rubbycop/cop/performance/case_when_splat.rb +176 -0
  248. data/lib/rubbycop/cop/performance/casecmp.rb +107 -0
  249. data/lib/rubbycop/cop/performance/compare_with_block.rb +107 -0
  250. data/lib/rubbycop/cop/performance/count.rb +98 -0
  251. data/lib/rubbycop/cop/performance/detect.rb +107 -0
  252. data/lib/rubbycop/cop/performance/double_start_end_with.rb +102 -0
  253. data/lib/rubbycop/cop/performance/end_with.rb +55 -0
  254. data/lib/rubbycop/cop/performance/fixed_size.rb +56 -0
  255. data/lib/rubbycop/cop/performance/flat_map.rb +73 -0
  256. data/lib/rubbycop/cop/performance/hash_each_methods.rb +84 -0
  257. data/lib/rubbycop/cop/performance/lstrip_rstrip.rb +41 -0
  258. data/lib/rubbycop/cop/performance/range_include.rb +41 -0
  259. data/lib/rubbycop/cop/performance/redundant_block_call.rb +93 -0
  260. data/lib/rubbycop/cop/performance/redundant_match.rb +55 -0
  261. data/lib/rubbycop/cop/performance/redundant_merge.rb +149 -0
  262. data/lib/rubbycop/cop/performance/redundant_sort_by.rb +45 -0
  263. data/lib/rubbycop/cop/performance/regexp_match.rb +215 -0
  264. data/lib/rubbycop/cop/performance/reverse_each.rb +40 -0
  265. data/lib/rubbycop/cop/performance/sample.rb +140 -0
  266. data/lib/rubbycop/cop/performance/size.rb +71 -0
  267. data/lib/rubbycop/cop/performance/start_with.rb +58 -0
  268. data/lib/rubbycop/cop/performance/string_replacement.rb +170 -0
  269. data/lib/rubbycop/cop/performance/times_map.rb +61 -0
  270. data/lib/rubbycop/cop/rails/action_filter.rb +96 -0
  271. data/lib/rubbycop/cop/rails/active_support_aliases.rb +68 -0
  272. data/lib/rubbycop/cop/rails/application_job.rb +32 -0
  273. data/lib/rubbycop/cop/rails/application_record.rb +32 -0
  274. data/lib/rubbycop/cop/rails/blank.rb +138 -0
  275. data/lib/rubbycop/cop/rails/date.rb +127 -0
  276. data/lib/rubbycop/cop/rails/delegate.rb +106 -0
  277. data/lib/rubbycop/cop/rails/delegate_allow_blank.rb +51 -0
  278. data/lib/rubbycop/cop/rails/dynamic_find_by.rb +81 -0
  279. data/lib/rubbycop/cop/rails/enum_uniqueness.rb +43 -0
  280. data/lib/rubbycop/cop/rails/exit.rb +61 -0
  281. data/lib/rubbycop/cop/rails/file_path.rb +75 -0
  282. data/lib/rubbycop/cop/rails/find_by.rb +51 -0
  283. data/lib/rubbycop/cop/rails/find_each.rb +47 -0
  284. data/lib/rubbycop/cop/rails/has_and_belongs_to_many.rb +18 -0
  285. data/lib/rubbycop/cop/rails/http_positional_arguments.rb +106 -0
  286. data/lib/rubbycop/cop/rails/not_null_column.rb +67 -0
  287. data/lib/rubbycop/cop/rails/output.rb +23 -0
  288. data/lib/rubbycop/cop/rails/output_safety.rb +58 -0
  289. data/lib/rubbycop/cop/rails/pluralization_grammar.rb +106 -0
  290. data/lib/rubbycop/cop/rails/present.rb +143 -0
  291. data/lib/rubbycop/cop/rails/read_write_attribute.rb +65 -0
  292. data/lib/rubbycop/cop/rails/relative_date_constant.rb +88 -0
  293. data/lib/rubbycop/cop/rails/request_referer.rb +56 -0
  294. data/lib/rubbycop/cop/rails/reversible_migration.rb +216 -0
  295. data/lib/rubbycop/cop/rails/safe_navigation.rb +91 -0
  296. data/lib/rubbycop/cop/rails/save_bang.rb +160 -0
  297. data/lib/rubbycop/cop/rails/scope_args.rb +29 -0
  298. data/lib/rubbycop/cop/rails/skips_model_validations.rb +63 -0
  299. data/lib/rubbycop/cop/rails/time_zone.rb +197 -0
  300. data/lib/rubbycop/cop/rails/uniq_before_pluck.rb +93 -0
  301. data/lib/rubbycop/cop/rails/validation.rb +64 -0
  302. data/lib/rubbycop/cop/registry.rb +171 -0
  303. data/lib/rubbycop/cop/security/eval.rb +30 -0
  304. data/lib/rubbycop/cop/security/json_load.rb +44 -0
  305. data/lib/rubbycop/cop/security/marshal_load.rb +37 -0
  306. data/lib/rubbycop/cop/security/yaml_load.rb +37 -0
  307. data/lib/rubbycop/cop/severity.rb +76 -0
  308. data/lib/rubbycop/cop/style/accessor_method_name.rb +45 -0
  309. data/lib/rubbycop/cop/style/alias.rb +119 -0
  310. data/lib/rubbycop/cop/style/and_or.rb +125 -0
  311. data/lib/rubbycop/cop/style/array_join.rb +30 -0
  312. data/lib/rubbycop/cop/style/ascii_comments.rb +38 -0
  313. data/lib/rubbycop/cop/style/ascii_identifiers.rb +36 -0
  314. data/lib/rubbycop/cop/style/attr.rb +50 -0
  315. data/lib/rubbycop/cop/style/auto_resource_cleanup.rb +42 -0
  316. data/lib/rubbycop/cop/style/bare_percent_literals.rb +57 -0
  317. data/lib/rubbycop/cop/style/begin_block.rb +16 -0
  318. data/lib/rubbycop/cop/style/block_comments.rb +46 -0
  319. data/lib/rubbycop/cop/style/block_delimiters.rb +228 -0
  320. data/lib/rubbycop/cop/style/braces_around_hash_parameters.rb +138 -0
  321. data/lib/rubbycop/cop/style/case_equality.rb +18 -0
  322. data/lib/rubbycop/cop/style/character_literal.rb +43 -0
  323. data/lib/rubbycop/cop/style/class_and_module_camel_case.rb +29 -0
  324. data/lib/rubbycop/cop/style/class_and_module_children.rb +69 -0
  325. data/lib/rubbycop/cop/style/class_check.rb +40 -0
  326. data/lib/rubbycop/cop/style/class_methods.rb +67 -0
  327. data/lib/rubbycop/cop/style/class_vars.rb +23 -0
  328. data/lib/rubbycop/cop/style/collection_methods.rb +51 -0
  329. data/lib/rubbycop/cop/style/colon_method_call.rb +33 -0
  330. data/lib/rubbycop/cop/style/command_literal.rb +119 -0
  331. data/lib/rubbycop/cop/style/comment_annotation.rb +62 -0
  332. data/lib/rubbycop/cop/style/conditional_assignment.rb +691 -0
  333. data/lib/rubbycop/cop/style/constant_name.rb +29 -0
  334. data/lib/rubbycop/cop/style/copyright.rb +89 -0
  335. data/lib/rubbycop/cop/style/def_with_parentheses.rb +31 -0
  336. data/lib/rubbycop/cop/style/documentation.rb +79 -0
  337. data/lib/rubbycop/cop/style/documentation_method.rb +80 -0
  338. data/lib/rubbycop/cop/style/double_negation.rb +35 -0
  339. data/lib/rubbycop/cop/style/each_for_simple_loop.rb +57 -0
  340. data/lib/rubbycop/cop/style/each_with_object.rb +91 -0
  341. data/lib/rubbycop/cop/style/empty_case_condition.rb +84 -0
  342. data/lib/rubbycop/cop/style/empty_else.rb +138 -0
  343. data/lib/rubbycop/cop/style/empty_literal.rb +108 -0
  344. data/lib/rubbycop/cop/style/empty_method.rb +102 -0
  345. data/lib/rubbycop/cop/style/encoding.rb +92 -0
  346. data/lib/rubbycop/cop/style/end_block.rb +17 -0
  347. data/lib/rubbycop/cop/style/even_odd.rb +56 -0
  348. data/lib/rubbycop/cop/style/file_name.rb +183 -0
  349. data/lib/rubbycop/cop/style/flip_flop.rb +20 -0
  350. data/lib/rubbycop/cop/style/for.rb +50 -0
  351. data/lib/rubbycop/cop/style/format_string.rb +46 -0
  352. data/lib/rubbycop/cop/style/format_string_token.rb +141 -0
  353. data/lib/rubbycop/cop/style/frozen_string_literal_comment.rb +96 -0
  354. data/lib/rubbycop/cop/style/global_vars.rb +70 -0
  355. data/lib/rubbycop/cop/style/guard_clause.rb +90 -0
  356. data/lib/rubbycop/cop/style/hash_syntax.rb +214 -0
  357. data/lib/rubbycop/cop/style/identical_conditional_branches.rb +130 -0
  358. data/lib/rubbycop/cop/style/if_inside_else.rb +45 -0
  359. data/lib/rubbycop/cop/style/if_unless_modifier.rb +80 -0
  360. data/lib/rubbycop/cop/style/if_unless_modifier_of_if_unless.rb +38 -0
  361. data/lib/rubbycop/cop/style/if_with_semicolon.rb +20 -0
  362. data/lib/rubbycop/cop/style/implicit_runtime_error.rb +31 -0
  363. data/lib/rubbycop/cop/style/infinite_loop.rb +91 -0
  364. data/lib/rubbycop/cop/style/inline_comment.rb +32 -0
  365. data/lib/rubbycop/cop/style/inverse_methods.rb +130 -0
  366. data/lib/rubbycop/cop/style/lambda.rb +209 -0
  367. data/lib/rubbycop/cop/style/lambda_call.rb +66 -0
  368. data/lib/rubbycop/cop/style/line_end_concatenation.rb +115 -0
  369. data/lib/rubbycop/cop/style/method_call_with_args_parentheses.rb +107 -0
  370. data/lib/rubbycop/cop/style/method_call_without_args_parentheses.rb +75 -0
  371. data/lib/rubbycop/cop/style/method_called_on_do_end_block.rb +44 -0
  372. data/lib/rubbycop/cop/style/method_def_parentheses.rb +83 -0
  373. data/lib/rubbycop/cop/style/method_missing.rb +81 -0
  374. data/lib/rubbycop/cop/style/method_name.rb +28 -0
  375. data/lib/rubbycop/cop/style/missing_else.rb +100 -0
  376. data/lib/rubbycop/cop/style/mixin_grouping.rb +135 -0
  377. data/lib/rubbycop/cop/style/module_function.rb +64 -0
  378. data/lib/rubbycop/cop/style/multiline_block_chain.rb +42 -0
  379. data/lib/rubbycop/cop/style/multiline_if_modifier.rb +63 -0
  380. data/lib/rubbycop/cop/style/multiline_if_then.rb +47 -0
  381. data/lib/rubbycop/cop/style/multiline_memoization.rb +77 -0
  382. data/lib/rubbycop/cop/style/multiline_ternary_operator.rb +19 -0
  383. data/lib/rubbycop/cop/style/mutable_constant.rb +68 -0
  384. data/lib/rubbycop/cop/style/negated_if.rb +103 -0
  385. data/lib/rubbycop/cop/style/negated_while.rb +32 -0
  386. data/lib/rubbycop/cop/style/nested_modifier.rb +87 -0
  387. data/lib/rubbycop/cop/style/nested_parenthesized_calls.rb +61 -0
  388. data/lib/rubbycop/cop/style/nested_ternary_operator.rb +21 -0
  389. data/lib/rubbycop/cop/style/next.rb +225 -0
  390. data/lib/rubbycop/cop/style/nil_comparison.rb +35 -0
  391. data/lib/rubbycop/cop/style/non_nil_check.rb +121 -0
  392. data/lib/rubbycop/cop/style/not.rb +69 -0
  393. data/lib/rubbycop/cop/style/numeric_literal_prefix.rb +97 -0
  394. data/lib/rubbycop/cop/style/numeric_literals.rb +101 -0
  395. data/lib/rubbycop/cop/style/numeric_predicate.rb +140 -0
  396. data/lib/rubbycop/cop/style/one_line_conditional.rb +75 -0
  397. data/lib/rubbycop/cop/style/op_method.rb +41 -0
  398. data/lib/rubbycop/cop/style/option_hash.rb +58 -0
  399. data/lib/rubbycop/cop/style/optional_arguments.rb +62 -0
  400. data/lib/rubbycop/cop/style/parallel_assignment.rb +287 -0
  401. data/lib/rubbycop/cop/style/parentheses_around_condition.rb +56 -0
  402. data/lib/rubbycop/cop/style/percent_literal_delimiters.rb +100 -0
  403. data/lib/rubbycop/cop/style/percent_q_literals.rb +52 -0
  404. data/lib/rubbycop/cop/style/perl_backrefs.rb +31 -0
  405. data/lib/rubbycop/cop/style/predicate_name.rb +67 -0
  406. data/lib/rubbycop/cop/style/preferred_hash_methods.rb +78 -0
  407. data/lib/rubbycop/cop/style/proc.rb +26 -0
  408. data/lib/rubbycop/cop/style/raise_args.rb +140 -0
  409. data/lib/rubbycop/cop/style/redundant_begin.rb +47 -0
  410. data/lib/rubbycop/cop/style/redundant_exception.rb +55 -0
  411. data/lib/rubbycop/cop/style/redundant_freeze.rb +45 -0
  412. data/lib/rubbycop/cop/style/redundant_parentheses.rb +199 -0
  413. data/lib/rubbycop/cop/style/redundant_return.rb +121 -0
  414. data/lib/rubbycop/cop/style/redundant_self.rb +144 -0
  415. data/lib/rubbycop/cop/style/regexp_literal.rb +114 -0
  416. data/lib/rubbycop/cop/style/rescue_modifier.rb +37 -0
  417. data/lib/rubbycop/cop/style/safe_navigation.rb +145 -0
  418. data/lib/rubbycop/cop/style/self_assignment.rb +93 -0
  419. data/lib/rubbycop/cop/style/semicolon.rb +70 -0
  420. data/lib/rubbycop/cop/style/send.rb +21 -0
  421. data/lib/rubbycop/cop/style/signal_exception.rb +109 -0
  422. data/lib/rubbycop/cop/style/single_line_block_params.rb +68 -0
  423. data/lib/rubbycop/cop/style/single_line_methods.rb +77 -0
  424. data/lib/rubbycop/cop/style/special_global_vars.rb +156 -0
  425. data/lib/rubbycop/cop/style/stabby_lambda_parentheses.rb +113 -0
  426. data/lib/rubbycop/cop/style/string_literals.rb +102 -0
  427. data/lib/rubbycop/cop/style/string_literals_in_interpolation.rb +30 -0
  428. data/lib/rubbycop/cop/style/string_methods.rb +34 -0
  429. data/lib/rubbycop/cop/style/struct_inheritance.rb +32 -0
  430. data/lib/rubbycop/cop/style/symbol_array.rb +109 -0
  431. data/lib/rubbycop/cop/style/symbol_literal.rb +32 -0
  432. data/lib/rubbycop/cop/style/symbol_proc.rb +143 -0
  433. data/lib/rubbycop/cop/style/ternary_parentheses.rb +200 -0
  434. data/lib/rubbycop/cop/style/trailing_comma_in_arguments.rb +64 -0
  435. data/lib/rubbycop/cop/style/trailing_comma_in_literal.rb +56 -0
  436. data/lib/rubbycop/cop/style/trailing_underscore_variable.rb +113 -0
  437. data/lib/rubbycop/cop/style/trivial_accessors.rb +176 -0
  438. data/lib/rubbycop/cop/style/unless_else.rb +39 -0
  439. data/lib/rubbycop/cop/style/unneeded_capital_w.rb +41 -0
  440. data/lib/rubbycop/cop/style/unneeded_interpolation.rb +98 -0
  441. data/lib/rubbycop/cop/style/unneeded_percent_q.rb +96 -0
  442. data/lib/rubbycop/cop/style/variable_interpolation.rb +44 -0
  443. data/lib/rubbycop/cop/style/variable_name.rb +39 -0
  444. data/lib/rubbycop/cop/style/variable_number.rb +78 -0
  445. data/lib/rubbycop/cop/style/when_then.rb +24 -0
  446. data/lib/rubbycop/cop/style/while_until_do.rb +36 -0
  447. data/lib/rubbycop/cop/style/while_until_modifier.rb +41 -0
  448. data/lib/rubbycop/cop/style/word_array.rb +114 -0
  449. data/lib/rubbycop/cop/style/zero_length_predicate.rb +90 -0
  450. data/lib/rubbycop/cop/team.rb +193 -0
  451. data/lib/rubbycop/cop/util.rb +309 -0
  452. data/lib/rubbycop/cop/variable_force.rb +458 -0
  453. data/lib/rubbycop/cop/variable_force/assignment.rb +90 -0
  454. data/lib/rubbycop/cop/variable_force/branch.rb +318 -0
  455. data/lib/rubbycop/cop/variable_force/branchable.rb +21 -0
  456. data/lib/rubbycop/cop/variable_force/reference.rb +49 -0
  457. data/lib/rubbycop/cop/variable_force/scope.rb +107 -0
  458. data/lib/rubbycop/cop/variable_force/variable.rb +103 -0
  459. data/lib/rubbycop/cop/variable_force/variable_table.rb +128 -0
  460. data/lib/rubbycop/error.rb +11 -0
  461. data/lib/rubbycop/formatter/base_formatter.rb +123 -0
  462. data/lib/rubbycop/formatter/clang_style_formatter.rb +54 -0
  463. data/lib/rubbycop/formatter/colorizable.rb +41 -0
  464. data/lib/rubbycop/formatter/disabled_config_formatter.rb +181 -0
  465. data/lib/rubbycop/formatter/disabled_lines_formatter.rb +57 -0
  466. data/lib/rubbycop/formatter/emacs_style_formatter.rb +24 -0
  467. data/lib/rubbycop/formatter/file_list_formatter.rb +19 -0
  468. data/lib/rubbycop/formatter/formatter_set.rb +102 -0
  469. data/lib/rubbycop/formatter/fuubar_style_formatter.rb +80 -0
  470. data/lib/rubbycop/formatter/html_formatter.rb +134 -0
  471. data/lib/rubbycop/formatter/json_formatter.rb +74 -0
  472. data/lib/rubbycop/formatter/offense_count_formatter.rb +55 -0
  473. data/lib/rubbycop/formatter/progress_formatter.rb +63 -0
  474. data/lib/rubbycop/formatter/simple_text_formatter.rb +136 -0
  475. data/lib/rubbycop/formatter/text_util.rb +20 -0
  476. data/lib/rubbycop/formatter/worst_offenders_formatter.rb +60 -0
  477. data/lib/rubbycop/magic_comment.rb +210 -0
  478. data/lib/rubbycop/name_similarity.rb +21 -0
  479. data/lib/rubbycop/node_pattern.rb +543 -0
  480. data/lib/rubbycop/options.rb +355 -0
  481. data/lib/rubbycop/path_util.rb +36 -0
  482. data/lib/rubbycop/platform.rb +11 -0
  483. data/lib/rubbycop/processed_source.rb +151 -0
  484. data/lib/rubbycop/rake_task.rb +86 -0
  485. data/lib/rubbycop/remote_config.rb +78 -0
  486. data/lib/rubbycop/result_cache.rb +176 -0
  487. data/lib/rubbycop/rspec/cop_helper.rb +98 -0
  488. data/lib/rubbycop/rspec/host_environment_simulation_helper.rb +32 -0
  489. data/lib/rubbycop/rspec/shared_contexts.rb +98 -0
  490. data/lib/rubbycop/rspec/shared_examples.rb +92 -0
  491. data/lib/rubbycop/rspec/support.rb +8 -0
  492. data/lib/rubbycop/runner.rb +338 -0
  493. data/lib/rubbycop/string_interpreter.rb +57 -0
  494. data/lib/rubbycop/string_util.rb +156 -0
  495. data/lib/rubbycop/target_finder.rb +201 -0
  496. data/lib/rubbycop/token.rb +25 -0
  497. data/lib/rubbycop/version.rb +19 -0
  498. data/lib/rubbycop/warning.rb +11 -0
  499. metadata +663 -0
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubbyCop
4
+ module Cop
5
+ module Style
6
+ # This cop checks for numeric comparisons that can be replaced
7
+ # by a predicate method, such as receiver.length == 0,
8
+ # receiver.length > 0, receiver.length != 0,
9
+ # receiver.length < 1 and receiver.size == 0 that can be
10
+ # replaced by receiver.empty? and !receiver.empty.
11
+ #
12
+ # @example
13
+ #
14
+ # @bad
15
+ # [1, 2, 3].length == 0
16
+ # 0 == "foobar".length
17
+ # array.length < 1
18
+ # {a: 1, b: 2}.length != 0
19
+ # string.length > 0
20
+ # hash.size > 0
21
+ #
22
+ # @good
23
+ # [1, 2, 3].empty?
24
+ # "foobar".empty?
25
+ # array.empty?
26
+ # !{a: 1, b: 2}.empty?
27
+ # !string.empty?
28
+ # !hash.empty?
29
+ class ZeroLengthPredicate < Cop
30
+ ZERO_MSG = 'Use `empty?` instead of `%s %s %s`.'.freeze
31
+ NONZERO_MSG = 'Use `!empty?` instead of `%s %s %s`.'.freeze
32
+
33
+ def on_send(node)
34
+ zero_length_predicate = zero_length_predicate(node)
35
+
36
+ if zero_length_predicate
37
+ add_offense(node, :expression,
38
+ format(ZERO_MSG, *zero_length_predicate))
39
+ end
40
+
41
+ nonzero_length_predicate = nonzero_length_predicate(node)
42
+
43
+ # rubbycop:disable Style/GuardClause
44
+ if nonzero_length_predicate
45
+ add_offense(node, :expression,
46
+ format(NONZERO_MSG, *nonzero_length_predicate))
47
+ end
48
+ # rubbycop:enable Style/GuardClause
49
+ end
50
+
51
+ def_node_matcher :zero_length_predicate, <<-END
52
+ {(send (send (...) ${:length :size}) $:== (int $0))
53
+ (send (int $0) $:== (send (...) ${:length :size}))
54
+ (send (send (...) ${:length :size}) $:< (int $1))
55
+ (send (int $1) $:> (send (...) ${:length :size}))}
56
+ END
57
+
58
+ def_node_matcher :nonzero_length_predicate, <<-END
59
+ {(send (send (...) ${:length :size}) ${:> :!=} (int $0))
60
+ (send (int $0) ${:< :!=} (send (...) ${:length :size}))}
61
+ END
62
+
63
+ def autocorrect(node)
64
+ lambda do |corrector|
65
+ corrector.replace(node.loc.expression, replacement(node))
66
+ end
67
+ end
68
+
69
+ def replacement(node)
70
+ receiver = zero_length_receiver(node)
71
+ return "#{receiver.source}.empty?" if receiver
72
+
73
+ "!#{other_receiver(node).source}.empty?"
74
+ end
75
+
76
+ def_node_matcher :zero_length_receiver, <<-END
77
+ {(send (send $_ _) :== (int 0))
78
+ (send (int 0) :== (send $_ _))
79
+ (send (send $_ _) :< (int 1))
80
+ (send (int 1) :> (send $_ _))}
81
+ END
82
+
83
+ def_node_matcher :other_receiver, <<-END
84
+ {(send (send $_ _) _ _)
85
+ (send _ _ (send $_ _))}
86
+ END
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubbyCop
4
+ module Cop
5
+ # FIXME
6
+ class Team
7
+ # If these cops try to autocorrect the same file at the same time,
8
+ # bad things are liable to happen
9
+ INCOMPATIBLE_COPS = {
10
+ Style::SymbolProc => [Layout::SpaceBeforeBlockBraces],
11
+ Layout::SpaceBeforeBlockBraces => [Style::SymbolProc],
12
+ Style::LineEndConcatenation => [Style::UnneededInterpolation],
13
+ Style::UnneededInterpolation => [Style::LineEndConcatenation],
14
+ Style::SelfAssignment => [Layout::SpaceAroundOperators],
15
+ Layout::SpaceAroundOperators => [Style::SelfAssignment],
16
+ Style::BracesAroundHashParameters => [Layout::MultilineHashBraceLayout]
17
+ }.freeze
18
+
19
+ DEFAULT_OPTIONS = {
20
+ auto_correct: false,
21
+ debug: false
22
+ }.freeze
23
+
24
+ Investigation = Struct.new(:offenses, :errors)
25
+
26
+ attr_reader :errors, :warnings, :updated_source_file
27
+
28
+ alias updated_source_file? updated_source_file
29
+
30
+ def initialize(cop_classes, config, options = nil)
31
+ @cop_classes = cop_classes
32
+ @config = config
33
+ @options = options || DEFAULT_OPTIONS
34
+ @errors = []
35
+ @warnings = []
36
+
37
+ validate_config
38
+ end
39
+
40
+ def autocorrect?
41
+ @options[:auto_correct]
42
+ end
43
+
44
+ def debug?
45
+ @options[:debug]
46
+ end
47
+
48
+ def inspect_file(processed_source)
49
+ # If we got any syntax errors, return only the syntax offenses.
50
+ unless processed_source.valid_syntax?
51
+ return Lint::Syntax.offenses_from_processed_source(processed_source)
52
+ end
53
+
54
+ offenses(processed_source)
55
+ end
56
+
57
+ def cops
58
+ only_options = @options.fetch(:only, [])
59
+ @cops ||= @cop_classes.enabled(@config, only_options).map do |cop_class|
60
+ cop_class.new(@config, @options)
61
+ end
62
+ end
63
+
64
+ def forces
65
+ @forces ||= forces_for(cops)
66
+ end
67
+
68
+ def forces_for(cops)
69
+ Force.all.each_with_object([]) do |force_class, forces|
70
+ joining_cops = cops.select { |cop| cop.join_force?(force_class) }
71
+ next if joining_cops.empty?
72
+ forces << force_class.new(joining_cops)
73
+ end
74
+ end
75
+
76
+ def autocorrect(buffer, cops)
77
+ @updated_source_file = false
78
+ return unless autocorrect?
79
+
80
+ new_source = autocorrect_all_cops(buffer, cops)
81
+
82
+ return if new_source == buffer.source
83
+
84
+ if @options[:stdin]
85
+ # holds source read in from stdin, when --stdin option is used
86
+ @options[:stdin] = new_source
87
+ else
88
+ filename = buffer.name
89
+ File.open(filename, 'w') { |f| f.write(new_source) }
90
+ end
91
+ @updated_source_file = true
92
+ end
93
+
94
+ private
95
+
96
+ def offenses(processed_source)
97
+ # The autocorrection process may have to be repeated multiple times
98
+ # until there are no corrections left to perform
99
+ # To speed things up, run auto-correcting cops by themselves, and only
100
+ # run the other cops when no corrections are left
101
+ autocorrect_cops, other_cops = cops.partition(&:autocorrect?)
102
+
103
+ autocorrect =
104
+ investigate(autocorrect_cops, processed_source) do |offenses|
105
+ # We corrected some errors. Another round of inspection will be
106
+ # done, and any other offenses will be caught then, so we don't
107
+ # need to continue.
108
+ return offenses if autocorrect(processed_source.buffer,
109
+ autocorrect_cops)
110
+ end
111
+
112
+ other = investigate(other_cops, processed_source)
113
+
114
+ errors = autocorrect.errors.merge(other.errors)
115
+ process_commissioner_errors(processed_source.path, errors)
116
+
117
+ autocorrect.offenses.concat(other.offenses)
118
+ end
119
+
120
+ def investigate(cops, processed_source)
121
+ return Investigation.new([], {}) if cops.empty?
122
+
123
+ commissioner = Commissioner.new(cops, forces_for(cops))
124
+ offenses = commissioner.investigate(processed_source)
125
+ yield offenses if block_given?
126
+
127
+ Investigation.new(offenses, commissioner.errors)
128
+ end
129
+
130
+ def autocorrect_all_cops(buffer, cops)
131
+ corrector = Corrector.new(buffer)
132
+ skip = Set.new
133
+
134
+ cops.each do |cop|
135
+ next if cop.corrections.empty?
136
+ next if skip.include?(cop.class)
137
+ corrector.corrections.concat(cop.corrections)
138
+ incompatible = INCOMPATIBLE_COPS[cop.class]
139
+ skip.merge(incompatible) if incompatible
140
+ end
141
+
142
+ if !corrector.corrections.empty?
143
+ corrector.rewrite
144
+ else
145
+ buffer.source
146
+ end
147
+ end
148
+
149
+ def validate_config
150
+ cops.each do |cop|
151
+ cop.validate_config if cop.respond_to?(:validate_config)
152
+ end
153
+ end
154
+
155
+ def process_commissioner_errors(file, file_errors)
156
+ file_errors.each do |cop, errors|
157
+ errors.each do |cop_error|
158
+ e = cop_error.error
159
+ line = ":#{cop_error.line}" if cop_error.line
160
+ column = ":#{cop_error.column}" if cop_error.column
161
+ location = "#{file}#{line}#{column}"
162
+
163
+ if e.is_a?(Warning)
164
+ handle_warning(e, location)
165
+ else
166
+ handle_error(e, location, cop)
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ def handle_warning(e, location)
173
+ message = Rainbow("#{e.message} (from file: #{location})").yellow
174
+
175
+ @warnings << message
176
+ warn message
177
+ puts e.backtrace if debug?
178
+ end
179
+
180
+ def handle_error(e, location, cop)
181
+ message = Rainbow("An error occurred while #{cop.name}" \
182
+ " cop was inspecting #{location}.").red
183
+ @errors << message
184
+ warn message
185
+ if debug?
186
+ puts e.message, e.backtrace
187
+ else
188
+ warn 'To see the complete backtrace run rubbycop -d.'
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,309 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubbycop:disable Metrics/ModuleLength
4
+ module RubbyCop
5
+ module Cop
6
+ # This module contains a collection of useful utility methods.
7
+ module Util
8
+ include PathUtil
9
+ extend RubbyCop::AST::Sexp
10
+
11
+ BYTE_ORDER_MARK = 0xfeff # The Unicode codepoint
12
+
13
+ EQUALS_ASGN_NODES = %i[lvasgn ivasgn cvasgn gvasgn
14
+ casgn masgn].freeze
15
+ SHORTHAND_ASGN_NODES = %i[op_asgn or_asgn and_asgn].freeze
16
+ ASGN_NODES = (EQUALS_ASGN_NODES + SHORTHAND_ASGN_NODES).freeze
17
+
18
+ MODIFIER_NODES = %i[if while until].freeze
19
+ CONDITIONAL_NODES = (MODIFIER_NODES + [:case]).freeze
20
+ LOGICAL_OPERATOR_NODES = %i[and or].freeze
21
+
22
+ # http://phrogz.net/programmingruby/language.html#table_18.4
23
+ # Backtick is added last just to help editors parse this code.
24
+ OPERATOR_METHODS = %w(
25
+ | ^ & <=> == === =~ > >= < <= << >>
26
+ + - * / % ** ~ +@ -@ [] []= ! != !~
27
+ ).map(&:to_sym).push(:'`').freeze
28
+
29
+ # Match literal regex characters, not including anchors, character
30
+ # classes, alternatives, groups, repetitions, references, etc
31
+ LITERAL_REGEX = /[\w\s\-,"'!#%&<>=;:`~]|\\[^AbBdDgGhHkpPRwWXsSzZ0-9]/
32
+
33
+ module_function
34
+
35
+ def operator?(symbol)
36
+ OPERATOR_METHODS.include?(symbol)
37
+ end
38
+
39
+ def strip_quotes(str)
40
+ if str[0] == '"' || str[0] == "'"
41
+ str[0] = ''
42
+ else
43
+ # we're dealing with %q or %Q
44
+ str[0, 3] = ''
45
+ end
46
+ str[-1] = ''
47
+
48
+ str
49
+ end
50
+
51
+ def block_length(block_node)
52
+ block_node.loc.end.line - block_node.loc.begin.line
53
+ end
54
+
55
+ def comment_line?(line_source)
56
+ line_source =~ /^\s*#/
57
+ end
58
+
59
+ def line_range(arg)
60
+ source_range = case arg
61
+ when Parser::Source::Range
62
+ arg
63
+ when Parser::AST::Node
64
+ arg.source_range
65
+ else
66
+ raise ArgumentError, "Invalid argument #{arg}"
67
+ end
68
+
69
+ source_range.begin.line..source_range.end.line
70
+ end
71
+
72
+ def parentheses?(node)
73
+ node.loc.respond_to?(:end) && node.loc.end &&
74
+ node.loc.end.is?(')'.freeze)
75
+ end
76
+
77
+ def parenthesized_call?(send)
78
+ send.loc.begin && send.loc.begin.is?('(')
79
+ end
80
+
81
+ def on_node(syms, sexp, excludes = [], &block)
82
+ return to_enum(:on_node, syms, sexp, excludes) unless block_given?
83
+
84
+ yield sexp if Array(syms).include?(sexp.type)
85
+ return if Array(excludes).include?(sexp.type)
86
+
87
+ sexp.each_child_node { |elem| on_node(syms, elem, excludes, &block) }
88
+ end
89
+
90
+ def source_range(source_buffer, line_number, column, length = 1)
91
+ if column.is_a?(Range)
92
+ column_index = column.begin
93
+ length = column.size
94
+ else
95
+ column_index = column
96
+ end
97
+
98
+ line_begin_pos = if line_number.zero?
99
+ 0
100
+ else
101
+ source_buffer.line_range(line_number).begin_pos
102
+ end
103
+ begin_pos = line_begin_pos + column_index
104
+ end_pos = begin_pos + length
105
+
106
+ Parser::Source::Range.new(source_buffer, begin_pos, end_pos)
107
+ end
108
+
109
+ # Returns the column attribute of the range, except if the range is on
110
+ # the first line and there's a byte order mark at the beginning of that
111
+ # line, in which case 1 is subtracted from the column value. This gives
112
+ # the column as it appears when viewing the file in an editor.
113
+ def effective_column(range)
114
+ if range.line == 1 &&
115
+ @processed_source.raw_source.codepoints.first == BYTE_ORDER_MARK
116
+ range.column - 1
117
+ else
118
+ range.column
119
+ end
120
+ end
121
+
122
+ def range_between(start_pos, end_pos)
123
+ Parser::Source::Range.new(processed_source.buffer, start_pos, end_pos)
124
+ end
125
+
126
+ def range_with_surrounding_comma(range, side = :both)
127
+ buffer = @processed_source.buffer
128
+ src = buffer.source
129
+
130
+ go_left, go_right = directions(side)
131
+
132
+ begin_pos = range.begin_pos
133
+ end_pos = range.end_pos
134
+ begin_pos = move_pos(src, begin_pos, -1, go_left, /,/)
135
+ end_pos = move_pos(src, end_pos, 1, go_right, /,/)
136
+
137
+ Parser::Source::Range.new(buffer, begin_pos, end_pos)
138
+ end
139
+
140
+ def range_with_surrounding_space(range, side = :both, with_newline = true)
141
+ buffer = @processed_source.buffer
142
+ src = buffer.source
143
+
144
+ go_left, go_right = directions(side)
145
+
146
+ begin_pos = range.begin_pos
147
+ end_pos = range.end_pos
148
+ begin_pos = move_pos(src, begin_pos, -1, go_left, /[ \t]/)
149
+ begin_pos = move_pos(src, begin_pos, -1, go_left && with_newline, /\n/)
150
+ end_pos = move_pos(src, end_pos, 1, go_right, /[ \t]/)
151
+ end_pos = move_pos(src, end_pos, 1, go_right && with_newline, /\n/)
152
+ Parser::Source::Range.new(buffer, begin_pos, end_pos)
153
+ end
154
+
155
+ def range_by_whole_lines(range, include_final_newline: false)
156
+ buffer = @processed_source.buffer
157
+
158
+ begin_pos = range.begin_pos
159
+ begin_offset = range.column
160
+ begin_of_first_line = begin_pos - begin_offset
161
+
162
+ last_line = buffer.source_line(range.last_line)
163
+ end_pos = range.end_pos
164
+ end_offset = last_line.length - range.last_column
165
+ end_offset += 1 if include_final_newline
166
+ end_of_last_line = end_pos + end_offset
167
+
168
+ Parser::Source::Range.new(buffer, begin_of_first_line, end_of_last_line)
169
+ end
170
+
171
+ def move_pos(src, pos, step, condition, regexp)
172
+ offset = step == -1 ? -1 : 0
173
+ pos += step while condition && src[pos + offset] =~ regexp
174
+ pos < 0 ? 0 : pos
175
+ end
176
+
177
+ def directions(side)
178
+ if side == :both
179
+ [true, true]
180
+ else
181
+ [side == :left, side == :right]
182
+ end
183
+ end
184
+
185
+ def begins_its_line?(range)
186
+ (range.source_line =~ /\S/) == range.column
187
+ end
188
+
189
+ def ends_its_line?(range)
190
+ line = range.source_buffer.source_line(range.last_line)
191
+ (line =~ /\s*\z/) == range.last_column
192
+ end
193
+
194
+ def within_node?(inner, outer)
195
+ o = outer.is_a?(AST::Node) ? outer.source_range : outer
196
+ i = inner.is_a?(AST::Node) ? inner.source_range : inner
197
+ i.begin_pos >= o.begin_pos && i.end_pos <= o.end_pos
198
+ end
199
+
200
+ # Returns, for example, a bare `if` node if the given node is an `if`
201
+ # with calls chained to the end of it.
202
+ def first_part_of_call_chain(node)
203
+ while node
204
+ case node.type
205
+ when :send
206
+ receiver, _method_name, _args = *node
207
+ node = receiver
208
+ when :block
209
+ method, _args, _body = *node
210
+ node = method
211
+ else
212
+ break
213
+ end
214
+ end
215
+ node
216
+ end
217
+
218
+ # If converting a string to Ruby string literal source code, must
219
+ # double quotes be used?
220
+ def double_quotes_required?(string)
221
+ # Double quotes are required for strings which either:
222
+ # - Contain single quotes
223
+ # - Contain non-printable characters, which must use an escape
224
+
225
+ # Regex matches IF there is a ' or there is a \\ in the string that is
226
+ # not preceded/followed by another \\ (e.g. "\\x34") but not "\\\\".
227
+ string =~ /'|(?<! \\) \\{2}* \\ (?![\\"])/x
228
+ end
229
+
230
+ def needs_escaping?(string)
231
+ double_quotes_required?(escape_string(string))
232
+ end
233
+
234
+ def escape_string(string)
235
+ string.inspect[1..-2].tap { |s| s.gsub!(/\\"/, '"') }
236
+ end
237
+
238
+ def to_string_literal(string)
239
+ if needs_escaping?(string) && compatible_external_encoding_for?(string)
240
+ string.inspect
241
+ else
242
+ "'#{string.gsub('\\') { '\\\\' }}'"
243
+ end
244
+ end
245
+
246
+ def to_symbol_literal(string)
247
+ if symbol_without_quote?(string)
248
+ ":#{string}"
249
+ else
250
+ ":#{to_string_literal(string)}"
251
+ end
252
+ end
253
+
254
+ def symbol_without_quote?(string)
255
+ special_gvars = %w[
256
+ $! $" $$ $& $' $* $+ $, $/ $; $: $. $< $= $> $? $@ $\\ $_ $` $~ $0
257
+ $-0 $-F $-I $-K $-W $-a $-d $-i $-l $-p $-v $-w
258
+ ]
259
+ redefinable_operators = %w(
260
+ | ^ & <=> == === =~ > >= < <= << >>
261
+ + - * / % ** ~ +@ -@ [] []= ` ! != !~
262
+ )
263
+
264
+ # method name
265
+ string =~ /\A[a-zA-Z_]\w*[!?]?\z/ ||
266
+ # instance / class variable
267
+ string =~ /\A\@\@?[a-zA-Z_]\w*\z/ ||
268
+ # global variable
269
+ string =~ /\A\$[1-9]\d*\z/ ||
270
+ string =~ /\A\$[a-zA-Z_]\w*\z/ ||
271
+ special_gvars.include?(string) ||
272
+ redefinable_operators.include?(string)
273
+ end
274
+
275
+ def interpret_string_escapes(string)
276
+ StringInterpreter.interpret(string)
277
+ end
278
+
279
+ def same_line?(n1, n2)
280
+ n1.respond_to?(:loc) &&
281
+ n2.respond_to?(:loc) &&
282
+ n1.loc.line == n2.loc.line
283
+ end
284
+
285
+ def line_distance(n1, n2)
286
+ n2.loc.line - n1.loc.line
287
+ end
288
+
289
+ def preceed?(n1, n2)
290
+ line_distance(n1, n2) == 1
291
+ end
292
+
293
+ def stripped_source_upto(line)
294
+ processed_source[0..line].map(&:strip)
295
+ end
296
+
297
+ def compatible_external_encoding_for?(src)
298
+ src = src.dup if RUBY_VERSION < '2.3'
299
+ src.force_encoding(Encoding.default_external).valid_encoding?
300
+ end
301
+
302
+ def to_supported_styles(enforced_style)
303
+ enforced_style
304
+ .sub(/^Enforced/, 'Supported')
305
+ .sub('Style', 'Styles')
306
+ end
307
+ end
308
+ end
309
+ end