rubocop 0.57.2 → 0.58.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -9
  3. data/bin/setup +7 -0
  4. data/config/default.yml +18 -2
  5. data/config/disabled.yml +4 -0
  6. data/lib/rubocop.rb +1 -0
  7. data/lib/rubocop/ast/node.rb +5 -0
  8. data/lib/rubocop/ast/node/str_node.rb +2 -0
  9. data/lib/rubocop/cli.rb +4 -7
  10. data/lib/rubocop/config.rb +4 -4
  11. data/lib/rubocop/config_loader.rb +4 -8
  12. data/lib/rubocop/cop/corrector.rb +25 -0
  13. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +3 -7
  14. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  15. data/lib/rubocop/cop/layout/indentation_width.rb +9 -1
  16. data/lib/rubocop/cop/layout/leading_blank_lines.rb +1 -1
  17. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +28 -51
  18. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  19. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -3
  20. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +1 -1
  21. data/lib/rubocop/cop/lint/useless_access_modifier.rb +17 -4
  22. data/lib/rubocop/cop/metrics/line_length.rb +28 -6
  23. data/lib/rubocop/cop/mixin/check_assignment.rb +0 -2
  24. data/lib/rubocop/cop/mixin/statement_modifier.rb +6 -1
  25. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +79 -4
  26. data/lib/rubocop/cop/performance/inefficient_hash_search.rb +9 -5
  27. data/lib/rubocop/cop/performance/range_include.rb +9 -3
  28. data/lib/rubocop/cop/performance/sample.rb +6 -4
  29. data/lib/rubocop/cop/rails/bulk_change_table.rb +11 -7
  30. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +3 -1
  31. data/lib/rubocop/cop/registry.rb +11 -2
  32. data/lib/rubocop/cop/style/encoding.rb +5 -0
  33. data/lib/rubocop/cop/style/end_block.rb +8 -0
  34. data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -1
  35. data/lib/rubocop/cop/style/ip_addresses.rb +76 -0
  36. data/lib/rubocop/cop/style/multiple_comparison.rb +16 -2
  37. data/lib/rubocop/cop/style/symbol_proc.rb +4 -2
  38. data/lib/rubocop/cop/style/unneeded_condition.rb +19 -2
  39. data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -3
  40. data/lib/rubocop/options.rb +20 -12
  41. data/lib/rubocop/processed_source.rb +2 -5
  42. data/lib/rubocop/rspec/cop_helper.rb +0 -4
  43. data/lib/rubocop/rspec/shared_contexts.rb +0 -4
  44. data/lib/rubocop/rspec/shared_examples.rb +0 -23
  45. data/lib/rubocop/version.rb +1 -1
  46. metadata +7 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '059456c464bec007ceecf522ade27bd7cf5e7c5a'
4
- data.tar.gz: cfe7d827a44e1a84835870f38d25c4f9b13a4a00
3
+ metadata.gz: f3841f2f7a2e69362f57238be2722eb4f06bccf8
4
+ data.tar.gz: '0193123e23f57b0cea3701b8f59c90c2ea6b0658'
5
5
  SHA512:
6
- metadata.gz: bdd27ccbc33113527d0d6bfbdc83cc48cf83d1a00b1162328b25fa67b062b7d13330bb5011628aab74dacbcb690610f26e4e209361c1565c4ff9341c4e32cb48
7
- data.tar.gz: '092c870e83c677788d8d314a1869a84a2a505090fc5c703f10145d1ad513231087d539a497050d985e483cf869a46b8fb96424b3465933796683972f9b02928a'
6
+ metadata.gz: 59d32b347c6000e8b1b23981d00cde8017bee3870e941fd72482d415de3966c3928c11b566489ba55e22545d8243e82008df7c5ba4c69e788a75c878df2d13dd
7
+ data.tar.gz: 85337f25210448131a7bc0be46a654fd71db0590c5269a328208fbb874e82b79647150b09d64a2a1178bd7d322c013642bd1ecb59ba17516c276a1e31461916d
data/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/rubocop.svg)](http://badge.fury.io/rb/rubocop)
2
2
  [![Travis Status](https://travis-ci.org/rubocop-hq/rubocop.svg?branch=master)](https://travis-ci.org/rubocop-hq/rubocop)
3
+ [![CircleCI Status](https://circleci.com/gh/rubocop-hq/rubocop/tree/master.svg?style=svg)](https://circleci.com/gh/rubocop-hq/rubocop/tree/master)
3
4
  [![AppVeyor Status](https://ci.appveyor.com/api/projects/status/sj3ye7n5690d0nvg?svg=true)](https://ci.appveyor.com/project/bbatsov/rubocop)
4
5
  [![Coverage Status](https://img.shields.io/codeclimate/coverage/github/bbatsov/rubocop.svg)](https://codeclimate.com/github/bbatsov/rubocop)
5
6
  [![Code Climate](https://codeclimate.com/github/bbatsov/rubocop/badges/gpa.svg)](https://codeclimate.com/github/bbatsov/rubocop)
6
7
  [![Inline docs](http://inch-ci.org/github/bbatsov/rubocop.svg)](http://inch-ci.org/github/bbatsov/rubocop)
8
+ [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=rubocop&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=rubocop&package-manager=bundler&version-scheme=semver)
7
9
 
8
10
  [![Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)](https://www.patreon.com/bbatsov)
9
11
  [![Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/bbatsov/donate)
@@ -11,7 +13,7 @@
11
13
  [![OpenCollective](https://opencollective.com/rubocop/sponsors/badge.svg)](#open-collective-sponsors)
12
14
 
13
15
  <p align="center">
14
- <img src="https://raw.githubusercontent.com/bbatsov/rubocop/master/logo/rubo-logo-horizontal.png" alt="RuboCop Logo"/>
16
+ <img src="https://raw.githubusercontent.com/rubocop-hq/rubocop/master/logo/rubo-logo-horizontal.png" alt="RuboCop Logo"/>
15
17
  </p>
16
18
 
17
19
  > Role models are important. <br/>
@@ -19,10 +21,10 @@
19
21
 
20
22
  **RuboCop** is a Ruby static code analyzer. Out of the box it will
21
23
  enforce many of the guidelines outlined in the community
22
- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide).
24
+ [Ruby Style Guide](https://github.com/rubocop-hq/ruby-style-guide).
23
25
 
24
26
  Most aspects of its behavior can be tweaked via various
25
- [configuration options](https://github.com/bbatsov/rubocop/blob/master/config/default.yml).
27
+ [configuration options](https://github.com/rubocop-hq/rubocop/blob/master/config/default.yml).
26
28
 
27
29
  Apart from reporting problems in your code, RuboCop can also
28
30
  automatically fix some of the problems for you.
@@ -51,7 +53,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
51
53
  might want to use a conservative version locking in your `Gemfile`:
52
54
 
53
55
  ```rb
54
- gem 'rubocop', '~> 0.57.2', require: false
56
+ gem 'rubocop', '~> 0.58.0', require: false
55
57
  ```
56
58
 
57
59
  ## Quickstart
@@ -65,13 +67,13 @@ $ rubocop
65
67
 
66
68
  ## Official manual
67
69
 
68
- You can read a ton more about RuboCop in its [official manual](http://rubocop.readthedocs.io).
70
+ You can read a ton more about RuboCop in its [official manual](http://docs.rubocop.org).
69
71
 
70
72
  ## Compatibility
71
73
 
72
74
  RuboCop supports the following Ruby implementations:
73
75
 
74
- * MRI 2.1+
76
+ * MRI 2.2+
75
77
  * JRuby 9.0+
76
78
 
77
79
  The Rails cops support the following versions:
@@ -82,24 +84,25 @@ The Rails cops support the following versions:
82
84
 
83
85
  Here's a list of RuboCop's core developers:
84
86
 
85
- * [Bozhidar Batsov](https://github.com/bbatsov)
87
+ * [Bozhidar Batsov](https://github.com/bbatsov) (author & head maintainer)
86
88
  * [Jonas Arvidsson](https://github.com/jonas054)
87
89
  * [Yuji Nakayama](https://github.com/yujinakayama)
88
90
  * [Evgeni Dzhelyov](https://github.com/edzhelyov) (retired)
89
91
  * [Ted Johansson](https://github.com/drenmi)
90
92
  * [Masataka Kuwabara](https://github.com/pocke)
93
+ * [Koichi Ito](https://github.com/koic)
91
94
 
92
95
  ## Logo
93
96
 
94
97
  RuboCop's logo was created by [Dimiter Petrov](https://www.chadomoto.com/). You can find the logo in various
95
- formats [here](https://github.com/bbatsov/rubocop/tree/master/logo).
98
+ formats [here](https://github.com/rubocop-hq/rubocop/tree/master/logo).
96
99
 
97
100
  The logo is licensed under a
98
101
  [Creative Commons Attribution-NonCommercial 4.0 International License](http://creativecommons.org/licenses/by-nc/4.0/deed.en_GB).
99
102
 
100
103
  ## Contributors
101
104
 
102
- Here's a [list](https://github.com/bbatsov/rubocop/graphs/contributors) of
105
+ Here's a [list](https://github.com/rubocop-hq/rubocop/graphs/contributors) of
103
106
  all the people who have contributed to the development of RuboCop.
104
107
 
105
108
  I'm extremely grateful to each and every one of them!
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ IFS=$'\n\t'
5
+ set -vx
6
+
7
+ bundle install
@@ -130,7 +130,7 @@ AllCops:
130
130
  # followed by the Gemfile.lock or gems.locked file. (Although the Ruby version
131
131
  # is specified in the Gemfile or gems.rb file, RuboCop reads the final value
132
132
  # from the lock file.) If the Ruby version is still unresolved, RuboCop will
133
- # use the oldest officially supported Ruby version (currently Ruby 2.1).
133
+ # use the oldest officially supported Ruby version (currently Ruby 2.2).
134
134
  TargetRubyVersion: ~
135
135
  # What version of Rails is the inspected code using? If a value is specified
136
136
  # for TargetRailsVersion then it is used. Acceptable values are specificed
@@ -739,6 +739,13 @@ Naming/HeredocDelimiterCase:
739
739
  - lowercase
740
740
  - uppercase
741
741
 
742
+ Naming/MemoizedInstanceVariableName:
743
+ EnforcedStyleForLeadingUnderscores: disallowed
744
+ SupportedStylesForLeadingUnderscores:
745
+ - disallowed
746
+ - required
747
+ - optional
748
+
742
749
  Naming/MethodName:
743
750
  EnforcedStyle: snake_case
744
751
  SupportedStyles:
@@ -1132,6 +1139,12 @@ Style/InverseMethods:
1132
1139
  :select: :reject
1133
1140
  :select!: :reject!
1134
1141
 
1142
+ Style/IpAddresses:
1143
+ # Allow strings to be whitelisted
1144
+ Whitelist:
1145
+ - "::"
1146
+ # :: is a valid IPv6 address, but could potentially be legitimately in code
1147
+
1135
1148
  Style/Lambda:
1136
1149
  EnforcedStyle: line_count_dependent
1137
1150
  SupportedStyles:
@@ -1539,7 +1552,10 @@ Metrics/AbcSize:
1539
1552
  Metrics/BlockLength:
1540
1553
  CountComments: false # count full line comments?
1541
1554
  Max: 25
1542
- ExcludedMethods: []
1555
+ ExcludedMethods:
1556
+ # By default, exclude the `#refine` method, as it tends to have larger
1557
+ # associated blocks.
1558
+ - refine
1543
1559
 
1544
1560
  Metrics/BlockNesting:
1545
1561
  CountBlocks: false
@@ -82,6 +82,10 @@ Style/InlineComment:
82
82
  Description: 'Avoid trailing inline comments.'
83
83
  Enabled: false
84
84
 
85
+ Style/IpAddresses:
86
+ Description: "Don't include literal IP addresses in code."
87
+ Enabled: false
88
+
85
89
  Style/MethodCallWithArgsParentheses:
86
90
  Description: 'Use parentheses for method calls with arguments.'
87
91
  StyleGuide: '#method-invocation-parens'
@@ -441,6 +441,7 @@ require_relative 'rubocop/cop/style/implicit_runtime_error'
441
441
  require_relative 'rubocop/cop/style/infinite_loop'
442
442
  require_relative 'rubocop/cop/style/inverse_methods'
443
443
  require_relative 'rubocop/cop/style/inline_comment'
444
+ require_relative 'rubocop/cop/style/ip_addresses'
444
445
  require_relative 'rubocop/cop/style/lambda'
445
446
  require_relative 'rubocop/cop/style/lambda_call'
446
447
  require_relative 'rubocop/cop/style/line_end_concatenation'
@@ -379,6 +379,11 @@ module RuboCop
379
379
  {equals_asgn? shorthand_asgn? asgn_method_call?}
380
380
  PATTERN
381
381
 
382
+ # Some cops treat the shovel operator as a kind of assignment.
383
+ def_node_matcher :assignment_or_similar?, <<-PATTERN
384
+ {assignment? (send _recv :<< ...)}
385
+ PATTERN
386
+
382
387
  def literal?
383
388
  LITERALS.include?(type)
384
389
  end
@@ -6,6 +6,8 @@ module RuboCop
6
6
  # in place of a plain node when the builder constructs the AST, making
7
7
  # its methods available to all `str` nodes within RuboCop.
8
8
  class StrNode < Node
9
+ include BasicLiteralNode
10
+
9
11
  def heredoc?
10
12
  loc.is_a?(Parser::Source::Map::Heredoc)
11
13
  end
@@ -39,7 +39,7 @@ module RuboCop
39
39
  act_on_options
40
40
  apply_default_formatter
41
41
  execute_runners(paths)
42
- rescue RuboCop::ConfigNotFoundError => e
42
+ rescue ConfigNotFoundError, IncorrectCopNameError, OptionArgumentError => e
43
43
  warn e.message
44
44
  STATUS_ERROR
45
45
  rescue RuboCop::Error => e
@@ -47,9 +47,6 @@ module RuboCop
47
47
  STATUS_ERROR
48
48
  rescue Finished
49
49
  STATUS_SUCCESS
50
- rescue IncorrectCopNameError => e
51
- warn e.message
52
- STATUS_ERROR
53
50
  rescue OptionParser::InvalidOption => e
54
51
  warn e.message
55
52
  warn 'For usage information, use --help'
@@ -128,9 +125,9 @@ module RuboCop
128
125
  def validate_options_vs_config
129
126
  if @options[:parallel] &&
130
127
  !@config_store.for(Dir.pwd).for_all_cops['UseCache']
131
- raise ArgumentError, '-P/--parallel uses caching to speed up ' \
132
- 'execution, so combining with AllCops: ' \
133
- 'UseCache: false is not allowed.'
128
+ raise OptionArgumentError, '-P/--parallel uses caching to speed up ' \
129
+ 'execution, so combining with AllCops: ' \
130
+ 'UseCache: false is not allowed.'
134
131
  end
135
132
  end
136
133
 
@@ -16,10 +16,10 @@ module RuboCop
16
16
 
17
17
  COMMON_PARAMS = %w[Exclude Include Severity
18
18
  AutoCorrect StyleGuide Details].freeze
19
- # 2.1 is the oldest officially supported Ruby version.
20
- DEFAULT_RUBY_VERSION = 2.1
21
- KNOWN_RUBIES = [2.1, 2.2, 2.3, 2.4, 2.5].freeze
22
- OBSOLETE_RUBIES = { 1.9 => '0.50', 2.0 => '0.50' }.freeze
19
+ # 2.2 is the oldest officially supported Ruby version.
20
+ DEFAULT_RUBY_VERSION = 2.2
21
+ KNOWN_RUBIES = [2.2, 2.3, 2.4, 2.5].freeze
22
+ OBSOLETE_RUBIES = { 1.9 => '0.50', 2.0 => '0.50', 2.1 => '0.58' }.freeze
23
23
  RUBY_VERSION_FILENAME = '.ruby-version'.freeze
24
24
  DEFAULT_RAILS_VERSION = 5.0
25
25
  OBSOLETE_COPS = {
@@ -176,15 +176,11 @@ module RuboCop
176
176
  end
177
177
 
178
178
  def yaml_safe_load(yaml_code, filename)
179
- if YAML.respond_to?(:safe_load) # Ruby 2.1+
180
- if defined?(SafeYAML) && SafeYAML.respond_to?(:load)
181
- SafeYAML.load(yaml_code, filename,
182
- whitelisted_tags: %w[!ruby/regexp])
183
- else
184
- YAML.safe_load(yaml_code, [Regexp, Symbol], [], false, filename)
185
- end
179
+ if defined?(SafeYAML) && SafeYAML.respond_to?(:load)
180
+ SafeYAML.load(yaml_code, filename,
181
+ whitelisted_tags: %w[!ruby/regexp])
186
182
  else
187
- YAML.load(yaml_code, filename) # rubocop:disable Security/YAMLLoad
183
+ YAML.safe_load(yaml_code, [Regexp, Symbol], [], false, filename)
188
184
  end
189
185
  end
190
186
  end
@@ -32,6 +32,8 @@ module RuboCop
32
32
  # corrector = Corrector.new(source_buffer, corrections)
33
33
  def initialize(source_buffer, corrections = [])
34
34
  @source_buffer = source_buffer
35
+ raise 'source_buffer should be a Parser::Source::Buffer' unless \
36
+ source_buffer.is_a? Parser::Source::Buffer
35
37
  @corrections = corrections
36
38
  @source_rewriter = Parser::Source::TreeRewriter.new(
37
39
  source_buffer,
@@ -72,6 +74,7 @@ module RuboCop
72
74
  #
73
75
  # @param [Parser::Source::Range] range
74
76
  def remove(range)
77
+ validate_range range
75
78
  @source_rewriter.remove(range)
76
79
  end
77
80
 
@@ -80,6 +83,7 @@ module RuboCop
80
83
  # @param [Parser::Source::Range] range
81
84
  # @param [String] content
82
85
  def insert_before(range, content)
86
+ validate_range range
83
87
  # TODO: Fix Cops using bad ranges instead
84
88
  if range.end_pos > @source_buffer.source.size
85
89
  range = range.with(end_pos: @source_buffer.source.size)
@@ -93,6 +97,7 @@ module RuboCop
93
97
  # @param [Parser::Source::Range] range
94
98
  # @param [String] content
95
99
  def insert_after(range, content)
100
+ validate_range range
96
101
  @source_rewriter.insert_after(range, content)
97
102
  end
98
103
 
@@ -101,6 +106,7 @@ module RuboCop
101
106
  # @param [Parser::Source::Range] range
102
107
  # @param [String] content
103
108
  def replace(range, content)
109
+ validate_range range
104
110
  @source_rewriter.replace(range, content)
105
111
  end
106
112
 
@@ -109,6 +115,7 @@ module RuboCop
109
115
  # @param [Parser::Source::Range] range
110
116
  # @param [Integer] size
111
117
  def remove_preceding(range, size)
118
+ validate_range range
112
119
  to_remove = Parser::Source::Range.new(range.source_buffer,
113
120
  range.begin_pos - size,
114
121
  range.begin_pos)
@@ -122,6 +129,7 @@ module RuboCop
122
129
  # @param [Parser::Source::Range] range
123
130
  # @param [Integer] size
124
131
  def remove_leading(range, size)
132
+ validate_range range
125
133
  to_remove = Parser::Source::Range.new(range.source_buffer,
126
134
  range.begin_pos,
127
135
  range.begin_pos + size)
@@ -135,11 +143,28 @@ module RuboCop
135
143
  # @param [Parser::Source::Range] range
136
144
  # @param [Integer] size
137
145
  def remove_trailing(range, size)
146
+ validate_range range
138
147
  to_remove = Parser::Source::Range.new(range.source_buffer,
139
148
  range.end_pos - size,
140
149
  range.end_pos)
141
150
  @source_rewriter.remove(to_remove)
142
151
  end
152
+
153
+ private
154
+
155
+ # :nodoc:
156
+ def validate_range(range)
157
+ return if range.source_buffer == @source_buffer
158
+ unless range.source_buffer.is_a?(Parser::Source::Buffer)
159
+ # actually this should be enforced by parser gem
160
+ raise 'Corrector expected range source buffer to be a '\
161
+ "Parser::Source::Buffer, but got #{range.source_buffer.class}"
162
+ end
163
+ raise "Correction target buffer #{range.source_buffer.object_id} "\
164
+ "name:#{range.source_buffer.name.inspect}"\
165
+ " is not current #{@source_buffer.object_id} "\
166
+ "name:#{@source_buffer.name.inspect} under investigation"
167
+ end
143
168
  end
144
169
  end
145
170
  end
@@ -55,13 +55,9 @@ module RuboCop
55
55
  'beginning of method definition.'.freeze
56
56
 
57
57
  def on_heredoc(node)
58
- return if heredoc_type(node) == SIMPLE_HEREDOC
59
-
60
- if empty_heredoc?(node) ||
61
- contents_indentation(node) >= closing_indentation(node)
62
- return if opening_indentation(node) == closing_indentation(node)
63
- return if argument_indentation_correct?(node)
64
- end
58
+ return if heredoc_type(node) == SIMPLE_HEREDOC ||
59
+ opening_indentation(node) == closing_indentation(node) ||
60
+ argument_indentation_correct?(node)
65
61
 
66
62
  add_offense(node, location: :heredoc_end)
67
63
  end
@@ -162,7 +162,7 @@ module RuboCop
162
162
  def alignment_node_for_variable_style(node)
163
163
  return node.parent if node.case_type? && node.argument?
164
164
 
165
- assignment = node.ancestors.find(&:assignment?)
165
+ assignment = node.ancestors.find(&:assignment_or_similar?)
166
166
  if assignment && !line_break_before_keyword?(assignment.source_range,
167
167
  node)
168
168
  assignment
@@ -103,7 +103,11 @@ module RuboCop
103
103
 
104
104
  def_end_config = config.for_cop('Layout/DefEndAlignment')
105
105
  style = def_end_config['EnforcedStyleAlignWith'] || 'start_of_line'
106
- base = style == 'def' ? node.first_argument : node
106
+ base = if style == 'def'
107
+ node.first_argument
108
+ else
109
+ leftmost_modifier_of(node) || node
110
+ end
107
111
 
108
112
  check_indentation(base.source_range, body)
109
113
  ignore_node(node.first_argument)
@@ -319,6 +323,10 @@ module RuboCop
319
323
  def configured_indentation_width
320
324
  cop_config['Width']
321
325
  end
326
+
327
+ def leftmost_modifier_of(node)
328
+ node.each_ancestor(:send).to_a.last
329
+ end
322
330
  end
323
331
  end
324
332
  end
@@ -39,7 +39,7 @@ module RuboCop
39
39
  end
40
40
 
41
41
  def autocorrect(node)
42
- range = Parser::Source::Range.new(processed_source.raw_source,
42
+ range = Parser::Source::Range.new(processed_source.buffer,
43
43
  0,
44
44
  node.begin_pos)
45
45
 
@@ -53,7 +53,7 @@ module RuboCop
53
53
  ALTERNATIVE_PROTECTED = '`protected` inside a `class << self` ' \
54
54
  'block'.freeze
55
55
 
56
- def_node_matcher :private_class_method, <<-PATTERN
56
+ def_node_search :private_class_methods, <<-PATTERN
57
57
  (send nil? :private_class_method $...)
58
58
  PATTERN
59
59
 
@@ -67,25 +67,26 @@ module RuboCop
67
67
 
68
68
  private
69
69
 
70
- def clear
71
- @useless = {}
72
- @last_access_modifier = nil
73
- end
74
-
75
70
  def check_node(node)
76
71
  return unless node && node.begin_type?
77
72
 
78
- clear
79
- check_scope(node)
73
+ ignored_methods = private_class_method_names(node)
80
74
 
81
- @useless.each do |_name, (defs_node, visibility, modifier)|
75
+ ineffective_modifier(node, ignored_methods) do |defs_node, modifier|
82
76
  add_offense(defs_node,
83
77
  location: :keyword,
84
- message: format_message(visibility, modifier))
78
+ message: format_message(modifier))
85
79
  end
86
80
  end
87
81
 
88
- def format_message(visibility, modifier)
82
+ def private_class_method_names(node)
83
+ private_class_methods(node).to_a.flatten
84
+ .select(&:basic_literal?)
85
+ .map(&:value)
86
+ end
87
+
88
+ def format_message(modifier)
89
+ visibility = modifier.method_name
89
90
  alternative = if visibility == :private
90
91
  ALTERNATIVE_PRIVATE
91
92
  else
@@ -96,52 +97,28 @@ module RuboCop
96
97
  alternative: alternative)
97
98
  end
98
99
 
99
- def check_scope(node, cur_vis = :public)
100
- node.each_child_node.reduce(cur_vis) do |visibility, child|
101
- check_child_scope(child, visibility)
102
- end
103
- end
104
-
105
- def check_child_scope(node, cur_vis)
106
- case node.type
107
- when :send
108
- cur_vis = check_send(node, cur_vis)
109
- when :defs
110
- check_defs(node, cur_vis)
111
- when :kwbegin
112
- check_scope(node, cur_vis)
100
+ def ineffective_modifier(node, ignored_methods, modifier = nil, &block)
101
+ node.each_child_node do |child|
102
+ case child.type
103
+ when :send
104
+ modifier = child if access_modifier?(child)
105
+ when :defs
106
+ next if correct_visibility?(child, modifier, ignored_methods)
107
+ yield child, modifier
108
+ when :kwbegin
109
+ ineffective_modifier(child, ignored_methods, modifier, &block)
110
+ end
113
111
  end
114
-
115
- cur_vis
116
112
  end
117
113
 
118
- def check_send(node, cur_vis)
119
- if node.bare_access_modifier? && !node.method?(:module_function)
120
- @last_access_modifier = node
121
- return node.method_name
122
- elsif (methods = private_class_method(node))
123
- # don't warn about defs nodes which are followed by a call to
124
- # `private_class_method :name`
125
- # obviously the programmer knows what they are doing
126
- revert_method_uselessness(methods)
127
- end
128
-
129
- cur_vis
114
+ def access_modifier?(node)
115
+ node.bare_access_modifier? && !node.method?(:module_function)
130
116
  end
131
117
 
132
- def check_defs(node, cur_vis)
133
- mark_method_as_useless(node, cur_vis) if cur_vis != :public
134
- end
118
+ def correct_visibility?(node, modifier, ignored_methods)
119
+ return true if modifier.nil? || modifier.method_name == :public
135
120
 
136
- def mark_method_as_useless(node, cur_vis)
137
- @useless[node.method_name] = [node, cur_vis, @last_access_modifier]
138
- end
139
-
140
- def revert_method_uselessness(methods)
141
- methods.each do |sym|
142
- next unless sym.sym_type?
143
- @useless.delete(sym.value)
144
- end
121
+ ignored_methods.include?(node.method_name)
145
122
  end
146
123
  end
147
124
  end