rubocop-legion 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d9316d83d8676fe5adb80fd7500f3daece09203ece25f0ce0c81887d19982ca
4
- data.tar.gz: 646cab78aebc73b233882dcfc594d6c0efbea0acb3e2881e02a1f888ec5513e4
3
+ metadata.gz: ab19d4bce0d274768b632aa0579aa8997cb503befa24d4d613442f4cc894cb09
4
+ data.tar.gz: 85caebdfc215b98b74febd7b59c09c90fc6574e36f9dd2c126c866ca43138cde
5
5
  SHA512:
6
- metadata.gz: 83f63897f48898014d992e98b11cdfd9f2b830e405b2fd49bff484acffdaaeafd853dea8016baaa280787302a0c15a701e2f1d0c71274d1bf0fa04761574e8bd
7
- data.tar.gz: 69aa65b8634cef75041fe37a57b87ca54bdc911a59fc12710193a66550b71c01926831618ef9100b775c5fc498d0705d8eaab50af11c5c1446d36ab801be51ae
6
+ metadata.gz: 93425642d48e67c4897e9466b34394aa88b43048435c0841d0c6b1c05a6eee4ce022fd3211757ed6a3de084b5f154dea614a764e763b92a845be779cc717a0b9
7
+ data.tar.gz: e45f70a81e9e658b90e984a5561e027d88044450831c0a714d31f96a231e3933662128d167b60666624d3631077672898f8e5a50627c77e267423b00f9fb32f2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.11] - 2026-08-04
4
+
5
+ ### Added
6
+ - New cop `Legion/Framework/NoUnusedArgDisable` (universal): bans `# rubocop:disable`/`:todo`/`:enable Lint/UnusedMethodArgument`. An unused kwarg is a real offense, not something to hide — autocorrect removes the directive so it resurfaces and must be fixed properly (drop the arg, or `**` → `**opts` and read `opts[:key]`). Single-cop directives autocorrect; multi-cop directives are flagged without autocorrect. `# rubocop:disable all` is out of scope.
7
+
8
+ ### Fixed
9
+ - `Legion/Framework/NoUnderscorePrefixedKwargs` now autocorrects an unused splat (`**_opts`, `**_rest`, `**_`) to `**` (nameless accept-and-ignore) instead of `**opts`. The underscore signals the splat is unused; rewriting to a named `**opts` produced a named-but-unused splat that falsely claims the body reads `opts`. `**opts` is correct only when the body actually reads it.
10
+
3
11
  ## [0.1.10] - 2026-07-31
4
12
 
5
13
  ### Fixed
data/config/default.yml CHANGED
@@ -340,11 +340,17 @@ Legion/Extension/DefinitionCallMismatched:
340
340
  # Legion/Framework — N×N routing guard cops (Phase 6 enforcement)
341
341
 
342
342
  Legion/Framework/NoUnderscorePrefixedKwargs:
343
- Description: 'Ban underscore-prefixed kwargs and `**_rest` splats. Use plain kwarg, defaulted kwarg, or `**opts`.'
343
+ Description: 'Ban underscore-prefixed kwargs and `**_rest` splats. Use plain kwarg, defaulted kwarg, `**opts`, or `**`.'
344
344
  Enabled: true
345
345
  Severity: warning
346
346
  VersionAdded: '0.1.8'
347
347
 
348
+ Legion/Framework/NoUnusedArgDisable:
349
+ Description: 'Ban `# rubocop:disable Lint/UnusedMethodArgument`. Drop the arg or use `**opts`.'
350
+ Enabled: true
351
+ Severity: warning
352
+ VersionAdded: '0.1.11'
353
+
348
354
  Legion/Framework/NoInlineSettingDefaults:
349
355
  Description: 'Flag `Legion::Settings[...] || <literal>` and shadow-default patterns. Defaults belong in `settings.rb`.'
350
356
  Enabled: true
@@ -18,15 +18,16 @@ module RuboCop
18
18
  # # good
19
19
  # def foo(bar:); end
20
20
  # def foo(bar: nil); end
21
- # def foo(**opts); end
21
+ # def foo(**); end # unused passthrough
22
+ # def foo(**opts); end # only when the body reads `opts`
22
23
  class NoUnderscorePrefixedKwargs < Base
23
24
  extend AutoCorrector
24
25
 
25
26
  MSG_KWARG = 'Underscore-prefixed kwarg `%<name>s` is not allowed. ' \
26
27
  'Use plain kwarg (required), defaulted kwarg (optional), ' \
27
28
  'or `**opts` for passthrough.'
28
- MSG_SPLAT = 'Underscore-prefixed kwarg splat `%<name>s` is not allowed. ' \
29
- 'Use `**opts` for passthrough.'
29
+ MSG_SPLAT = 'Underscore-prefixed splat `%<name>s` means unused use `**` to ' \
30
+ 'accept-and-ignore, or `**opts` only if the body reads `opts`.'
30
31
 
31
32
  def on_def(node)
32
33
  check_params(node)
@@ -70,7 +71,7 @@ module RuboCop
70
71
  return unless name.to_s.start_with?('_')
71
72
 
72
73
  add_offense(arg, message: format(MSG_SPLAT, name: name)) do |corrector|
73
- corrector.replace(arg.source_range, '**opts')
74
+ corrector.replace(arg.source_range, '**')
74
75
  end
75
76
  end
76
77
 
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Legion
6
+ module Framework
7
+ # Bans disabling `Lint/UnusedMethodArgument` with an inline directive.
8
+ # An unused kwarg is a real offense, not something to hide — a `**` /
9
+ # `**opts` splat already swallows extras, so the arg should be dropped;
10
+ # if it is genuinely optional, change `**` to `**opts` and read
11
+ # `opts[:key]`. RuboCop's own `RedundantCopDisableDirective` never flags
12
+ # this because the offense is genuine, so the directive stays invisible.
13
+ #
14
+ # Autocorrect removes the directive so the real `Lint/UnusedMethodArgument`
15
+ # offense resurfaces and must be fixed properly. It never edits the method
16
+ # signature — dropping a load-bearing public kwarg is a human decision.
17
+ #
18
+ # A blanket "disable all" directive is intentionally out of scope; only
19
+ # directives that name `Lint/UnusedMethodArgument` explicitly are flagged.
20
+ #
21
+ # @example
22
+ # # bad — a disable directive naming Lint/UnusedMethodArgument on the def
23
+ # def foo(bar:, unused:)
24
+ # end
25
+ #
26
+ # # good — drop the unused arg (a splat already swallows it)
27
+ # def foo(bar:, **)
28
+ # end
29
+ #
30
+ # # good — keep it and actually read it
31
+ # def foo(bar:, **opts)
32
+ # opts[:unused]
33
+ # end
34
+ class NoUnusedArgDisable < Base
35
+ include RangeHelp
36
+ extend AutoCorrector
37
+
38
+ MSG = 'Do not disable `Lint/UnusedMethodArgument`. Drop the unused arg ' \
39
+ '(a `**`/`**opts` splat already swallows it) or change `**` to ' \
40
+ '`**opts` and read `opts[:key]`.'
41
+
42
+ TARGET = 'Lint/UnusedMethodArgument'
43
+
44
+ # Matches a disable / todo / enable directive and captures the cop list.
45
+ DIRECTIVE = /#\s*rubocop:(?:disable|todo|enable)\s+(?<cops>[^#]+)/
46
+
47
+ def on_new_investigation
48
+ processed_source.comments.each do |comment|
49
+ match = DIRECTIVE.match(comment.text)
50
+ next unless match
51
+
52
+ cops = match[:cops].split(',').map(&:strip)
53
+ next unless cops.include?(TARGET)
54
+
55
+ register(comment, cops)
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def register(comment, cops)
62
+ add_offense(comment) do |corrector|
63
+ # Only autocorrect the unambiguous single-cop case; leave multi-cop
64
+ # directives to a human so we never strip an unrelated disable.
65
+ corrector.remove(removal_range(comment)) if cops == [TARGET]
66
+ end
67
+ end
68
+
69
+ # Trailing directive (`code # rubocop:disable ...`) → strip the comment
70
+ # and the whitespace before it. Standalone directive line → strip the
71
+ # whole line including its newline.
72
+ def removal_range(comment)
73
+ range = comment.source_range
74
+ line_range = range.source_line
75
+ leading = line_range[0...range.column]
76
+
77
+ if leading.strip.empty?
78
+ range_by_whole_lines(range, include_final_newline: true)
79
+ else
80
+ range.with(begin_pos: range.begin_pos - trailing_ws(leading))
81
+ end
82
+ end
83
+
84
+ def trailing_ws(leading)
85
+ leading.length - leading.rstrip.length
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Legion
5
- VERSION = '0.1.10'
5
+ VERSION = '0.1.11'
6
6
  end
7
7
  end
@@ -45,6 +45,7 @@ require 'rubocop/cop/legion/framework/cache_time_coercion'
45
45
  require 'rubocop/cop/legion/framework/api_string_keys'
46
46
  require 'rubocop/cop/legion/framework/mutex_nested_sync'
47
47
  require 'rubocop/cop/legion/framework/no_underscore_prefixed_kwargs'
48
+ require 'rubocop/cop/legion/framework/no_unused_arg_disable'
48
49
  require 'rubocop/cop/legion/framework/no_inline_setting_defaults'
49
50
  require 'rubocop/cop/legion/framework/no_direct_dispatch'
50
51
  require 'rubocop/cop/legion/framework/no_shape_duck_typing'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-legion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -148,6 +148,7 @@ files:
148
148
  - lib/rubocop/cop/legion/framework/no_inline_setting_defaults.rb
149
149
  - lib/rubocop/cop/legion/framework/no_shape_duck_typing.rb
150
150
  - lib/rubocop/cop/legion/framework/no_underscore_prefixed_kwargs.rb
151
+ - lib/rubocop/cop/legion/framework/no_unused_arg_disable.rb
151
152
  - lib/rubocop/cop/legion/framework/sinatra_host_auth.rb
152
153
  - lib/rubocop/cop/legion/framework/thor_reserved_run.rb
153
154
  - lib/rubocop/cop/legion/helper_migration/defined_transport_guard.rb