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,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubbyCop
4
+ # This class parses the special `rubbycop:disable` comments in a source
5
+ # and provides a way to check if each cop is enabled at arbitrary line.
6
+ class CommentConfig
7
+ UNNEEDED_DISABLE = 'Lint/UnneededDisable'.freeze
8
+
9
+ COP_NAME_PATTERN = '([A-Z]\w+/)?(?:[A-Z]\w+)'.freeze
10
+ COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}".freeze
11
+ COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})".freeze
12
+
13
+ COMMENT_DIRECTIVE_REGEXP = Regexp.new(
14
+ ('# rubbycop : ((?:dis|en)able)\b ' + COPS_PATTERN).gsub(' ', '\s*')
15
+ )
16
+
17
+ CopAnalysis = Struct.new(:line_ranges, :start_line_number)
18
+
19
+ attr_reader :processed_source
20
+
21
+ def initialize(processed_source)
22
+ @processed_source = processed_source
23
+ end
24
+
25
+ def cop_enabled_at_line?(cop, line_number)
26
+ cop = cop.cop_name if cop.respond_to?(:cop_name)
27
+ disabled_line_ranges = cop_disabled_line_ranges[cop]
28
+ return true unless disabled_line_ranges
29
+
30
+ disabled_line_ranges.none? { |range| range.include?(line_number) }
31
+ end
32
+
33
+ def cop_disabled_line_ranges
34
+ @cop_disabled_line_ranges ||= analyze
35
+ end
36
+
37
+ private
38
+
39
+ def analyze
40
+ analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
41
+
42
+ each_mentioned_cop do |cop_name, disabled, line, single_line|
43
+ analyses[cop_name] =
44
+ analyze_cop(analyses[cop_name], disabled, line, single_line)
45
+ end
46
+
47
+ analyses.each_with_object({}) do |element, hash|
48
+ cop_name, analysis = *element
49
+ hash[cop_name] = cop_line_ranges(analysis)
50
+ end
51
+ end
52
+
53
+ def analyze_cop(analysis, disabled, line, single_line)
54
+ if single_line
55
+ analyze_single_line(analysis, line, disabled)
56
+ elsif disabled
57
+ analyze_disabled(analysis, line)
58
+ else
59
+ analyze_rest(analysis, line)
60
+ end
61
+ end
62
+
63
+ def analyze_single_line(analysis, line, disabled)
64
+ return analysis unless disabled
65
+
66
+ CopAnalysis.new(analysis.line_ranges + [(line..line)],
67
+ analysis.start_line_number)
68
+ end
69
+
70
+ def analyze_disabled(analysis, line)
71
+ if (start_line = analysis.start_line_number)
72
+ # Cop already disabled on this line, so we end the current disabled
73
+ # range before we start a new range.
74
+ return CopAnalysis.new(analysis.line_ranges + [start_line..line], line)
75
+ end
76
+
77
+ CopAnalysis.new(analysis.line_ranges, line)
78
+ end
79
+
80
+ def analyze_rest(analysis, line)
81
+ if (start_line = analysis.start_line_number)
82
+ return CopAnalysis.new(analysis.line_ranges + [start_line..line], nil)
83
+ end
84
+
85
+ CopAnalysis.new(analysis.line_ranges, nil)
86
+ end
87
+
88
+ def cop_line_ranges(analysis)
89
+ return analysis.line_ranges unless analysis.start_line_number
90
+
91
+ analysis.line_ranges + [(analysis.start_line_number..Float::INFINITY)]
92
+ end
93
+
94
+ def each_mentioned_cop
95
+ each_directive do |comment, cop_names, disabled|
96
+ comment_line_number = comment.loc.expression.line
97
+ single_line = !comment_only_line?(comment_line_number)
98
+
99
+ cop_names.each do |cop_name|
100
+ yield qualified_cop_name(cop_name), disabled, comment_line_number,
101
+ single_line
102
+ end
103
+ end
104
+ end
105
+
106
+ def each_directive
107
+ return if processed_source.comments.nil?
108
+
109
+ processed_source.comments.each do |comment|
110
+ directive = directive_parts(comment)
111
+ next unless directive
112
+
113
+ yield comment, *directive
114
+ end
115
+ end
116
+
117
+ def directive_parts(comment)
118
+ match = comment.text.match(COMMENT_DIRECTIVE_REGEXP)
119
+ return unless match
120
+
121
+ switch, cops_string = match.captures
122
+
123
+ cop_names =
124
+ cops_string == 'all' ? all_cop_names : cops_string.split(/,\s*/)
125
+
126
+ disabled = (switch == 'disable')
127
+
128
+ [cop_names, disabled]
129
+ end
130
+
131
+ def qualified_cop_name(cop_name)
132
+ Cop::Cop.qualified_cop_name(cop_name.strip, processed_source.buffer.name)
133
+ end
134
+
135
+ def all_cop_names
136
+ @all_cop_names ||= Cop::Cop.registry.names - [UNNEEDED_DISABLE]
137
+ end
138
+
139
+ def comment_only_line?(line_number)
140
+ non_comment_token_line_numbers.none? do |non_comment_line_number|
141
+ non_comment_line_number == line_number
142
+ end
143
+ end
144
+
145
+ def non_comment_token_line_numbers
146
+ @non_comment_token_line_numbers ||= begin
147
+ non_comment_tokens = processed_source.tokens.reject do |token|
148
+ token.type == :tCOMMENT
149
+ end
150
+
151
+ non_comment_tokens.map { |token| token.pos.line }.uniq
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,444 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ # rubbycop:disable Metrics/ClassLength
6
+
7
+ module RubbyCop
8
+ # This class represents the configuration of the RubbyCop application
9
+ # and all its cops. A Config is associated with a YAML configuration
10
+ # file from which it was read. Several different Configs can be used
11
+ # during a run of the rubbycop program, if files in several
12
+ # directories are inspected.
13
+ class Config
14
+ include PathUtil
15
+
16
+ COMMON_PARAMS = %w[Exclude Include Severity
17
+ AutoCorrect StyleGuide Details].freeze
18
+ # 2.1 is the oldest officially supported Ruby version.
19
+ DEFAULT_RUBY_VERSION = 2.1
20
+ KNOWN_RUBIES = [1.9, 2.0, 2.1, 2.2, 2.3, 2.4].freeze
21
+ DEFAULT_RAILS_VERSION = 5.0
22
+ OBSOLETE_COPS = {
23
+ 'Style/TrailingComma' =>
24
+ 'The `Style/TrailingComma` cop no longer exists. Please use ' \
25
+ '`Style/TrailingCommaInLiteral` and/or ' \
26
+ '`Style/TrailingCommaInArguments` instead.',
27
+ 'Rails/DefaultScope' =>
28
+ 'The `Rails/DefaultScope` cop no longer exists.',
29
+ 'Style/SingleSpaceBeforeFirstArg' =>
30
+ 'The `Style/SingleSpaceBeforeFirstArg` cop has been renamed to ' \
31
+ '`Layout/SpaceBeforeFirstArg`.',
32
+ 'Lint/SpaceBeforeFirstArg' =>
33
+ 'The `Lint/SpaceBeforeFirstArg` cop has been removed, since it was a ' \
34
+ 'duplicate of `Layout/SpaceBeforeFirstArg`. Please use ' \
35
+ '`Layout/SpaceBeforeFirstArg` instead.',
36
+ 'Layout/SpaceAfterControlKeyword' =>
37
+ 'The `Layout/SpaceAfterControlKeyword` cop has been removed. Please ' \
38
+ 'use `Layout/SpaceAroundKeyword` instead.',
39
+ 'Layout/SpaceBeforeModifierKeyword' =>
40
+ 'The `Layout/SpaceBeforeModifierKeyword` cop has been removed. ' \
41
+ 'Please use `Layout/SpaceAroundKeyword` instead.',
42
+ 'Style/SpaceAfterControlKeyword' =>
43
+ 'The `Style/SpaceAfterControlKeyword` cop has been removed. Please ' \
44
+ 'use `Layout/SpaceAroundKeyword` instead.',
45
+ 'Style/SpaceBeforeModifierKeyword' =>
46
+ 'The `Style/SpaceBeforeModifierKeyword` cop has been removed. Please ' \
47
+ 'use `Layout/SpaceAroundKeyword` instead.',
48
+ 'Style/MethodCallParentheses' =>
49
+ 'The `Style/MethodCallParentheses` cop has been renamed to ' \
50
+ '`Style/MethodCallWithoutArgsParentheses`.',
51
+ 'Lint/Eval' =>
52
+ 'The `Lint/Eval` cop has been renamed to `Security/Eval`.',
53
+ 'Style/DeprecatedHashMethods' =>
54
+ 'The `Style/DeprecatedHashMethods` cop has been renamed to ' \
55
+ '`Style/PreferredHashMethods`.'
56
+ }.freeze
57
+
58
+ OBSOLETE_PARAMETERS = [
59
+ {
60
+ cop: 'Layout/SpaceAroundOperators',
61
+ parameter: 'MultiSpaceAllowedForOperators',
62
+ alternative: 'If your intention was to allow extra spaces ' \
63
+ 'for alignment, please use AllowForAlignment: ' \
64
+ 'true instead.'
65
+ },
66
+ {
67
+ cop: 'Style/SpaceAroundOperators',
68
+ parameter: 'MultiSpaceAllowedForOperators',
69
+ alternative: 'If your intention was to allow extra spaces ' \
70
+ 'for alignment, please use AllowForAlignment: ' \
71
+ 'true instead.'
72
+ },
73
+ {
74
+ cop: 'AllCops',
75
+ parameter: 'RunRailsCops',
76
+ alternative: "Use the following configuration instead:\n" \
77
+ "Rails:\n Enabled: true"
78
+ },
79
+ {
80
+ cop: 'Layout/CaseIndentation',
81
+ parameter: 'IndentWhenRelativeTo',
82
+ alternative: '`IndentWhenRelativeTo` has been renamed to ' \
83
+ '`EnforcedStyle`'
84
+ },
85
+ {
86
+ cop: 'Lint/BlockAlignment',
87
+ parameter: 'AlignWith',
88
+ alternative: '`AlignWith` has been renamed to ' \
89
+ '`EnforcedStyleAlignWith`'
90
+ },
91
+ {
92
+ cop: 'Lint/EndAlignment',
93
+ parameter: 'AlignWith',
94
+ alternative: '`AlignWith` has been renamed to ' \
95
+ '`EnforcedStyleAlignWith`'
96
+ },
97
+ {
98
+ cop: 'Lint/DefEndAlignment',
99
+ parameter: 'AlignWith',
100
+ alternative: '`AlignWith` has been renamed to ' \
101
+ '`EnforcedStyleAlignWith`'
102
+ },
103
+ {
104
+ cop: 'Rails/UniqBeforePluck',
105
+ parameter: 'EnforcedMode',
106
+ alternative: '`EnforcedMode` has been renamed to ' \
107
+ '`EnforcedStyle`'
108
+ }
109
+ ].freeze
110
+
111
+ attr_reader :loaded_path
112
+
113
+ def initialize(hash = {}, loaded_path = nil)
114
+ @loaded_path = loaded_path
115
+ @for_cop = Hash.new do |h, cop|
116
+ qualified_cop_name = Cop::Cop.qualified_cop_name(cop, loaded_path)
117
+ cop_options = self[qualified_cop_name] || {}
118
+ cop_options['Enabled'] = enable_cop?(qualified_cop_name, cop_options)
119
+ h[cop] = cop_options
120
+ end
121
+ @hash = hash
122
+ end
123
+
124
+ def [](key)
125
+ @hash[key]
126
+ end
127
+
128
+ def []=(key, value)
129
+ @hash[key] = value
130
+ end
131
+
132
+ def delete(key)
133
+ @hash.delete(key)
134
+ end
135
+
136
+ def each(&block)
137
+ @hash.each(&block)
138
+ end
139
+
140
+ def key?(key)
141
+ @hash.key?(key)
142
+ end
143
+
144
+ def keys
145
+ @hash.keys
146
+ end
147
+
148
+ def map(&block)
149
+ @hash.map(&block)
150
+ end
151
+
152
+ def merge(other_hash)
153
+ @hash.merge(other_hash)
154
+ end
155
+
156
+ def to_h
157
+ @hash
158
+ end
159
+
160
+ def to_hash
161
+ @hash
162
+ end
163
+
164
+ def to_s
165
+ @to_s ||= @hash.to_s
166
+ end
167
+
168
+ def make_excludes_absolute
169
+ each do |key, _|
170
+ validate_section_presence(key)
171
+ next unless self[key]['Exclude']
172
+
173
+ self[key]['Exclude'].map! do |exclude_elem|
174
+ if exclude_elem.is_a?(String) && !absolute?(exclude_elem)
175
+ File.expand_path(File.join(base_dir_for_path_parameters,
176
+ exclude_elem))
177
+ else
178
+ exclude_elem
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ def add_excludes_from_higher_level(highest_config)
185
+ return unless highest_config.for_all_cops['Exclude']
186
+
187
+ excludes = for_all_cops['Exclude'] ||= []
188
+ highest_config.for_all_cops['Exclude'].each do |path|
189
+ unless path.is_a?(Regexp) || absolute?(path)
190
+ path = File.join(File.dirname(highest_config.loaded_path), path)
191
+ end
192
+ excludes << path unless excludes.include?(path)
193
+ end
194
+ end
195
+
196
+ def deprecation_check
197
+ %w[Exclude Include].each do |key|
198
+ plural = "#{key}s"
199
+ next unless for_all_cops[plural]
200
+
201
+ for_all_cops[key] = for_all_cops[plural] # Stay backwards compatible.
202
+ for_all_cops.delete(plural)
203
+ yield "AllCops/#{plural} was renamed to AllCops/#{key}"
204
+ end
205
+ end
206
+
207
+ def for_cop(cop)
208
+ @for_cop[cop.respond_to?(:cop_name) ? cop.cop_name : cop]
209
+ end
210
+
211
+ def for_all_cops
212
+ @for_all_cops ||= self['AllCops'] || {}
213
+ end
214
+
215
+ def validate
216
+ # Don't validate RubbyCop's own files. Avoids infinite recursion.
217
+ base_config_path = File.expand_path(File.join(ConfigLoader::RUBOCOP_HOME,
218
+ 'config'))
219
+ return if File.expand_path(loaded_path).start_with?(base_config_path)
220
+
221
+ valid_cop_names, invalid_cop_names = keys.partition do |key|
222
+ ConfigLoader.default_configuration.key?(key)
223
+ end
224
+
225
+ reject_obsolete_cops_and_parameters
226
+ warn_about_unrecognized_cops(invalid_cop_names)
227
+ check_target_ruby
228
+ validate_parameter_names(valid_cop_names)
229
+ validate_enforced_styles(valid_cop_names)
230
+ reject_mutually_exclusive_defaults
231
+ end
232
+
233
+ def file_to_include?(file)
234
+ relative_file_path = path_relative_to_config(file)
235
+
236
+ # Optimization to quickly decide if the given file is hidden (on the top
237
+ # level) and can not be matched by any pattern.
238
+ is_hidden = relative_file_path.start_with?('.') &&
239
+ !relative_file_path.start_with?('..')
240
+ return false if is_hidden && !possibly_include_hidden?
241
+
242
+ absolute_file_path = File.expand_path(file)
243
+
244
+ patterns_to_include.any? do |pattern|
245
+ match_path?(pattern, relative_file_path) ||
246
+ match_path?(pattern, absolute_file_path)
247
+ end
248
+ end
249
+
250
+ # Returns true if there's a chance that an Include pattern matches hidden
251
+ # files, false if that's definitely not possible.
252
+ def possibly_include_hidden?
253
+ return @possibly_include_hidden if defined?(@possibly_include_hidden)
254
+
255
+ @possibly_include_hidden = patterns_to_include.any? do |s|
256
+ s.is_a?(Regexp) || s.start_with?('.') || s.include?('/.')
257
+ end
258
+ end
259
+
260
+ def file_to_exclude?(file)
261
+ file = File.expand_path(file)
262
+ patterns_to_exclude.any? do |pattern|
263
+ match_path?(pattern, file)
264
+ end
265
+ end
266
+
267
+ def patterns_to_include
268
+ for_all_cops['Include']
269
+ end
270
+
271
+ def patterns_to_exclude
272
+ for_all_cops['Exclude']
273
+ end
274
+
275
+ def path_relative_to_config(path)
276
+ relative_path(path, base_dir_for_path_parameters)
277
+ end
278
+
279
+ # Paths specified in configuration files starting with .rubbycop are
280
+ # relative to the directory where that file is. Paths in other config files
281
+ # are relative to the current directory. This is so that paths in
282
+ # config/default.yml, for example, are not relative to RubbyCop's config
283
+ # directory since that wouldn't work.
284
+ def base_dir_for_path_parameters
285
+ @base_dir_for_path_parameters ||=
286
+ if File.basename(loaded_path).start_with?('.rubbycop') &&
287
+ loaded_path != File.join(Dir.home, ConfigLoader::DOTFILE)
288
+ File.expand_path(File.dirname(loaded_path))
289
+ else
290
+ Dir.pwd
291
+ end
292
+ end
293
+
294
+ def target_ruby_version
295
+ @target_ruby_version ||=
296
+ if for_all_cops['TargetRubyVersion']
297
+ @target_ruby_version_source = :rubbycop_yml
298
+
299
+ for_all_cops['TargetRubyVersion']
300
+ elsif File.file?('.ruby-version') &&
301
+ /\A(ruby-)?(?<version>\d+\.\d+)/ =~ File.read('.ruby-version')
302
+
303
+ @target_ruby_version_source = :dot_ruby_version
304
+
305
+ version.to_f
306
+ else
307
+ DEFAULT_RUBY_VERSION
308
+ end
309
+ end
310
+
311
+ def target_rails_version
312
+ @target_rails_version ||=
313
+ for_all_cops.fetch('TargetRailsVersion', DEFAULT_RAILS_VERSION)
314
+ end
315
+
316
+ private
317
+
318
+ def warn_about_unrecognized_cops(invalid_cop_names)
319
+ invalid_cop_names.each do |name|
320
+ if name == 'Syntax'
321
+ raise ValidationError,
322
+ "configuration for Syntax cop found in #{loaded_path}\n" \
323
+ 'This cop cannot be configured.'
324
+ end
325
+
326
+ # There could be a custom cop with this name. If so, don't warn
327
+ next if Cop::Cop.registry.contains_cop_matching?([name])
328
+
329
+ warn Rainbow("Warning: unrecognized cop #{name} found in " \
330
+ "#{loaded_path}").yellow
331
+ end
332
+ end
333
+
334
+ def validate_section_presence(name)
335
+ return unless key?(name) && self[name].nil?
336
+ raise ValidationError, "empty section #{name} found in #{loaded_path}"
337
+ end
338
+
339
+ def validate_parameter_names(valid_cop_names)
340
+ valid_cop_names.each do |name|
341
+ validate_section_presence(name)
342
+ self[name].each_key do |param|
343
+ next if COMMON_PARAMS.include?(param) ||
344
+ ConfigLoader.default_configuration[name].key?(param)
345
+
346
+ warn Rainbow("Warning: unrecognized parameter #{name}:#{param} " \
347
+ "found in #{loaded_path}").yellow
348
+ end
349
+ end
350
+ end
351
+
352
+ def validate_enforced_styles(valid_cop_names)
353
+ valid_cop_names.each do |name|
354
+ styles = self[name].select { |key, _| key.start_with?('Enforced') }
355
+
356
+ styles.each do |style_name, style|
357
+ supported_key = RubbyCop::Cop::Util.to_supported_styles(style_name)
358
+ valid = ConfigLoader.default_configuration[name][supported_key]
359
+ next unless valid
360
+ next if valid.include?(style)
361
+
362
+ msg = "invalid #{style_name} '#{style}' for #{name} found in " \
363
+ "#{loaded_path}\n" \
364
+ "Valid choices are: #{valid.join(', ')}"
365
+ raise ValidationError, msg
366
+ end
367
+ end
368
+ end
369
+
370
+ def reject_obsolete_cops_and_parameters
371
+ messages = [
372
+ obsolete_cops,
373
+ obsolete_parameters
374
+ ].flatten.compact
375
+ return if messages.empty?
376
+
377
+ raise ValidationError, messages.join("\n")
378
+ end
379
+
380
+ def obsolete_parameters
381
+ OBSOLETE_PARAMETERS.map do |params|
382
+ obsolete_parameter_message(params[:cop], params[:parameter],
383
+ params[:alternative])
384
+ end
385
+ end
386
+
387
+ def obsolete_parameter_message(cop, parameter, alternative)
388
+ return unless self[cop] && self[cop].key?(parameter)
389
+
390
+ "obsolete parameter #{parameter} (for #{cop}) " \
391
+ "found in #{loaded_path}" \
392
+ "\n#{alternative}"
393
+ end
394
+
395
+ def obsolete_cops
396
+ OBSOLETE_COPS.map do |cop_name, message|
397
+ next unless key?(cop_name) || key?(Cop::Badge.parse(cop_name).cop_name)
398
+ message + "\n(obsolete configuration found in #{loaded_path}, please" \
399
+ ' update it)'
400
+ end
401
+ end
402
+
403
+ def check_target_ruby
404
+ return if KNOWN_RUBIES.include?(target_ruby_version)
405
+
406
+ msg = "Unknown Ruby version #{target_ruby_version.inspect} found "
407
+
408
+ msg +=
409
+ case @target_ruby_version_source
410
+ when :dot_ruby_version
411
+ 'in `.ruby-version`.'
412
+ when :rubbycop_yml
413
+ "in `TargetRubyVersion` parameter (in #{loaded_path})." \
414
+ end
415
+
416
+ msg += "\nKnown versions: #{KNOWN_RUBIES.join(', ')}"
417
+
418
+ raise ValidationError, msg
419
+ end
420
+
421
+ def reject_mutually_exclusive_defaults
422
+ disabled_by_default = for_all_cops['DisabledByDefault']
423
+ enabled_by_default = for_all_cops['EnabledByDefault']
424
+ return unless disabled_by_default && enabled_by_default
425
+
426
+ msg = 'Cops cannot be both enabled by default and disabled by default'
427
+ raise ValidationError, msg
428
+ end
429
+
430
+ def enable_cop?(qualified_cop_name, cop_options)
431
+ cop_department, cop_name = qualified_cop_name.split('/')
432
+ department = cop_name.nil?
433
+
434
+ unless department
435
+ department_options = self[cop_department]
436
+ if department_options && department_options.fetch('Enabled') == false
437
+ return false
438
+ end
439
+ end
440
+
441
+ cop_options.fetch('Enabled', true)
442
+ end
443
+ end
444
+ end