rubocop 0.90.0 → 0.93.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/config/default.yml +79 -3
  4. data/lib/rubocop.rb +20 -5
  5. data/lib/rubocop/cached_data.rb +2 -1
  6. data/lib/rubocop/cli/command/execute_runner.rb +8 -0
  7. data/lib/rubocop/comment_config.rb +9 -5
  8. data/lib/rubocop/config_loader.rb +3 -3
  9. data/lib/rubocop/config_regeneration.rb +33 -0
  10. data/lib/rubocop/config_store.rb +3 -3
  11. data/lib/rubocop/cop/bundler/duplicated_gem.rb +5 -1
  12. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
  13. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -0
  14. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
  15. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
  16. data/lib/rubocop/cop/generator.rb +1 -1
  17. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
  18. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
  19. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +1 -0
  20. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -0
  21. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -0
  22. data/lib/rubocop/cop/layout/array_alignment.rb +1 -0
  23. data/lib/rubocop/cop/layout/begin_end_alignment.rb +77 -0
  24. data/lib/rubocop/cop/layout/case_indentation.rb +4 -7
  25. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  26. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  27. data/lib/rubocop/cop/layout/dot_position.rb +6 -9
  28. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
  29. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +4 -12
  30. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +13 -8
  31. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -2
  32. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -2
  33. data/lib/rubocop/cop/layout/end_alignment.rb +5 -10
  34. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +26 -4
  35. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +4 -13
  36. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +7 -7
  37. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
  38. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +6 -21
  39. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +3 -8
  40. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +2 -2
  41. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
  42. data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -0
  43. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
  44. data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -2
  45. data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
  46. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +74 -0
  47. data/lib/rubocop/cop/lint/debugger.rb +2 -3
  48. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -3
  49. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -4
  50. data/lib/rubocop/cop/lint/duplicate_require.rb +7 -2
  51. data/lib/rubocop/cop/lint/duplicate_rescue_exception.rb +2 -4
  52. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
  53. data/lib/rubocop/cop/lint/empty_file.rb +1 -4
  54. data/lib/rubocop/cop/lint/erb_new_arguments.rb +2 -0
  55. data/lib/rubocop/cop/lint/float_comparison.rb +2 -2
  56. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  57. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
  58. data/lib/rubocop/cop/lint/identity_comparison.rb +51 -0
  59. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +2 -5
  60. data/lib/rubocop/cop/lint/inherit_exception.rb +2 -2
  61. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  62. data/lib/rubocop/cop/lint/multiple_comparison.rb +3 -1
  63. data/lib/rubocop/cop/lint/number_conversion.rb +1 -0
  64. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -2
  65. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  66. data/lib/rubocop/cop/lint/raise_exception.rb +1 -0
  67. data/lib/rubocop/cop/lint/rand_one.rb +2 -1
  68. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +22 -12
  69. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +14 -4
  70. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
  71. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
  72. data/lib/rubocop/cop/lint/rescue_type.rb +0 -1
  73. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +3 -1
  74. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -6
  75. data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
  76. data/lib/rubocop/cop/lint/to_json.rb +16 -5
  77. data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -6
  78. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +3 -1
  79. data/lib/rubocop/cop/lint/uri_regexp.rb +2 -1
  80. data/lib/rubocop/cop/lint/useless_access_modifier.rb +3 -9
  81. data/lib/rubocop/cop/lint/useless_method_definition.rb +20 -27
  82. data/lib/rubocop/cop/lint/useless_times.rb +106 -0
  83. data/lib/rubocop/cop/metrics/block_length.rb +3 -1
  84. data/lib/rubocop/cop/metrics/class_length.rb +14 -6
  85. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +25 -16
  86. data/lib/rubocop/cop/mixin/comments_help.rb +3 -9
  87. data/lib/rubocop/cop/mixin/configurable_naming.rb +2 -2
  88. data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
  89. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +9 -0
  90. data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -2
  91. data/lib/rubocop/cop/mixin/rescue_node.rb +1 -0
  92. data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -3
  93. data/lib/rubocop/cop/mixin/visibility_help.rb +4 -16
  94. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -1
  95. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  96. data/lib/rubocop/cop/offense.rb +15 -2
  97. data/lib/rubocop/cop/security/eval.rb +1 -0
  98. data/lib/rubocop/cop/security/json_load.rb +1 -0
  99. data/lib/rubocop/cop/security/marshal_load.rb +1 -0
  100. data/lib/rubocop/cop/security/open.rb +1 -0
  101. data/lib/rubocop/cop/security/yaml_load.rb +1 -0
  102. data/lib/rubocop/cop/style/access_modifier_declarations.rb +7 -11
  103. data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
  104. data/lib/rubocop/cop/style/alias.rb +2 -0
  105. data/lib/rubocop/cop/style/array_coercion.rb +4 -0
  106. data/lib/rubocop/cop/style/array_join.rb +1 -0
  107. data/lib/rubocop/cop/style/attr.rb +1 -0
  108. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +2 -0
  109. data/lib/rubocop/cop/style/case_equality.rb +3 -0
  110. data/lib/rubocop/cop/style/case_like_if.rb +20 -4
  111. data/lib/rubocop/cop/style/class_and_module_children.rb +2 -0
  112. data/lib/rubocop/cop/style/class_check.rb +6 -9
  113. data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
  114. data/lib/rubocop/cop/style/class_methods_definitions.rb +42 -16
  115. data/lib/rubocop/cop/style/class_vars.rb +1 -2
  116. data/lib/rubocop/cop/style/combinable_loops.rb +13 -11
  117. data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
  118. data/lib/rubocop/cop/style/commented_keyword.rb +7 -8
  119. data/lib/rubocop/cop/style/conditional_assignment.rb +49 -60
  120. data/lib/rubocop/cop/style/date_time.rb +12 -1
  121. data/lib/rubocop/cop/style/dir.rb +1 -0
  122. data/lib/rubocop/cop/style/double_negation.rb +1 -0
  123. data/lib/rubocop/cop/style/empty_literal.rb +3 -1
  124. data/lib/rubocop/cop/style/eval_with_location.rb +1 -3
  125. data/lib/rubocop/cop/style/even_odd.rb +1 -0
  126. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -2
  127. data/lib/rubocop/cop/style/explicit_block_argument.rb +7 -3
  128. data/lib/rubocop/cop/style/float_division.rb +2 -0
  129. data/lib/rubocop/cop/style/for.rb +0 -4
  130. data/lib/rubocop/cop/style/format_string.rb +1 -4
  131. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  132. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +24 -5
  133. data/lib/rubocop/cop/style/hash_transform_keys.rb +5 -11
  134. data/lib/rubocop/cop/style/hash_transform_values.rb +5 -11
  135. data/lib/rubocop/cop/style/if_unless_modifier.rb +0 -4
  136. data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
  137. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -6
  138. data/lib/rubocop/cop/style/lambda_call.rb +3 -1
  139. data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
  140. data/lib/rubocop/cop/style/mixin_usage.rb +8 -27
  141. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -2
  142. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +14 -1
  143. data/lib/rubocop/cop/style/multiline_when_then.rb +1 -0
  144. data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
  145. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  146. data/lib/rubocop/cop/style/non_nil_check.rb +2 -0
  147. data/lib/rubocop/cop/style/not.rb +1 -0
  148. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -3
  149. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -1
  150. data/lib/rubocop/cop/style/optional_boolean_parameter.rb +12 -1
  151. data/lib/rubocop/cop/style/preferred_hash_methods.rb +2 -0
  152. data/lib/rubocop/cop/style/raise_args.rb +2 -3
  153. data/lib/rubocop/cop/style/random_with_offset.rb +4 -3
  154. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -9
  155. data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
  156. data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
  157. data/lib/rubocop/cop/style/redundant_conditional.rb +4 -5
  158. data/lib/rubocop/cop/style/redundant_exception.rb +1 -3
  159. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
  160. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -1
  161. data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
  162. data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -6
  163. data/lib/rubocop/cop/style/redundant_percent_q.rb +9 -11
  164. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +39 -24
  165. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
  166. data/lib/rubocop/cop/style/redundant_return.rb +17 -17
  167. data/lib/rubocop/cop/style/redundant_self.rb +7 -9
  168. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -2
  169. data/lib/rubocop/cop/style/redundant_sort.rb +12 -29
  170. data/lib/rubocop/cop/style/redundant_sort_by.rb +5 -9
  171. data/lib/rubocop/cop/style/rescue_standard_error.rb +20 -16
  172. data/lib/rubocop/cop/style/safe_navigation.rb +5 -0
  173. data/lib/rubocop/cop/style/sample.rb +2 -1
  174. data/lib/rubocop/cop/style/send.rb +2 -3
  175. data/lib/rubocop/cop/style/signal_exception.rb +2 -0
  176. data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
  177. data/lib/rubocop/cop/style/slicing_with_range.rb +2 -1
  178. data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
  179. data/lib/rubocop/cop/style/string_concatenation.rb +17 -3
  180. data/lib/rubocop/cop/style/strip.rb +1 -0
  181. data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -3
  182. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +4 -3
  183. data/lib/rubocop/cop/style/unpack_first.rb +1 -0
  184. data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -5
  185. data/lib/rubocop/cop/util.rb +0 -1
  186. data/lib/rubocop/cop/variable_force/branch.rb +0 -4
  187. data/lib/rubocop/core_ext/string.rb +1 -1
  188. data/lib/rubocop/directive_comment.rb +32 -0
  189. data/lib/rubocop/ext/regexp_node.rb +23 -7
  190. data/lib/rubocop/formatter/disabled_config_formatter.rb +12 -5
  191. data/lib/rubocop/options.rb +37 -17
  192. data/lib/rubocop/result_cache.rb +38 -15
  193. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  194. data/lib/rubocop/rspec/expect_offense.rb +5 -5
  195. data/lib/rubocop/runner.rb +37 -18
  196. data/lib/rubocop/target_finder.rb +27 -26
  197. data/lib/rubocop/target_ruby.rb +1 -1
  198. data/lib/rubocop/version.rb +6 -1
  199. metadata +19 -18
  200. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
  201. data/lib/rubocop/cop/tokens_util.rb +0 -84
@@ -3,6 +3,7 @@
3
3
  require 'digest/sha1'
4
4
  require 'find'
5
5
  require 'etc'
6
+ require 'zlib'
6
7
 
7
8
  module RuboCop
8
9
  # Provides functionality for caching rubocop runs.
@@ -30,6 +31,11 @@ module RuboCop
30
31
  end
31
32
 
32
33
  class << self
34
+ # @api private
35
+ attr_accessor :rubocop_required_features
36
+
37
+ ResultCache.rubocop_required_features = []
38
+
33
39
  private
34
40
 
35
41
  def requires_file_removal?(file_count, config_store)
@@ -61,7 +67,8 @@ module RuboCop
61
67
  end
62
68
 
63
69
  def self.cache_root(config_store)
64
- root = config_store.for_pwd.for_all_cops['CacheRootDirectory']
70
+ root = ENV['RUBOCOP_CACHE_ROOT']
71
+ root ||= config_store.for_pwd.for_all_cops['CacheRootDirectory']
65
72
  root ||= if ENV.key?('XDG_CACHE_HOME')
66
73
  # Include user ID in the path to make sure the user has write
67
74
  # access.
@@ -76,7 +83,10 @@ module RuboCop
76
83
  config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
77
84
  end
78
85
 
86
+ attr :path
87
+
79
88
  def initialize(file, team, options, config_store, cache_root = nil)
89
+ cache_root ||= options[:cache_root]
80
90
  cache_root ||= ResultCache.cache_root(config_store)
81
91
  @allow_symlinks_in_cache_location =
82
92
  ResultCache.allow_symlinks_in_cache_location?(config_store)
@@ -85,6 +95,11 @@ module RuboCop
85
95
  context_checksum(team, options),
86
96
  file_checksum(file, config_store))
87
97
  @cached_data = CachedData.new(file)
98
+ @debug = options[:debug]
99
+ end
100
+
101
+ def debug?
102
+ @debug
88
103
  end
89
104
 
90
105
  def valid?
@@ -92,6 +107,7 @@ module RuboCop
92
107
  end
93
108
 
94
109
  def load
110
+ puts "Loading cache from #{@path}" if debug?
95
111
  @cached_data.from_json(IO.read(@path, encoding: Encoding::UTF_8))
96
112
  end
97
113
 
@@ -159,27 +175,34 @@ module RuboCop
159
175
  end
160
176
 
161
177
  # The checksum of the rubocop program running the inspection.
162
- # rubocop:disable Metrics/AbcSize
163
178
  def rubocop_checksum
164
179
  ResultCache.source_checksum ||=
165
180
  begin
166
- lib_root = File.join(File.dirname(__FILE__), '..')
167
- exe_root = File.join(lib_root, '..', 'exe')
168
-
169
- # These are all the files we have `require`d plus everything in the
170
- # exe directory. A change to any of them could affect the cop output
171
- # so we include them in the cache hash.
172
- source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
173
-
174
181
  digest = Digest::SHA1.new
175
- source_files
182
+ rubocop_extra_features
176
183
  .select { |path| File.file?(path) }
177
184
  .sort!
178
- .each { |path| digest << File.mtime(path).to_s }
185
+ .each do |path|
186
+ content = File.open(path, 'rb', &:read)
187
+ digest << Zlib.crc32(content).to_s # mtime not reliable
188
+ end
189
+ digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING
179
190
  digest.hexdigest
180
191
  end
181
192
  end
182
- # rubocop:enable Metrics/AbcSize
193
+
194
+ def rubocop_extra_features
195
+ lib_root = File.join(File.dirname(__FILE__), '..')
196
+ exe_root = File.join(lib_root, '..', 'exe')
197
+
198
+ # These are all the files we have `require`d plus everything in the
199
+ # exe directory. A change to any of them could affect the cop output
200
+ # so we include them in the cache hash.
201
+ source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
202
+ source_files -= ResultCache.rubocop_required_features # Rely on gem versions
203
+
204
+ source_files
205
+ end
183
206
 
184
207
  # Return a hash of the options given at invocation, minus the ones that have
185
208
  # no effect on which offenses and disabled line ranges are found, and thus
@@ -192,8 +215,8 @@ module RuboCop
192
215
  # The external dependency checksums are cached per RuboCop team so that
193
216
  # the checksums don't need to be recomputed for each file.
194
217
  def team_checksum(team)
195
- @checksum_by_team ||= {}
196
- @checksum_by_team[team.object_id] ||= team.external_dependency_checksum
218
+ @checksum_by_team ||= {}.compare_by_identity
219
+ @checksum_by_team[team] ||= team.external_dependency_checksum
197
220
  end
198
221
 
199
222
  # We combine team and options into a single "context" checksum to avoid
@@ -26,7 +26,7 @@ module CopHelper
26
26
  end
27
27
 
28
28
  def parse_source(source, file = nil)
29
- if file&.respond_to?(:write)
29
+ if file.respond_to?(:write)
30
30
  file.write(source)
31
31
  file.rewind
32
32
  file = file.path
@@ -133,14 +133,14 @@ module RuboCop
133
133
  "#{@processed_source.diagnostics.map(&:render).join("\n")}"
134
134
  end
135
135
 
136
- offenses = _investigate(cop, @processed_source)
136
+ @offenses = _investigate(cop, @processed_source)
137
137
  actual_annotations =
138
- expected_annotations.with_offense_annotations(offenses)
138
+ expected_annotations.with_offense_annotations(@offenses)
139
139
 
140
140
  expect(actual_annotations).to eq(expected_annotations), ''
141
- expect(offenses.map(&:severity).uniq).to eq([severity]) if severity
141
+ expect(@offenses.map(&:severity).uniq).to eq([severity]) if severity
142
142
 
143
- offenses
143
+ @offenses
144
144
  end
145
145
 
146
146
  def expect_correction(correction, loop: true)
@@ -157,7 +157,7 @@ module RuboCop
157
157
  break corrected_source if corrected_source == @processed_source.buffer.source
158
158
 
159
159
  if iteration > RuboCop::Runner::MAX_ITERATIONS
160
- raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [])
160
+ raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
161
161
  end
162
162
 
163
163
  # Prepare for next loop
@@ -11,9 +11,16 @@ module RuboCop
11
11
  class InfiniteCorrectionLoop < RuntimeError
12
12
  attr_reader :offenses
13
13
 
14
- def initialize(path, offenses)
15
- super "Infinite loop detected in #{path}."
16
- @offenses = offenses
14
+ def initialize(path, offenses_by_iteration, loop_start: -1)
15
+ @offenses = offenses_by_iteration.flatten.uniq
16
+ root_cause = offenses_by_iteration[loop_start..-1]
17
+ .map { |x| x.map(&:cop_name).uniq.join(', ') }
18
+ .join(' -> ')
19
+
20
+ message = 'Infinite loop detected'
21
+ message += " in #{path}" if path
22
+ message += " and caused by #{root_cause}" if root_cause
23
+ super message
17
24
  end
18
25
  end
19
26
 
@@ -81,7 +88,10 @@ module RuboCop
81
88
  # OPTIMIZE: Calling `ResultCache.cleanup` takes time. This optimization
82
89
  # mainly targets editors that integrates RuboCop. When RuboCop is run
83
90
  # by an editor, it should be inspecting only one file.
84
- ResultCache.cleanup(@config_store, @options[:debug]) if files.size > 1 && cached_run?
91
+ if files.size > 1 && cached_run?
92
+ ResultCache.cleanup(@config_store, @options[:debug], @options[:cache_root])
93
+ end
94
+
85
95
  formatter_set.finished(inspected_files.freeze)
86
96
  formatter_set.close_output_files
87
97
  end
@@ -233,18 +243,21 @@ module RuboCop
233
243
 
234
244
  def do_inspection_loop(file)
235
245
  processed_source = get_processed_source(file)
236
- offenses = []
246
+ # This variable is 2d array used to track corrected offenses after each
247
+ # inspection iteration. This is used to output meaningful infinite loop
248
+ # error message.
249
+ offenses_by_iteration = []
237
250
 
238
251
  # When running with --auto-correct, we need to inspect the file (which
239
252
  # includes writing a corrected version of it) until no more corrections
240
253
  # are made. This is because automatic corrections can introduce new
241
254
  # offenses. In the normal case the loop is only executed once.
242
- iterate_until_no_changes(processed_source, offenses) do
255
+ iterate_until_no_changes(processed_source, offenses_by_iteration) do
243
256
  # The offenses that couldn't be corrected will be found again so we
244
257
  # only keep the corrected ones in order to avoid duplicate reporting.
245
- offenses.select!(&:corrected?)
258
+ !offenses_by_iteration.empty? && offenses_by_iteration.last.select!(&:corrected?)
246
259
  new_offenses, updated_source_file = inspect_file(processed_source)
247
- offenses.concat(new_offenses).uniq!
260
+ offenses_by_iteration.push(new_offenses)
248
261
 
249
262
  # We have to reprocess the source to pickup the changes. Since the
250
263
  # change could (theoretically) introduce parsing errors, we break the
@@ -254,10 +267,12 @@ module RuboCop
254
267
  processed_source = get_processed_source(file)
255
268
  end
256
269
 
270
+ # Return summary of corrected offenses after all iterations
271
+ offenses = offenses_by_iteration.flatten.uniq
257
272
  [processed_source, offenses]
258
273
  end
259
274
 
260
- def iterate_until_no_changes(source, offenses)
275
+ def iterate_until_no_changes(source, offenses_by_iteration)
261
276
  # Keep track of the state of the source. If a cop modifies the source
262
277
  # and another cop undoes it producing identical source we have an
263
278
  # infinite loop.
@@ -269,10 +284,10 @@ module RuboCop
269
284
  iterations = 0
270
285
 
271
286
  loop do
272
- check_for_infinite_loop(source, offenses)
287
+ check_for_infinite_loop(source, offenses_by_iteration)
273
288
 
274
289
  if (iterations += 1) > MAX_ITERATIONS
275
- raise InfiniteCorrectionLoop.new(source.path, offenses)
290
+ raise InfiniteCorrectionLoop.new(source.path, offenses_by_iteration)
276
291
  end
277
292
 
278
293
  source = yield
@@ -282,11 +297,15 @@ module RuboCop
282
297
 
283
298
  # Check whether a run created source identical to a previous run, which
284
299
  # means that we definitely have an infinite loop.
285
- def check_for_infinite_loop(processed_source, offenses)
300
+ def check_for_infinite_loop(processed_source, offenses_by_iteration)
286
301
  checksum = processed_source.checksum
287
302
 
288
- if @processed_sources.include?(checksum)
289
- raise InfiniteCorrectionLoop.new(processed_source.path, offenses)
303
+ if (loop_start_index = @processed_sources.index(checksum))
304
+ raise InfiniteCorrectionLoop.new(
305
+ processed_source.path,
306
+ offenses_by_iteration,
307
+ loop_start: loop_start_index
308
+ )
290
309
  end
291
310
 
292
311
  @processed_sources << checksum
@@ -305,8 +324,8 @@ module RuboCop
305
324
  end
306
325
 
307
326
  def mobilized_cop_classes(config)
308
- @mobilized_cop_classes ||= {}
309
- @mobilized_cop_classes[config.object_id] ||= begin
327
+ @mobilized_cop_classes ||= {}.compare_by_identity
328
+ @mobilized_cop_classes[config] ||= begin
310
329
  cop_classes = Cop::Registry.all
311
330
 
312
331
  OptionsValidator.new(@options).validate_cop_options
@@ -380,8 +399,8 @@ module RuboCop
380
399
  # otherwise dormant team that can be used for config- and option-
381
400
  # level caching in ResultCache.
382
401
  def standby_team(config)
383
- @team_by_config ||= {}
384
- @team_by_config[config.object_id] ||=
402
+ @team_by_config ||= {}.compare_by_identity
403
+ @team_by_config[config] ||=
385
404
  Cop::Team.mobilize(mobilized_cop_classes(config), config, @options)
386
405
  end
387
406
  end
@@ -5,6 +5,8 @@ module RuboCop
5
5
  # and picking ruby files.
6
6
  # @api private
7
7
  class TargetFinder
8
+ HIDDEN_PATH_SUBSTRING = "#{File::SEPARATOR}."
9
+
8
10
  def initialize(config_store, options = {})
9
11
  @config_store = config_store
10
12
  @options = options
@@ -55,7 +57,8 @@ module RuboCop
55
57
  # Support Windows: Backslashes from command-line -> forward slashes
56
58
  base_dir = base_dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
57
59
  all_files = find_files(base_dir, File::FNM_DOTMATCH)
58
- hidden_files = Set.new(all_files - find_files(base_dir, 0))
60
+ # use file.include? for performance optimization
61
+ hidden_files = all_files.select { |file| file.include?(HIDDEN_PATH_SUBSTRING) }
59
62
  base_dir_config = @config_store.for(base_dir)
60
63
 
61
64
  target_files = all_files.select do |file|
@@ -78,34 +81,32 @@ module RuboCop
78
81
  # the top level directories that are excluded in configuration in the
79
82
  # normal way (dir/**/*).
80
83
  def find_files(base_dir, flags)
81
- wanted_toplevel_dirs = toplevel_dirs(base_dir, flags) -
82
- excluded_dirs(base_dir)
83
- wanted_toplevel_dirs.map! { |dir| dir << '/**/*' }
84
-
85
- pattern = if wanted_toplevel_dirs.empty?
86
- # We need this special case to avoid creating the pattern
87
- # /**/* which searches the entire file system.
88
- ["#{base_dir}/**/*"]
89
- else
90
- # Search the non-excluded top directories, but also add files
91
- # on the top level, which would otherwise not be found.
92
- wanted_toplevel_dirs.unshift("#{base_dir}/*")
84
+ # get all wanted directories first to improve speed of finding all files
85
+ exclude_pattern = combined_exclude_glob_patterns(base_dir)
86
+ dir_flags = flags | File::FNM_PATHNAME | File::FNM_EXTGLOB
87
+ patterns = wanted_dir_patterns(base_dir, exclude_pattern, dir_flags)
88
+ patterns.map! { |dir| File.join(dir, '*') }
89
+ # We need this special case to avoid creating the pattern
90
+ # /**/* which searches the entire file system.
91
+ patterns = [File.join(dir, '**/*')] if patterns.empty?
92
+
93
+ Dir.glob(patterns, flags).select { |path| FileTest.file?(path) }
94
+ end
95
+
96
+ def wanted_dir_patterns(base_dir, exclude_pattern, flags)
97
+ dirs = Dir.glob(File.join(base_dir, '*/'), flags)
98
+ .reject do |dir|
99
+ dir.end_with?('/./', '/../') || File.fnmatch?(exclude_pattern, dir, flags)
93
100
  end
94
- Dir.glob(pattern, flags).select { |path| FileTest.file?(path) }
101
+ dirs.flat_map { |dir| wanted_dir_patterns(dir, exclude_pattern, flags) }
102
+ .unshift(base_dir)
95
103
  end
96
104
 
97
- def toplevel_dirs(base_dir, flags)
98
- Dir.glob(File.join(base_dir, '*'), flags).select do |dir|
99
- File.directory?(dir) && !dir.end_with?('/.', '/..')
100
- end
101
- end
102
-
103
- def excluded_dirs(base_dir)
104
- all_cops_config = @config_store.for(base_dir).for_all_cops
105
- dir_tree_excludes = all_cops_config['Exclude'].select do |pattern|
106
- pattern.is_a?(String) && pattern.end_with?('/**/*')
107
- end
108
- dir_tree_excludes.map { |pattern| pattern.sub(%r{/\*\*/\*$}, '') }
105
+ def combined_exclude_glob_patterns(base_dir)
106
+ exclude = @config_store.for(base_dir).for_all_cops['Exclude']
107
+ patterns = exclude.select { |pattern| pattern.is_a?(String) && pattern.end_with?('/**/*') }
108
+ .map { |pattern| pattern.sub("#{base_dir}/", '') }
109
+ "#{base_dir}/{#{patterns.join(',')}}"
109
110
  end
110
111
 
111
112
  def ruby_extension?(file)
@@ -4,7 +4,7 @@ module RuboCop
4
4
  # The kind of Ruby that code inspected by RuboCop is written in.
5
5
  # @api private
6
6
  class TargetRuby
7
- KNOWN_RUBIES = [2.4, 2.5, 2.6, 2.7, 2.8].freeze
7
+ KNOWN_RUBIES = [2.4, 2.5, 2.6, 2.7, 3.0].freeze
8
8
  DEFAULT_VERSION = KNOWN_RUBIES.first
9
9
 
10
10
  OBSOLETE_RUBIES = {
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '0.90.0'
6
+ STRING = '0.93.1'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, '\
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
@@ -20,5 +20,10 @@ module RuboCop
20
20
  STRING
21
21
  end
22
22
  end
23
+
24
+ # @api private
25
+ def self.document_version
26
+ STRING.match('\d+\.\d+').to_s
27
+ end
23
28
  end
24
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.90.0
4
+ version: 0.93.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2020-09-01 00:00:00.000000000 Z
13
+ date: 2020-10-12 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parallel
@@ -32,14 +32,14 @@ dependencies:
32
32
  requirements:
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 2.7.1.1
35
+ version: 2.7.1.5
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 2.7.1.1
42
+ version: 2.7.1.5
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: rainbow
45
45
  requirement: !ruby/object:Gem::Requirement
@@ -66,14 +66,14 @@ dependencies:
66
66
  requirements:
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: '1.7'
69
+ version: '1.8'
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - ">="
75
75
  - !ruby/object:Gem::Version
76
- version: '1.7'
76
+ version: '1.8'
77
77
  - !ruby/object:Gem::Dependency
78
78
  name: rexml
79
79
  requirement: !ruby/object:Gem::Requirement
@@ -94,20 +94,14 @@ dependencies:
94
94
  requirements:
95
95
  - - ">="
96
96
  - !ruby/object:Gem::Version
97
- version: 0.3.0
98
- - - "<"
99
- - !ruby/object:Gem::Version
100
- version: '1.0'
97
+ version: 0.6.0
101
98
  type: :runtime
102
99
  prerelease: false
103
100
  version_requirements: !ruby/object:Gem::Requirement
104
101
  requirements:
105
102
  - - ">="
106
103
  - !ruby/object:Gem::Version
107
- version: 0.3.0
108
- - - "<"
109
- - !ruby/object:Gem::Version
110
- version: '1.0'
104
+ version: 0.6.0
111
105
  - !ruby/object:Gem::Dependency
112
106
  name: ruby-progressbar
113
107
  requirement: !ruby/object:Gem::Requirement
@@ -199,6 +193,7 @@ files:
199
193
  - lib/rubocop/config_loader.rb
200
194
  - lib/rubocop/config_loader_resolver.rb
201
195
  - lib/rubocop/config_obsoletion.rb
196
+ - lib/rubocop/config_regeneration.rb
202
197
  - lib/rubocop/config_store.rb
203
198
  - lib/rubocop/config_validator.rb
204
199
  - lib/rubocop/cop/autocorrect_logic.rb
@@ -248,6 +243,7 @@ files:
248
243
  - lib/rubocop/cop/layout/argument_alignment.rb
249
244
  - lib/rubocop/cop/layout/array_alignment.rb
250
245
  - lib/rubocop/cop/layout/assignment_indentation.rb
246
+ - lib/rubocop/cop/layout/begin_end_alignment.rb
251
247
  - lib/rubocop/cop/layout/block_alignment.rb
252
248
  - lib/rubocop/cop/layout/block_end_newline.rb
253
249
  - lib/rubocop/cop/layout/case_indentation.rb
@@ -345,6 +341,7 @@ files:
345
341
  - lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb
346
342
  - lib/rubocop/cop/lint/boolean_symbol.rb
347
343
  - lib/rubocop/cop/lint/circular_argument_reference.rb
344
+ - lib/rubocop/cop/lint/constant_definition_in_block.rb
348
345
  - lib/rubocop/cop/lint/constant_resolution.rb
349
346
  - lib/rubocop/cop/lint/debugger.rb
350
347
  - lib/rubocop/cop/lint/deprecated_class_methods.rb
@@ -370,7 +367,9 @@ files:
370
367
  - lib/rubocop/cop/lint/float_comparison.rb
371
368
  - lib/rubocop/cop/lint/float_out_of_range.rb
372
369
  - lib/rubocop/cop/lint/format_parameter_mismatch.rb
370
+ - lib/rubocop/cop/lint/hash_compare_by_identity.rb
373
371
  - lib/rubocop/cop/lint/heredoc_method_call_position.rb
372
+ - lib/rubocop/cop/lint/identity_comparison.rb
374
373
  - lib/rubocop/cop/lint/implicit_string_concatenation.rb
375
374
  - lib/rubocop/cop/lint/ineffective_access_modifier.rb
376
375
  - lib/rubocop/cop/lint/inherit_exception.rb
@@ -398,6 +397,7 @@ files:
398
397
  - lib/rubocop/cop/lint/redundant_cop_disable_directive.rb
399
398
  - lib/rubocop/cop/lint/redundant_cop_enable_directive.rb
400
399
  - lib/rubocop/cop/lint/redundant_require_statement.rb
400
+ - lib/rubocop/cop/lint/redundant_safe_navigation.rb
401
401
  - lib/rubocop/cop/lint/redundant_splat_expansion.rb
402
402
  - lib/rubocop/cop/lint/redundant_string_coercion.rb
403
403
  - lib/rubocop/cop/lint/redundant_with_index.rb
@@ -435,6 +435,7 @@ files:
435
435
  - lib/rubocop/cop/lint/useless_else_without_rescue.rb
436
436
  - lib/rubocop/cop/lint/useless_method_definition.rb
437
437
  - lib/rubocop/cop/lint/useless_setter_call.rb
438
+ - lib/rubocop/cop/lint/useless_times.rb
438
439
  - lib/rubocop/cop/lint/void.rb
439
440
  - lib/rubocop/cop/message_annotator.rb
440
441
  - lib/rubocop/cop/metrics/abc_size.rb
@@ -502,7 +503,6 @@ files:
502
503
  - lib/rubocop/cop/mixin/preferred_delimiters.rb
503
504
  - lib/rubocop/cop/mixin/range_help.rb
504
505
  - lib/rubocop/cop/mixin/rational_literal.rb
505
- - lib/rubocop/cop/mixin/regexp_literal_help.rb
506
506
  - lib/rubocop/cop/mixin/rescue_node.rb
507
507
  - lib/rubocop/cop/mixin/safe_assignment.rb
508
508
  - lib/rubocop/cop/mixin/space_after_punctuation.rb
@@ -560,6 +560,7 @@ files:
560
560
  - lib/rubocop/cop/style/character_literal.rb
561
561
  - lib/rubocop/cop/style/class_and_module_children.rb
562
562
  - lib/rubocop/cop/style/class_check.rb
563
+ - lib/rubocop/cop/style/class_equality_comparison.rb
563
564
  - lib/rubocop/cop/style/class_methods.rb
564
565
  - lib/rubocop/cop/style/class_methods_definitions.rb
565
566
  - lib/rubocop/cop/style/class_vars.rb
@@ -740,7 +741,6 @@ files:
740
741
  - lib/rubocop/cop/style/yoda_condition.rb
741
742
  - lib/rubocop/cop/style/zero_length_predicate.rb
742
743
  - lib/rubocop/cop/team.rb
743
- - lib/rubocop/cop/tokens_util.rb
744
744
  - lib/rubocop/cop/util.rb
745
745
  - lib/rubocop/cop/utils/format_string.rb
746
746
  - lib/rubocop/cop/variable_force.rb
@@ -753,6 +753,7 @@ files:
753
753
  - lib/rubocop/cop/variable_force/variable_table.rb
754
754
  - lib/rubocop/cops_documentation_generator.rb
755
755
  - lib/rubocop/core_ext/string.rb
756
+ - lib/rubocop/directive_comment.rb
756
757
  - lib/rubocop/error.rb
757
758
  - lib/rubocop/ext/processed_source.rb
758
759
  - lib/rubocop/ext/regexp_node.rb
@@ -804,7 +805,7 @@ metadata:
804
805
  homepage_uri: https://rubocop.org/
805
806
  changelog_uri: https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md
806
807
  source_code_uri: https://github.com/rubocop-hq/rubocop/
807
- documentation_uri: https://docs.rubocop.org/
808
+ documentation_uri: https://docs.rubocop.org/rubocop/0.93/
808
809
  bug_tracker_uri: https://github.com/rubocop-hq/rubocop/issues
809
810
  post_install_message:
810
811
  rdoc_options: []
@@ -821,7 +822,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
821
822
  - !ruby/object:Gem::Version
822
823
  version: '0'
823
824
  requirements: []
824
- rubygems_version: 3.1.2
825
+ rubygems_version: 3.1.4
825
826
  signing_key:
826
827
  specification_version: 4
827
828
  summary: Automatic Ruby code style checking tool.