rubocop 0.46.0 → 0.47.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubocop might be problematic. Click here for more details.

Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +77 -2
  4. data/config/default.yml +151 -74
  5. data/config/disabled.yml +9 -0
  6. data/config/enabled.yml +49 -9
  7. data/lib/rubocop.rb +36 -8
  8. data/lib/rubocop/ast/builder.rb +59 -0
  9. data/lib/rubocop/ast/node.rb +607 -0
  10. data/lib/rubocop/ast/node/array_node.rb +45 -0
  11. data/lib/rubocop/ast/node/case_node.rb +63 -0
  12. data/lib/rubocop/ast/node/for_node.rb +53 -0
  13. data/lib/rubocop/ast/node/hash_node.rb +102 -0
  14. data/lib/rubocop/ast/node/if_node.rb +136 -0
  15. data/lib/rubocop/ast/node/keyword_splat_node.rb +45 -0
  16. data/lib/rubocop/ast/node/mixin/conditional_node.rb +45 -0
  17. data/lib/rubocop/ast/node/mixin/hash_element_node.rb +125 -0
  18. data/lib/rubocop/ast/node/mixin/modifier_node.rb +17 -0
  19. data/lib/rubocop/ast/node/pair_node.rb +64 -0
  20. data/lib/rubocop/ast/node/until_node.rb +43 -0
  21. data/lib/rubocop/ast/node/when_node.rb +61 -0
  22. data/lib/rubocop/ast/node/while_node.rb +43 -0
  23. data/lib/rubocop/ast/sexp.rb +16 -0
  24. data/lib/rubocop/{ast_node → ast}/traversal.rb +1 -1
  25. data/lib/rubocop/cli.rb +18 -14
  26. data/lib/rubocop/comment_config.rb +1 -3
  27. data/lib/rubocop/config.rb +93 -35
  28. data/lib/rubocop/config_loader.rb +1 -1
  29. data/lib/rubocop/cop/badge.rb +73 -0
  30. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  31. data/lib/rubocop/cop/bundler/ordered_gems.rb +43 -3
  32. data/lib/rubocop/cop/commissioner.rb +17 -6
  33. data/lib/rubocop/cop/cop.rb +25 -112
  34. data/lib/rubocop/cop/lint/ambiguous_operator.rb +9 -4
  35. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +7 -0
  36. data/lib/rubocop/cop/lint/assignment_in_condition.rb +18 -4
  37. data/lib/rubocop/cop/lint/block_alignment.rb +40 -9
  38. data/lib/rubocop/cop/lint/circular_argument_reference.rb +14 -0
  39. data/lib/rubocop/cop/lint/condition_position.rb +14 -16
  40. data/lib/rubocop/cop/lint/debugger.rb +28 -0
  41. data/lib/rubocop/cop/lint/def_end_alignment.rb +21 -1
  42. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +13 -1
  43. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +26 -22
  44. data/lib/rubocop/cop/lint/duplicate_methods.rb +15 -1
  45. data/lib/rubocop/cop/lint/duplicated_key.rb +16 -8
  46. data/lib/rubocop/cop/lint/each_with_object_argument.rb +9 -0
  47. data/lib/rubocop/cop/lint/else_layout.rb +26 -29
  48. data/lib/rubocop/cop/lint/empty_ensure.rb +38 -0
  49. data/lib/rubocop/cop/lint/empty_expression.rb +11 -1
  50. data/lib/rubocop/cop/lint/empty_interpolation.rb +8 -0
  51. data/lib/rubocop/cop/lint/empty_when.rb +14 -16
  52. data/lib/rubocop/cop/lint/end_alignment.rb +48 -28
  53. data/lib/rubocop/cop/lint/end_in_method.rb +23 -0
  54. data/lib/rubocop/cop/lint/ensure_return.rb +21 -0
  55. data/lib/rubocop/cop/lint/float_out_of_range.rb +5 -0
  56. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +29 -4
  57. data/lib/rubocop/cop/lint/handle_exceptions.rb +40 -0
  58. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +7 -2
  59. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +11 -2
  60. data/lib/rubocop/cop/lint/invalid_character_literal.rb +3 -0
  61. data/lib/rubocop/cop/lint/literal_in_condition.rb +34 -36
  62. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -0
  63. data/lib/rubocop/cop/lint/loop.rb +36 -0
  64. data/lib/rubocop/cop/lint/multiple_compare.rb +46 -0
  65. data/lib/rubocop/cop/lint/nested_method_definition.rb +22 -0
  66. data/lib/rubocop/cop/lint/next_without_accumulator.rb +5 -0
  67. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -0
  68. data/lib/rubocop/cop/lint/percent_string_array.rb +27 -13
  69. data/lib/rubocop/cop/lint/percent_symbol_array.rb +14 -4
  70. data/lib/rubocop/cop/lint/rand_one.rb +7 -3
  71. data/lib/rubocop/cop/lint/require_parentheses.rb +20 -19
  72. data/lib/rubocop/cop/lint/rescue_exception.rb +20 -0
  73. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +66 -0
  74. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -1
  75. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +24 -0
  76. data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +8 -0
  77. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +24 -0
  78. data/lib/rubocop/cop/lint/unified_integer.rb +5 -0
  79. data/lib/rubocop/cop/lint/unneeded_disable.rb +2 -2
  80. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +5 -0
  81. data/lib/rubocop/cop/lint/unreachable_code.rb +17 -0
  82. data/lib/rubocop/cop/lint/unused_block_argument.rb +2 -0
  83. data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
  84. data/lib/rubocop/cop/lint/useless_access_modifier.rb +28 -1
  85. data/lib/rubocop/cop/lint/useless_assignment.rb +18 -0
  86. data/lib/rubocop/cop/lint/useless_comparison.rb +3 -1
  87. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +16 -1
  88. data/lib/rubocop/cop/lint/useless_setter_call.rb +16 -4
  89. data/lib/rubocop/cop/lint/void.rb +52 -0
  90. data/lib/rubocop/cop/message_annotator.rb +102 -0
  91. data/lib/rubocop/cop/metrics/block_length.rb +6 -0
  92. data/lib/rubocop/cop/metrics/block_nesting.rb +17 -5
  93. data/lib/rubocop/cop/metrics/line_length.rb +11 -4
  94. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
  95. data/lib/rubocop/cop/mixin/array_syntax.rb +2 -11
  96. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +12 -5
  97. data/lib/rubocop/cop/mixin/configurable_formatting.rb +48 -0
  98. data/lib/rubocop/cop/mixin/configurable_max.rb +3 -3
  99. data/lib/rubocop/cop/mixin/configurable_naming.rb +5 -33
  100. data/lib/rubocop/cop/mixin/configurable_numbering.rb +6 -47
  101. data/lib/rubocop/cop/mixin/documentation_comment.rb +7 -1
  102. data/lib/rubocop/cop/mixin/duplication.rb +46 -0
  103. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +2 -2
  104. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +14 -11
  105. data/lib/rubocop/cop/mixin/hash_alignment.rb +114 -0
  106. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -3
  107. data/lib/rubocop/cop/mixin/negative_conditional.rb +21 -7
  108. data/lib/rubocop/cop/mixin/on_method_def.rb +14 -0
  109. data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -24
  110. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -13
  111. data/lib/rubocop/cop/mixin/target_ruby_version.rb +16 -0
  112. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -3
  113. data/lib/rubocop/cop/offense.rb +1 -1
  114. data/lib/rubocop/cop/performance/case_when_splat.rb +56 -59
  115. data/lib/rubocop/cop/performance/detect.rb +2 -2
  116. data/lib/rubocop/cop/performance/flat_map.rb +3 -3
  117. data/lib/rubocop/cop/performance/redundant_merge.rb +3 -6
  118. data/lib/rubocop/cop/performance/regexp_match.rb +201 -0
  119. data/lib/rubocop/cop/rails/delegate.rb +2 -2
  120. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +10 -19
  121. data/lib/rubocop/cop/rails/enum_uniqueness.rb +12 -40
  122. data/lib/rubocop/cop/rails/file_path.rb +80 -0
  123. data/lib/rubocop/cop/rails/find_each.rb +5 -14
  124. data/lib/rubocop/cop/rails/http_positional_arguments.rb +30 -24
  125. data/lib/rubocop/cop/rails/not_null_column.rb +23 -0
  126. data/lib/rubocop/cop/rails/reversible_migration.rb +217 -0
  127. data/lib/rubocop/cop/rails/safe_navigation.rb +4 -2
  128. data/lib/rubocop/cop/rails/skips_model_validations.rb +46 -0
  129. data/lib/rubocop/cop/rails/time_zone.rb +1 -1
  130. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +7 -5
  131. data/lib/rubocop/cop/registry.rb +170 -0
  132. data/lib/rubocop/cop/{lint → security}/eval.rb +7 -1
  133. data/lib/rubocop/cop/security/marshal_load.rb +33 -0
  134. data/lib/rubocop/cop/security/yaml_load.rb +37 -0
  135. data/lib/rubocop/cop/style/align_hash.rb +138 -169
  136. data/lib/rubocop/cop/style/and_or.rb +1 -1
  137. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +10 -15
  138. data/lib/rubocop/cop/style/case_indentation.rb +36 -27
  139. data/lib/rubocop/cop/style/conditional_assignment.rb +64 -47
  140. data/lib/rubocop/cop/style/each_with_object.rb +4 -1
  141. data/lib/rubocop/cop/style/else_alignment.rb +14 -20
  142. data/lib/rubocop/cop/style/empty_case_condition.rb +16 -25
  143. data/lib/rubocop/cop/style/empty_else.rb +20 -22
  144. data/lib/rubocop/cop/style/empty_literal.rb +4 -4
  145. data/lib/rubocop/cop/style/empty_method.rb +12 -6
  146. data/lib/rubocop/cop/style/encoding.rb +1 -1
  147. data/lib/rubocop/cop/style/file_name.rb +24 -4
  148. data/lib/rubocop/cop/style/first_method_argument_line_break.rb +1 -1
  149. data/lib/rubocop/cop/style/format_string.rb +17 -48
  150. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +40 -11
  151. data/lib/rubocop/cop/style/guard_clause.rb +11 -17
  152. data/lib/rubocop/cop/style/hash_syntax.rb +24 -42
  153. data/lib/rubocop/cop/style/identical_conditional_branches.rb +40 -28
  154. data/lib/rubocop/cop/style/if_inside_else.rb +6 -9
  155. data/lib/rubocop/cop/style/if_unless_modifier.rb +16 -25
  156. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -9
  157. data/lib/rubocop/cop/style/indent_array.rb +1 -1
  158. data/lib/rubocop/cop/style/indentation_width.rb +29 -60
  159. data/lib/rubocop/cop/style/infinite_loop.rb +21 -22
  160. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +86 -0
  161. data/lib/rubocop/cop/style/{method_call_parentheses.rb → method_call_without_args_parentheses.rb} +8 -1
  162. data/lib/rubocop/cop/style/missing_else.rb +40 -14
  163. data/lib/rubocop/cop/style/multiline_if_modifier.rb +5 -15
  164. data/lib/rubocop/cop/style/multiline_if_then.rb +14 -8
  165. data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +3 -3
  166. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -5
  167. data/lib/rubocop/cop/style/mutable_constant.rb +3 -2
  168. data/lib/rubocop/cop/style/negated_if.rb +3 -19
  169. data/lib/rubocop/cop/style/negated_while.rb +2 -17
  170. data/lib/rubocop/cop/style/nested_modifier.rb +16 -43
  171. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -5
  172. data/lib/rubocop/cop/style/next.rb +23 -21
  173. data/lib/rubocop/cop/style/non_nil_check.rb +2 -3
  174. data/lib/rubocop/cop/style/not.rb +1 -3
  175. data/lib/rubocop/cop/style/numeric_literals.rb +2 -2
  176. data/lib/rubocop/cop/style/one_line_conditional.rb +12 -22
  177. data/lib/rubocop/cop/style/option_hash.rb +4 -15
  178. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
  179. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -12
  180. data/lib/rubocop/cop/style/percent_q_literals.rb +15 -12
  181. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -2
  182. data/lib/rubocop/cop/style/redundant_parentheses.rb +27 -4
  183. data/lib/rubocop/cop/style/redundant_return.rb +4 -8
  184. data/lib/rubocop/cop/style/safe_navigation.rb +13 -6
  185. data/lib/rubocop/cop/style/space_after_colon.rb +2 -4
  186. data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -1
  187. data/lib/rubocop/cop/style/space_around_operators.rb +15 -13
  188. data/lib/rubocop/cop/style/string_methods.rb +1 -3
  189. data/lib/rubocop/cop/style/symbol_array.rb +1 -5
  190. data/lib/rubocop/cop/style/ternary_parentheses.rb +5 -6
  191. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +2 -5
  192. data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +1 -1
  193. data/lib/rubocop/cop/style/unless_else.rb +1 -5
  194. data/lib/rubocop/cop/style/when_then.rb +4 -2
  195. data/lib/rubocop/cop/style/while_until_do.rb +9 -13
  196. data/lib/rubocop/cop/style/while_until_modifier.rb +12 -11
  197. data/lib/rubocop/cop/style/word_array.rb +5 -9
  198. data/lib/rubocop/cop/team.rb +16 -15
  199. data/lib/rubocop/cop/util.rb +13 -3
  200. data/lib/rubocop/formatter/clang_style_formatter.rb +2 -2
  201. data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
  202. data/lib/rubocop/magic_comment.rb +196 -0
  203. data/lib/rubocop/options.rb +5 -4
  204. data/lib/rubocop/processed_source.rb +1 -1
  205. data/lib/rubocop/rspec/cop_helper.rb +9 -0
  206. data/lib/rubocop/rspec/shared_examples.rb +1 -1
  207. data/lib/rubocop/runner.rb +7 -2
  208. data/lib/rubocop/version.rb +1 -1
  209. metadata +41 -14
  210. data/lib/rubocop/ast_node.rb +0 -624
  211. data/lib/rubocop/ast_node/builder.rb +0 -30
  212. data/lib/rubocop/ast_node/sexp.rb +0 -13
  213. data/lib/rubocop/cop/mixin/hash_node.rb +0 -14
  214. data/lib/rubocop/cop/mixin/if_node.rb +0 -42
@@ -9,6 +9,8 @@ module RuboCop
9
9
  class WhileUntilModifier < Cop
10
10
  include StatementModifier
11
11
 
12
+ MSG = 'Favor modifier `%s` usage when having a single-line body.'.freeze
13
+
12
14
  def on_while(node)
13
15
  check(node)
14
16
  end
@@ -17,22 +19,21 @@ module RuboCop
17
19
  check(node)
18
20
  end
19
21
 
22
+ private
23
+
20
24
  def autocorrect(node)
21
- cond, body = *node
22
- oneline = "#{body.source} #{node.loc.keyword.source} " + cond.source
23
- ->(corrector) { corrector.replace(node.source_range, oneline) }
24
- end
25
+ oneline = "#{node.body.source} #{node.keyword} " \
26
+ "#{node.condition.source}"
25
27
 
26
- private
28
+ lambda do |corrector|
29
+ corrector.replace(node.source_range, oneline)
30
+ end
31
+ end
27
32
 
28
33
  def check(node)
29
- return unless node.loc.end
30
- return unless single_line_as_modifier?(node)
31
- add_offense(node, :keyword, message(node.loc.keyword.source))
32
- end
34
+ return unless node.multiline? && single_line_as_modifier?(node)
33
35
 
34
- def message(keyword)
35
- "Favor modifier `#{keyword}` usage when having a single-line body."
36
+ add_offense(node, :keyword, format(MSG, node.keyword))
36
37
  end
37
38
  end
38
39
  end
@@ -18,7 +18,7 @@ module RuboCop
18
18
  def on_array(node)
19
19
  if bracketed_array_of?(:str, node)
20
20
  check_bracketed(node)
21
- elsif percent_syntax?(node)
21
+ elsif node.percent_literal?(:string)
22
22
  check_percent(node)
23
23
  end
24
24
  end
@@ -34,21 +34,17 @@ module RuboCop
34
34
  private
35
35
 
36
36
  def check_bracketed(node)
37
- array_elems = node.children
38
-
39
- return if complex_content?(array_elems) ||
37
+ return if complex_content?(node.values) ||
40
38
  comments_in_array?(node)
41
- style_detected(:brackets, array_elems.size)
39
+ style_detected(:brackets, node.values.size)
42
40
 
43
- return unless style == :percent && array_elems.size >= min_size
41
+ return unless style == :percent && node.values.size >= min_size
44
42
 
45
43
  add_offense(node, :expression, PERCENT_MSG)
46
44
  end
47
45
 
48
46
  def check_percent(node)
49
- array_elems = node.children
50
-
51
- style_detected(:percent, array_elems.size)
47
+ style_detected(:percent, node.values.size)
52
48
  add_offense(node, :expression, ARRAY_MSG) if style == :brackets
53
49
  end
54
50
 
@@ -52,7 +52,8 @@ module RuboCop
52
52
  end
53
53
 
54
54
  def cops
55
- @cops ||= @cop_classes.select { |c| cop_enabled?(c) }.map do |cop_class|
55
+ only_options = @options.fetch(:only, [])
56
+ @cops ||= @cop_classes.enabled(@config, only_options).map do |cop_class|
56
57
  cop_class.new(@config, @options)
57
58
  end
58
59
  end
@@ -123,11 +124,6 @@ module RuboCop
123
124
  Investigation.new(offenses, commissioner.errors)
124
125
  end
125
126
 
126
- def cop_enabled?(cop_class)
127
- @config.cop_enabled?(cop_class) ||
128
- (@options[:only] || []).include?(cop_class.cop_name)
129
- end
130
-
131
127
  def autocorrect_all_cops(buffer, cops)
132
128
  corrector = Corrector.new(buffer)
133
129
  skip = Set.new
@@ -155,27 +151,32 @@ module RuboCop
155
151
 
156
152
  def process_commissioner_errors(file, file_errors)
157
153
  file_errors.each do |cop, errors|
158
- errors.each do |e|
154
+ errors.each do |cop_error|
155
+ e = cop_error.error
156
+ line = ":#{cop_error.line}" if cop_error.line
157
+ column = ":#{cop_error.column}" if cop_error.column
158
+ location = "#{file}#{line}#{column}"
159
+
159
160
  if e.is_a?(Warning)
160
- handle_warning(e,
161
- Rainbow("#{e.message} (from file: " \
162
- "#{file})").yellow)
161
+ handle_warning(e, location)
163
162
  else
164
- handle_error(e,
165
- Rainbow("An error occurred while #{cop.name}" \
166
- " cop was inspecting #{file}.").red)
163
+ handle_error(e, location, cop)
167
164
  end
168
165
  end
169
166
  end
170
167
  end
171
168
 
172
- def handle_warning(e, message)
169
+ def handle_warning(e, location)
170
+ message = Rainbow("#{e.message} (from file: #{location})").yellow
171
+
173
172
  @warnings << message
174
173
  warn message
175
174
  puts e.backtrace if debug?
176
175
  end
177
176
 
178
- def handle_error(e, message)
177
+ def handle_error(e, location, cop)
178
+ message = Rainbow("An error occurred while #{cop.name}" \
179
+ " cop was inspecting #{location}.").red
179
180
  @errors << message
180
181
  warn message
181
182
  if debug?
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # This module contains a collection of useful utility methods.
7
7
  module Util
8
8
  include PathUtil
9
- extend RuboCop::Sexp
9
+ extend RuboCop::AST::Sexp
10
10
 
11
11
  BYTE_ORDER_MARK = 0xfeff # The Unicode codepoint
12
12
 
@@ -15,6 +15,10 @@ module RuboCop
15
15
  SHORTHAND_ASGN_NODES = [:op_asgn, :or_asgn, :and_asgn].freeze
16
16
  ASGN_NODES = (EQUALS_ASGN_NODES + SHORTHAND_ASGN_NODES).freeze
17
17
 
18
+ MODIFIER_NODES = [:if, :while, :until].freeze
19
+ CONDITIONAL_NODES = (MODIFIER_NODES + [:case]).freeze
20
+ LOGICAL_OPERATOR_NODES = [:and, :or].freeze
21
+
18
22
  # http://phrogz.net/programmingruby/language.html#table_18.4
19
23
  # Backtick is added last just to help editors parse this code.
20
24
  OPERATOR_METHODS = %w(
@@ -172,8 +176,8 @@ module RuboCop
172
176
  end
173
177
 
174
178
  def within_node?(inner, outer)
175
- o = outer.is_a?(Node) ? outer.source_range : outer
176
- i = inner.is_a?(Node) ? inner.source_range : inner
179
+ o = outer.is_a?(AST::Node) ? outer.source_range : outer
180
+ i = inner.is_a?(AST::Node) ? inner.source_range : inner
177
181
  i.begin_pos >= o.begin_pos && i.end_pos <= o.end_pos
178
182
  end
179
183
 
@@ -271,6 +275,12 @@ module RuboCop
271
275
  src = src.dup if RUBY_VERSION < '2.3'
272
276
  src.force_encoding(Encoding.default_external).valid_encoding?
273
277
  end
278
+
279
+ def to_supported_styles(enforced_style)
280
+ enforced_style
281
+ .sub(/^Enforced/, 'Supported')
282
+ .sub('Style', 'Styles')
283
+ end
274
284
  end
275
285
  end
276
286
  end
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # The precise location of the problem is shown together with the
7
7
  # relevant source code.
8
8
  class ClangStyleFormatter < SimpleTextFormatter
9
- ELLIPSES = Rainbow('...').yellow.freeze
9
+ ELLIPSES = '...'.freeze
10
10
 
11
11
  def report_file(file, offenses)
12
12
  offenses.each { |offense| report_offense(file, offense) }
@@ -41,7 +41,7 @@ module RuboCop
41
41
  if location.first_line == location.last_line
42
42
  output.puts(source_line)
43
43
  else
44
- output.puts("#{source_line} #{ELLIPSES}")
44
+ output.puts("#{source_line} #{yellow(ELLIPSES)}")
45
45
  end
46
46
  end
47
47
 
@@ -18,7 +18,7 @@ module RuboCop
18
18
  @config_to_allow_offenses = {}
19
19
  @detected_styles = {}
20
20
 
21
- COPS = Cop::Cop.all.group_by(&:cop_name)
21
+ COPS = Cop::Cop.registry.to_h
22
22
 
23
23
  class << self
24
24
  attr_accessor :config_to_allow_offenses, :detected_styles
@@ -66,6 +66,7 @@ module RuboCop
66
66
  if @exclude_limit_option
67
67
  command += format(' --exclude-limit %d', @exclude_limit_option.to_i)
68
68
  end
69
+ command += ' --no-offense-counts' if @options[:no_offense_counts]
69
70
 
70
71
  command
71
72
  end
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # Parse different formats of magic comments.
5
+ #
6
+ # @abstract parent of three different magic comment handlers
7
+ class MagicComment
8
+ # @see https://git.io/vMC1C IRB's pattern for matching magic comment tokens
9
+ TOKEN = /[[:alnum:]\-_]+/
10
+
11
+ # Detect magic comment format and pass it to the appropriate wrapper.
12
+ #
13
+ # @param comment [String]
14
+ #
15
+ # @return [RuboCop::MagicComment]
16
+ def self.parse(comment)
17
+ case comment
18
+ when EmacsComment::FORMAT then EmacsComment.new(comment)
19
+ when VimComment::FORMAT then VimComment.new(comment)
20
+ else
21
+ SimpleComment.new(comment)
22
+ end
23
+ end
24
+
25
+ def initialize(comment)
26
+ @comment = comment
27
+ end
28
+
29
+ # Does the magic comment enable the frozen string literal feature.
30
+ #
31
+ # Test whether the frozen string literal value is `true`. Cannot
32
+ # just return `frozen_string_literal` since an invalid magic comment
33
+ # like `# frozen_string_literal: yes` is possible and the truthy value
34
+ # `'yes'` does not actually enable the feature
35
+ #
36
+ # @return [Boolean]
37
+ def frozen_string_literal?
38
+ frozen_string_literal == true
39
+ end
40
+
41
+ # Was a magic comment for the frozen string literal found?
42
+ #
43
+ # @return [Boolean]
44
+ def frozen_string_literal_specified?
45
+ !frozen_string_literal.nil?
46
+ end
47
+
48
+ # Expose the `frozen_string_literal` value coerced to a boolean if possible.
49
+ #
50
+ # @return [Boolean] if value is `true` or `false`
51
+ # @return [nil] if frozen_string_literal comment isn't found
52
+ # @return [String] if comment is found but isn't true or false
53
+ def frozen_string_literal
54
+ return unless (setting = extract_frozen_string_literal)
55
+
56
+ case setting
57
+ when 'true' then true
58
+ when 'false' then false
59
+ else
60
+ setting
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ # Match the entire comment string with a pattern and take the first capture.
67
+ #
68
+ # @param pattern [Regexp]
69
+ #
70
+ # @return [String] if pattern matched
71
+ # @return [nil] otherwise
72
+ def extract(pattern)
73
+ @comment[pattern, 1]
74
+ end
75
+
76
+ # Parent to Vim and Emacs magic comment handling.
77
+ #
78
+ # @abstract
79
+ class EditorComment < MagicComment
80
+ private
81
+
82
+ # Find a token starting with the provided keyword and extract its value.
83
+ #
84
+ # @param keyword [String]
85
+ #
86
+ # @return [String] extracted value if it is found
87
+ # @return [nil] otherwise
88
+ def match(keyword)
89
+ pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s*(#{TOKEN})\z/
90
+
91
+ tokens.each do |token|
92
+ next unless (value = token[pattern, 1])
93
+
94
+ return value.downcase
95
+ end
96
+
97
+ nil
98
+ end
99
+
100
+ # Individual tokens composing an editor specific comment string.
101
+ #
102
+ # @return [Array<String>]
103
+ def tokens
104
+ extract(self.class::FORMAT).split(self.class::SEPARATOR).map(&:strip)
105
+ end
106
+ end
107
+
108
+ # Wrapper for Emacs style magic comments.
109
+ #
110
+ # @example Emacs style comment
111
+ # comment = RuboCop::MagicComment.parse(
112
+ # '# -*- encoding: ASCII-8BIT; frozen_string_literal: true -*-'
113
+ # )
114
+ #
115
+ # comment.encoding # => 'ascii-8bit'
116
+ # comment.frozen_string_literal # => true
117
+ #
118
+ # @see https://www.gnu.org/software/emacs/manual/html_node/emacs/Specify-Coding.html
119
+ # @see https://git.io/vMCXh Emacs handling in Ruby's parse.y
120
+ class EmacsComment < EditorComment
121
+ FORMAT = /\-\*\-(.+)\-\*\-/
122
+ SEPARATOR = ';'.freeze
123
+ OPERATOR = ':'.freeze
124
+
125
+ def encoding
126
+ match('encoding')
127
+ end
128
+
129
+ private
130
+
131
+ def extract_frozen_string_literal
132
+ match('frozen_string_literal')
133
+ end
134
+ end
135
+
136
+ # Wrapper for Vim style magic comments.
137
+ #
138
+ # @example Vim style comment
139
+ # comment = RuboCop::MagicComment.parse(
140
+ # '# vim: filetype=ruby, fileencoding=ascii-8bit'
141
+ # )
142
+ #
143
+ # comment.encoding # => 'ascii-8bit'
144
+ class VimComment < EditorComment
145
+ FORMAT = /#\s*vim:\s*(.+)/
146
+ SEPARATOR = ', '.freeze
147
+ OPERATOR = '='.freeze
148
+
149
+ # For some reason the fileencoding keyword only works if there
150
+ # is at least one other token included in the string. For example
151
+ #
152
+ # # works
153
+ # # vim: foo=bar, fileencoding=ascii-8bit
154
+ #
155
+ # # does nothing
156
+ # # vim: foo=bar, fileencoding=ascii-8bit
157
+ #
158
+ def encoding
159
+ match('fileencoding') if tokens.size > 1
160
+ end
161
+
162
+ # Vim comments cannot specify frozen string literal behavior.
163
+ def frozen_string_literal; end
164
+ end
165
+
166
+ # Wrapper for regular magic comments not bound to an editor.
167
+ #
168
+ # Simple comments can only specify one setting per comment.
169
+ #
170
+ # @example frozen string literal comments
171
+ # comment1 = RuboCop::MagicComment.parse('# frozen_string_literal: true')
172
+ # comment1.frozen_string_literal # => true
173
+ # comment1.encoding # => nil
174
+ #
175
+ # @example encoding comments
176
+ # comment2 = RuboCop::MagicComment.parse('# encoding: utf-8')
177
+ # comment2.frozen_string_literal # => nil
178
+ # comment2.encoding # => 'utf-8'
179
+ class SimpleComment < MagicComment
180
+ # Match `encoding` or `coding`
181
+ def encoding
182
+ extract(/\b(?:en)?coding: (#{TOKEN})/)
183
+ end
184
+
185
+ private
186
+
187
+ # Extract `frozen_string_literal`.
188
+ #
189
+ # The `frozen_string_literal` magic comment only works if it
190
+ # is the only text in the comment.
191
+ def extract_frozen_string_literal
192
+ extract(/^#\s*frozen_string_literal:\s*(#{TOKEN})\s*$/)
193
+ end
194
+ end
195
+ end
196
+ end
@@ -179,13 +179,14 @@ module RuboCop
179
179
  def self.validate_cop_list(names)
180
180
  return unless names
181
181
 
182
- namespaces = Cop::Cop.all.types.map { |t| t.to_s.capitalize }
182
+ departments = Cop::Cop.registry.departments.map(&:to_s)
183
+
183
184
  names.each do |name|
184
- next if Cop::Cop.all.any? { |c| c.cop_name == name }
185
- next if namespaces.include?(name)
185
+ next if Cop::Cop.registry.names.include?(name)
186
+ next if departments.include?(name)
186
187
  next if %w(Syntax Lint/Syntax).include?(name)
187
188
 
188
- raise ArgumentError, "Unrecognized cop or namespace: #{name}."
189
+ raise ArgumentError, "Unrecognized cop or department: #{name}."
189
190
  end
190
191
  end
191
192
 
@@ -133,7 +133,7 @@ module RuboCop
133
133
  end
134
134
 
135
135
  def create_parser(ruby_version)
136
- builder = RuboCop::Node::Builder.new
136
+ builder = RuboCop::AST::Builder.new
137
137
 
138
138
  parser_class(ruby_version).new(builder).tap do |parser|
139
139
  # On JRuby and Rubinius, there's a risk that we hang in tokenize() if we
@@ -53,6 +53,15 @@ module CopHelper
53
53
  corrector.rewrite
54
54
  end
55
55
 
56
+ def autocorrect_source_with_loop(cop, source, file = nil)
57
+ loop do
58
+ cop.instance_variable_set(:@corrections, [])
59
+ new_source = autocorrect_source(cop, source, file)
60
+ return new_source if new_source == source
61
+ source = new_source
62
+ end
63
+ end
64
+
56
65
  def _investigate(cop, processed_source)
57
66
  forces = RuboCop::Cop::Force.all.each_with_object([]) do |klass, instances|
58
67
  next unless cop.join_force?(klass)