rubocop 1.71.2 → 1.72.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +28 -0
  4. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  5. data/lib/rubocop/comment_config.rb +1 -1
  6. data/lib/rubocop/config.rb +4 -0
  7. data/lib/rubocop/config_loader.rb +40 -8
  8. data/lib/rubocop/config_loader_resolver.rb +21 -7
  9. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  10. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -1
  11. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  12. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
  13. data/lib/rubocop/cop/internal_affairs.rb +1 -16
  14. data/lib/rubocop/cop/layout/block_alignment.rb +2 -0
  15. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  16. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  17. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
  18. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  19. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  20. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  21. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  22. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  23. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +221 -0
  24. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  25. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +74 -0
  26. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  27. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  28. data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
  29. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +18 -18
  30. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  31. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  32. data/lib/rubocop/cop/mixin/range_help.rb +3 -3
  33. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  34. data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
  35. data/lib/rubocop/cop/style/redundant_format.rb +222 -0
  36. data/lib/rubocop/cop/style/redundant_parentheses.rb +17 -3
  37. data/lib/rubocop/cop/util.rb +1 -1
  38. data/lib/rubocop/cop/utils/format_string.rb +7 -5
  39. data/lib/rubocop/directive_comment.rb +35 -2
  40. data/lib/rubocop/lsp/runtime.rb +2 -0
  41. data/lib/rubocop/lsp/server.rb +0 -2
  42. data/lib/rubocop/options.rb +26 -11
  43. data/lib/rubocop/path_util.rb +4 -0
  44. data/lib/rubocop/plugin/configuration_integrator.rb +141 -0
  45. data/lib/rubocop/plugin/load_error.rb +35 -0
  46. data/lib/rubocop/plugin/loader.rb +100 -0
  47. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  48. data/lib/rubocop/plugin.rb +39 -0
  49. data/lib/rubocop/rake_task.rb +4 -1
  50. data/lib/rubocop/server/cache.rb +35 -2
  51. data/lib/rubocop/server/cli.rb +2 -2
  52. data/lib/rubocop/version.rb +17 -2
  53. data/lib/rubocop.rb +5 -0
  54. data/lib/ruby_lsp/rubocop/addon.rb +7 -10
  55. data/lib/ruby_lsp/rubocop/{wraps_built_in_lsp_runtime.rb → runtime_adapter.rb} +5 -8
  56. metadata +35 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d7c6408a777042eced58bec2bc889312b24d8701f5db99da3b471088f589d6f
4
- data.tar.gz: 27423e682d55f04840a3bf3d5e0301556e4a1c419857e3422ced38ec423c0003
3
+ metadata.gz: 4660ddf63f92b10c83414d6a542725aacda2df1b9f47aec675b075fcdaa58817
4
+ data.tar.gz: b7c045964213e406e20675c06ed8df3a7e19bff18cf48b0db9891b8e1ae6cd8a
5
5
  SHA512:
6
- metadata.gz: 8729a8ea3adae11fcb2501bfea338821a8f9894209ea6fb482b62ebfae87019e07ded7bf02d3371c18726b28c2491c79952e7b86c193388a045f886a833b427c
7
- data.tar.gz: 44251afbbbc2aa7c121033ea05f25e1b3447afba7487d04a81f9463347ba28bcea05bdc2e434248f15cd235d9e452cb3f9f378f94adb5507eeb6d5ce58ba4119
6
+ metadata.gz: 0c4982b57b3c2cfbd48d2768eefeb839b6b91a5c9c90a55f4dfc1f1c37b655d73b64d99bbebc642d928ecfb9740c6992ed340ea38f2f1638626aa3d2e2c7a190
7
+ data.tar.gz: f4d6cfcfb42615a5a4065c961aac1dd55eb7e6bd28812d0a31aef135be94b9248eab2b53f1a452847b49c206aab7b3eb19b45581203af63d10be9e7cb71e67da
data/README.md CHANGED
@@ -52,7 +52,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
52
52
  in your `Gemfile`:
53
53
 
54
54
  ```rb
55
- gem 'rubocop', '~> 1.71', require: false
55
+ gem 'rubocop', '~> 1.72', require: false
56
56
  ```
57
57
 
58
58
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -1685,6 +1685,11 @@ Lint/ConstantResolution:
1685
1685
  # Restrict this cop from only looking at certain names
1686
1686
  Ignore: []
1687
1687
 
1688
+ Lint/CopDirectiveSyntax:
1689
+ Description: 'Checks that `# rubocop:` directives are strictly formatted.'
1690
+ Enabled: pending
1691
+ VersionAdded: '1.72'
1692
+
1688
1693
  Lint/Debugger:
1689
1694
  Description: 'Check for debugger calls.'
1690
1695
  Enabled: true
@@ -2285,6 +2290,11 @@ Lint/RedundantStringCoercion:
2285
2290
  VersionAdded: '0.19'
2286
2291
  VersionChanged: '0.77'
2287
2292
 
2293
+ Lint/RedundantTypeConversion:
2294
+ Description: 'Checks for redundantly converting a literal to the same type.'
2295
+ Enabled: pending
2296
+ VersionAdded: '1.72'
2297
+
2288
2298
  Lint/RedundantWithIndex:
2289
2299
  Description: 'Checks for redundant `with_index`.'
2290
2300
  Enabled: true
@@ -2433,6 +2443,12 @@ Lint/SuppressedException:
2433
2443
  VersionAdded: '0.9'
2434
2444
  VersionChanged: '1.12'
2435
2445
 
2446
+ Lint/SuppressedExceptionInNumberConversion:
2447
+ Description: 'Checks for cases where exceptions unrelated to the numeric constructors may be unintentionally swallowed.'
2448
+ Enabled: pending
2449
+ SafeAutoCorrect: false
2450
+ VersionAdded: '1.72'
2451
+
2436
2452
  Lint/SymbolConversion:
2437
2453
  Description: 'Checks for unnecessary symbol conversions.'
2438
2454
  Enabled: pending
@@ -2588,6 +2604,11 @@ Lint/UselessAssignment:
2588
2604
  VersionAdded: '0.11'
2589
2605
  VersionChanged: '1.66'
2590
2606
 
2607
+ Lint/UselessConstantScoping:
2608
+ Description: 'Checks for useless constant scoping.'
2609
+ Enabled: pending
2610
+ VersionAdded: '1.72'
2611
+
2591
2612
  Lint/UselessDefined:
2592
2613
  Description: 'Checks for calls to `defined?` with strings and symbols. The result of such a call will always be truthy.'
2593
2614
  Enabled: pending
@@ -3041,6 +3062,8 @@ Naming/PredicateName:
3041
3062
  MethodDefinitionMacros:
3042
3063
  - define_method
3043
3064
  - define_singleton_method
3065
+ # Use Sorbet's T::Boolean return type to detect predicate methods.
3066
+ UseSorbetSigs: false
3044
3067
  # Exclude Rspec specs because there is a strong convention to write spec
3045
3068
  # helpers in the form of `have_something` or `be_something`.
3046
3069
  Exclude:
@@ -5145,6 +5168,11 @@ Style/RedundantFilterChain:
5145
5168
  VersionAdded: '1.52'
5146
5169
  VersionChanged: '1.57'
5147
5170
 
5171
+ Style/RedundantFormat:
5172
+ Description: 'Checks for usages of `Kernel#format` or `Kernel#sprintf` with only a single argument.'
5173
+ Enabled: pending
5174
+ VersionAdded: '1.72'
5175
+
5148
5176
  Style/RedundantFreeze:
5149
5177
  Description: "Checks usages of Object#freeze on immutable objects."
5150
5178
  Enabled: true
@@ -97,7 +97,13 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def loaded_extensions
100
- @config_store.for_pwd.loaded_features.to_a
100
+ rubocop_config = @config_store.for_pwd
101
+
102
+ plugin_names = rubocop_config.loaded_plugins.map do |plugin|
103
+ plugin.about.name
104
+ end
105
+
106
+ plugin_names + rubocop_config.loaded_features.to_a
101
107
  end
102
108
 
103
109
  def installed_and_not_loaded_extensions
@@ -205,7 +205,7 @@ module RuboCop
205
205
  directive.cop_names.each do |name|
206
206
  if directive.disabled?
207
207
  names[name] += 1
208
- elsif (names[name]).positive?
208
+ elsif names[name].positive?
209
209
  names[name] -= 1
210
210
  else
211
211
  extras[directive.comment] << name
@@ -45,6 +45,10 @@ module RuboCop
45
45
  end
46
46
  # rubocop:enable Metrics/AbcSize
47
47
 
48
+ def loaded_plugins
49
+ @loaded_plugins ||= ConfigLoader.loaded_plugins
50
+ end
51
+
48
52
  def loaded_features
49
53
  @loaded_features ||= ConfigLoader.loaded_features
50
54
  end
@@ -33,13 +33,14 @@ module RuboCop
33
33
  attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
34
34
  :ignore_unrecognized_cops
35
35
  attr_writer :default_configuration
36
- attr_reader :loaded_features
36
+ attr_reader :loaded_plugins, :loaded_features
37
37
 
38
38
  alias debug? debug
39
39
  alias ignore_parent_exclusion? ignore_parent_exclusion
40
40
 
41
41
  def clear_options
42
42
  @debug = nil
43
+ @loaded_plugins = Set.new
43
44
  @loaded_features = Set.new
44
45
  @disable_pending_cops = nil
45
46
  @enable_pending_cops = nil
@@ -48,11 +49,17 @@ module RuboCop
48
49
  FileFinder.root_level = nil
49
50
  end
50
51
 
52
+ # rubocop:disable Metrics/AbcSize
51
53
  def load_file(file, check: true)
52
54
  path = file_path(file)
53
55
 
54
56
  hash = load_yaml_configuration(path)
55
57
 
58
+ rubocop_config = Config.create(hash, path, check: false)
59
+ plugins = hash.delete('plugins')
60
+ loaded_plugins = resolver.resolve_plugins(rubocop_config, plugins)
61
+ add_loaded_plugins(loaded_plugins)
62
+
56
63
  loaded_features = resolver.resolve_requires(path, hash)
57
64
  add_loaded_features(loaded_features)
58
65
 
@@ -67,6 +74,7 @@ module RuboCop
67
74
 
68
75
  Config.create(hash, path, check: check)
69
76
  end
77
+ # rubocop:enable Metrics/AbcSize
70
78
 
71
79
  def load_yaml_configuration(absolute_path)
72
80
  file_contents = read_file(absolute_path)
@@ -155,14 +163,31 @@ module RuboCop
155
163
  end
156
164
  end
157
165
 
158
- # @api private
159
- def inject_defaults!(project_root)
160
- path = File.join(project_root, 'config', 'default.yml')
161
- config = load_file(path)
162
- new_config = ConfigLoader.merge_with_default(config, path)
163
- puts "configuration from #{path}" if debug?
164
- @default_configuration = new_config
166
+ # rubocop:disable Metrics/MethodLength
167
+ def inject_defaults!(config_yml_path)
168
+ if Pathname(config_yml_path).directory?
169
+ # TODO: Since the warning noise is expected to be high until some time after the release,
170
+ # warnings will only be issued when `RUBYOPT=-w` is specified.
171
+ # To proceed step by step, the next step is to remove `$VERBOSE` and always issue warning.
172
+ # Eventually, `project_root` will no longer be accepted.
173
+ if $VERBOSE
174
+ warn Rainbow(<<~MESSAGE).yellow, uplevel: 1
175
+ Use config YAML file path instead of project root directory.
176
+ e.g., `path/to/config/default.yml`
177
+ MESSAGE
178
+ end
179
+ # NOTE: For compatibility.
180
+ project_root = config_yml_path
181
+ path = File.join(project_root, 'config', 'default.yml')
182
+ config = load_file(path)
183
+ else
184
+ hash = ConfigLoader.load_yaml_configuration(config_yml_path.to_s)
185
+ config = Config.new(hash, config_yml_path).tap(&:make_excludes_absolute)
186
+ end
187
+
188
+ @default_configuration = ConfigLoader.merge_with_default(config, path)
165
189
  end
190
+ # rubocop:enable Metrics/MethodLength
166
191
 
167
192
  # Returns the path RuboCop inferred as the root of the project. No file
168
193
  # searches will go past this directory.
@@ -196,6 +221,13 @@ module RuboCop
196
221
  resolver.merge_with_default(config, config_file, unset_nil: unset_nil)
197
222
  end
198
223
 
224
+ # @api private
225
+ # Used to add plugins that were required inside a config or from
226
+ # the CLI using `--plugin`.
227
+ def add_loaded_plugins(loaded_plugins)
228
+ @loaded_plugins.merge(Array(loaded_plugins))
229
+ end
230
+
199
231
  # @api private
200
232
  # Used to add features that were required inside a config or from
201
233
  # the CLI using `--require`.
@@ -2,16 +2,34 @@
2
2
 
3
3
  require 'pathname'
4
4
  require 'yaml'
5
+ require_relative 'plugin'
5
6
 
6
7
  module RuboCop
7
8
  # A help class for ConfigLoader that handles configuration resolution.
8
9
  # @api private
9
10
  class ConfigLoaderResolver # rubocop:disable Metrics/ClassLength
11
+ def resolve_plugins(rubocop_config, plugins)
12
+ return if (plugins = Array(plugins)).empty?
13
+
14
+ Plugin.integrate_plugins(rubocop_config, plugins)
15
+ end
16
+
10
17
  def resolve_requires(path, hash)
11
18
  config_dir = File.dirname(path)
12
19
  hash.delete('require').tap do |loaded_features|
13
20
  Array(loaded_features).each do |feature|
14
- FeatureLoader.load(config_directory_path: config_dir, feature: feature)
21
+ if Plugin.plugin_capable?(feature)
22
+ # NOTE: Compatibility for before plugins style.
23
+ warn Rainbow(<<~MESSAGE).yellow
24
+ #{feature} extension supports plugin, specify `plugins: #{feature}` instead of `require: #{feature}` in #{path}.
25
+ For more information, see https://docs.rubocop.org/rubocop/plugin_migration_guide.html.
26
+ MESSAGE
27
+ rubocop_config = Config.create(hash, path, check: false)
28
+
29
+ resolve_plugins(rubocop_config, feature)
30
+ else
31
+ FeatureLoader.load(config_directory_path: config_dir, feature: feature)
32
+ end
15
33
  end
16
34
  end
17
35
  end
@@ -157,7 +175,7 @@ module RuboCop
157
175
  return false if inherited_file.nil? # Not inheritance resolving merge
158
176
  return false if inherited_file.start_with?('..') # Legitimate override
159
177
  return false if base_hash[key] == derived_hash[key] # Same value
160
- return false if remote_file?(inherited_file) # Can't change
178
+ return false if PathUtil.remote_file?(inherited_file) # Can't change
161
179
 
162
180
  Gem.path.none? { |dir| inherited_file.start_with?(dir) } # Can change?
163
181
  end
@@ -225,7 +243,7 @@ module RuboCop
225
243
  end
226
244
 
227
245
  def inherited_file(path, inherit_from, file)
228
- if remote_file?(inherit_from)
246
+ if PathUtil.remote_file?(inherit_from)
229
247
  # A remote configuration, e.g. `inherit_from: http://example.com/rubocop.yml`.
230
248
  RemoteConfig.new(inherit_from, File.dirname(path))
231
249
  elsif Pathname.new(inherit_from).absolute?
@@ -245,10 +263,6 @@ module RuboCop
245
263
  end
246
264
  end
247
265
 
248
- def remote_file?(uri)
249
- uri.start_with?('http://', 'https://')
250
- end
251
-
252
266
  def remote_config?(file)
253
267
  file.is_a?(RemoteConfig)
254
268
  end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # When a node location may not exist, `Node#loc?` or `Node#loc_is?`
7
+ # can be used instead of calling `Node#respond_to?` before using
8
+ # the value.
9
+ #
10
+ # @example
11
+ # # bad
12
+ # node.loc.respond_to?(:begin) && node.loc.begin
13
+ #
14
+ # # good
15
+ # node.loc?(:begin)
16
+ #
17
+ # # bad
18
+ # node.loc.respond_to?(:begin) && node.loc.begin.is?('(')
19
+ #
20
+ # # good
21
+ # node.loc_is?(:begin, '(')
22
+ #
23
+ # # bad
24
+ # node.loc.respond_to?(:begin) && node.loc.begin.source == '('
25
+ #
26
+ # # good
27
+ # node.loc_is?(:begin, '(')
28
+ #
29
+ class LocationExists < Base
30
+ extend AutoCorrector
31
+
32
+ MSG = 'Use `%<replacement>s` instead of `%<source>s`.'
33
+
34
+ # @!method replaceable_with_loc_is(node)
35
+ def_node_matcher :replaceable_with_loc_is, <<~PATTERN
36
+ (and
37
+ (call
38
+ (call $_receiver :loc) :respond_to?
39
+ $(sym _location))
40
+ {
41
+ (call
42
+ (call
43
+ (call _receiver :loc) _location) :is?
44
+ $(str _))
45
+ (call
46
+ (call
47
+ (call
48
+ (call _receiver :loc) _location) :source) :==
49
+ $(str _))
50
+ })
51
+ PATTERN
52
+
53
+ # @!method replaceable_with_loc(node)
54
+ def_node_matcher :replaceable_with_loc, <<~PATTERN
55
+ (and
56
+ (call
57
+ (call $_receiver :loc) :respond_to?
58
+ $(sym _location))
59
+ (call
60
+ (call _receiver :loc) _location))
61
+ PATTERN
62
+
63
+ def on_and(node)
64
+ replace_with_loc(node) || replace_with_loc_is(node)
65
+ end
66
+
67
+ private
68
+
69
+ def replace_with_loc(node)
70
+ replaceable_with_loc(node) do |receiver, location|
71
+ if node.parent&.assignment?
72
+ register_offense(node, replace_assignment(receiver, location))
73
+ else
74
+ register_offense(node, replacement(receiver, "loc?(#{location.source})"))
75
+ end
76
+ end
77
+ end
78
+
79
+ def replace_with_loc_is(node)
80
+ replaceable_with_loc_is(node) do |receiver, location, value|
81
+ replacement = replacement(receiver, "loc_is?(#{location.source}, #{value.source})")
82
+ register_offense(node, replacement)
83
+ end
84
+ end
85
+
86
+ def register_offense(node, replacement)
87
+ message = format(MSG, replacement: replacement, source: node.source)
88
+
89
+ add_offense(node, message: message) do |corrector|
90
+ corrector.replace(node, replacement)
91
+ end
92
+ end
93
+
94
+ def replacement(receiver, rest)
95
+ "#{replace_receiver(receiver)}#{rest}"
96
+ end
97
+
98
+ def replace_assignment(receiver, location)
99
+ prefix = replace_receiver(receiver)
100
+
101
+ "#{prefix}loc#{dot(receiver)}#{location.value} if #{prefix}loc?(#{location.source})"
102
+ end
103
+
104
+ def replace_receiver(receiver)
105
+ return '' unless receiver
106
+
107
+ "#{receiver.source}#{dot(receiver)}"
108
+ end
109
+
110
+ def dot(node)
111
+ node.parent.loc.dot.source
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module InternalAffairs
6
- # rubocop:disable InternalAffairs/RedundantSourceRange - node here is a `NodePattern::Node`
6
+ # rubocop:disable InternalAffairs/RedundantSourceRange -- node here is a `NodePattern::Node`
7
7
  class NodePatternGroups
8
8
  # Walks an AST that has been processed by `InternalAffairs::NodePatternGroups::Processor`
9
9
  # in order to find `node_type` and `node_sequence` nodes that can be replaced with a node
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lint_roller'
4
+
5
+ module RuboCop
6
+ module InternalAffairs
7
+ # A Plugin for `InternalAffairs` department, which has internal cops.
8
+ class Plugin < LintRoller::Plugin
9
+ def about
10
+ LintRoller::About.new(
11
+ name: 'rubocop-internal_affairs',
12
+ version: Version::STRING,
13
+ homepage: 'https://github.com/rubocop/rubocop/tree/master/lib/rubocop/cop/internal_affairs',
14
+ description: 'A collection of RuboCop cops to check for internal affairs.'
15
+ )
16
+ end
17
+
18
+ def supported?(context)
19
+ context.engine == :rubocop
20
+ end
21
+
22
+ def rules(_context)
23
+ require_relative '../internal_affairs'
24
+
25
+ LintRoller::Rules.new(
26
+ type: :path,
27
+ config_format: :rubocop,
28
+ value: Pathname.new(__dir__).join('../../../../config/internal_affairs.yml')
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end
@@ -17,7 +17,13 @@ module RuboCop
17
17
  'in `config/default.yml`.'
18
18
  CONFIG_PATH = find_file_upwards('config/default.yml', Dir.pwd)
19
19
  CONFIG = if CONFIG_PATH
20
- ConfigLoader.load_yaml_configuration(CONFIG_PATH)
20
+ begin
21
+ original_debug = ConfigLoader.debug
22
+ ConfigLoader.debug = false
23
+ ConfigLoader.load_yaml_configuration(CONFIG_PATH)
24
+ ensure
25
+ ConfigLoader.debug = original_debug
26
+ end
21
27
  else
22
28
  {}
23
29
  end
@@ -8,6 +8,7 @@ require_relative 'internal_affairs/example_description'
8
8
  require_relative 'internal_affairs/example_heredoc_delimiter'
9
9
  require_relative 'internal_affairs/inherit_deprecated_cop_class'
10
10
  require_relative 'internal_affairs/lambda_or_proc'
11
+ require_relative 'internal_affairs/location_exists'
11
12
  require_relative 'internal_affairs/location_expression'
12
13
  require_relative 'internal_affairs/location_line_equality_comparison'
13
14
  require_relative 'internal_affairs/method_name_end_with'
@@ -36,19 +37,3 @@ require_relative 'internal_affairs/style_detected_api_use'
36
37
  require_relative 'internal_affairs/undefined_config'
37
38
  require_relative 'internal_affairs/useless_message_assertion'
38
39
  require_relative 'internal_affairs/useless_restrict_on_send'
39
-
40
- module RuboCop
41
- # Patch in the InternalAffairs specific config values
42
- module InternalAffairs
43
- def self.inject!
44
- path = File.join(ConfigLoader::RUBOCOP_HOME, 'config', 'internal_affairs.yml')
45
- hash = ConfigLoader.load_yaml_configuration(path)
46
- config = Config.new(hash, path)
47
- puts "configuration from #{path}" if ConfigLoader.debug?
48
- config = ConfigLoader.merge_with_default(config, path)
49
- ConfigLoader.instance_variable_set(:@default_configuration, config)
50
- end
51
- end
52
- end
53
-
54
- RuboCop::InternalAffairs.inject!
@@ -73,6 +73,8 @@ module RuboCop
73
73
  # @!method block_end_align_target?(node, child)
74
74
  def_node_matcher :block_end_align_target?, <<~PATTERN
75
75
  {assignment?
76
+ def
77
+ defs
76
78
  splat
77
79
  and
78
80
  or
@@ -49,7 +49,7 @@ module RuboCop
49
49
  end
50
50
 
51
51
  def on_rescue(node)
52
- return unless node.loc.respond_to?(:else) && node.loc.else
52
+ return unless node.loc?(:else)
53
53
 
54
54
  check_alignment(base_range_of_rescue(node), node.loc.else)
55
55
  end
@@ -189,7 +189,7 @@ module RuboCop
189
189
  end
190
190
 
191
191
  def offense_location(node)
192
- if node.loc.respond_to?(:end) && node.loc.end
192
+ if node.loc?(:end)
193
193
  node.loc.end
194
194
  else
195
195
  node
@@ -27,9 +27,14 @@ module RuboCop
27
27
  KIND = 'method'
28
28
 
29
29
  def on_def(node)
30
- first_line = node.arguments.source_range&.last_line
30
+ if node.endless?
31
+ return unless offending_endless_method?(node)
31
32
 
32
- check(node, node.body, adjusted_first_line: first_line)
33
+ register_offense_for_endless_method(node)
34
+ else
35
+ first_line = node.arguments.source_range&.last_line
36
+ check(node, node.body, adjusted_first_line: first_line)
37
+ end
33
38
  end
34
39
  alias on_defs on_def
35
40
 
@@ -38,6 +43,21 @@ module RuboCop
38
43
  def style
39
44
  :no_empty_lines
40
45
  end
46
+
47
+ def offending_endless_method?(node)
48
+ node.body.first_line > node.loc.assignment.line + 1 &&
49
+ processed_source.lines[node.loc.assignment.line].empty?
50
+ end
51
+
52
+ def register_offense_for_endless_method(node)
53
+ range = processed_source.buffer.line_range(node.loc.assignment.line + 1).resize(1)
54
+
55
+ msg = message(MSG_EXTRA, 'beginning')
56
+
57
+ add_offense(range, message: msg) do |corrector|
58
+ corrector.remove(range)
59
+ end
60
+ end
41
61
  end
42
62
  end
43
63
  end
@@ -162,7 +162,7 @@ module RuboCop
162
162
 
163
163
  def end_keyword_before_closing_parenthesis?(parenthesized_send_node)
164
164
  parenthesized_send_node.ancestors.any? do |ancestor|
165
- ancestor.loc.respond_to?(:end) && ancestor.loc.end&.source == 'end'
165
+ ancestor.loc_is?(:end, 'end')
166
166
  end
167
167
  end
168
168
 
@@ -216,7 +216,7 @@ module RuboCop
216
216
 
217
217
  def get_dot_right_above(node)
218
218
  node.each_ancestor.find do |a|
219
- dot = a.loc.respond_to?(:dot) && a.loc.dot
219
+ dot = a.loc.dot if a.loc?(:dot)
220
220
  next unless dot
221
221
 
222
222
  dot.line == node.loc.dot.line - 1 && dot.column == node.loc.dot.column
@@ -239,7 +239,7 @@ module RuboCop
239
239
  node = node.receiver while node.receiver
240
240
  # ascend to first call which has a dot
241
241
  node = node.parent
242
- node = node.parent until node.loc.respond_to?(:dot) && node.loc.dot
242
+ node = node.parent until node.loc?(:dot)
243
243
 
244
244
  node
245
245
  end
@@ -51,7 +51,7 @@ module RuboCop
51
51
  alias on_csend on_send
52
52
 
53
53
  def on_const(node)
54
- return unless node.loc.respond_to?(:double_colon) && node.loc.double_colon
54
+ return unless node.loc?(:double_colon)
55
55
 
56
56
  check_space_after_double_colon(node)
57
57
  end