shirobai-performance 2026.0709.0000

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 14db2ef6c53a828bdc439c90f4f00aaebd12e17671279a96a4d110d5cb2cd2f9
4
+ data.tar.gz: 18532cf76d85c01323f89e96d1c4695b96dafb1ff6032b0e323ebd93f808eba0
5
+ SHA512:
6
+ metadata.gz: c38254b43bf6d2621906b5ccfc41b5b8e3ca22b13f66a07fbd9547b7dd963f82d9c321ae566b263f7a3a100c89102a70c7a000a9af8cb42fa9fa6140e77c792e
7
+ data.tar.gz: 83a6116f358a960b54790ece4de3cefa820e2f9b1ee4bc841b315d56eb33ff6a3276adcca524abac2b2d18ed49cae09509d6290684ff050db72795f9a44a943b
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fusagiko / takayamaki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shirobai
4
+ module Cop
5
+ module Performance
6
+ # Drop-in Rust reimplementation of `Performance/Detect`
7
+ # (rubocop-performance 1.26.1).
8
+ #
9
+ # Rust replicates the four stock pattern branches (`select` /
10
+ # `find_all` / `filter` chained with `first` / `last` / `[0]` /
11
+ # `[-1]`, block and block-pass forms) including the
12
+ # `accept_first_call?` gates (empty block body, non-block-pass args,
13
+ # `lazy` chains) and the parser-semantics offense range (inner
14
+ # selector through outer selector, where the sugar index form's
15
+ # selector is the whole `[0]` bracket construct). The wrapper applies
16
+ # the Rust-computed removal/replacement ranges — including stock's
17
+ # knowingly broken rewrite of the explicit `.[](0)` form, byte for
18
+ # byte. Messages come from Rust, formatted with the preferred method
19
+ # resolved from `Style/CollectionMethods` below.
20
+ class Detect < RuboCop::Cop::Base
21
+ include Shirobai::Cop::BundleEligible
22
+ extend RuboCop::Cop::AutoCorrector
23
+
24
+ def self.cop_name = "Performance/Detect"
25
+ def self.badge = RuboCop::Cop::Badge.parse(cop_name)
26
+
27
+ # Packed args for the bundled run: `[preferred_method]`. Stock reads
28
+ # `config.for_cop('Style/CollectionMethods')['PreferredMethods']['detect']`
29
+ # and falls back to `detect`; the extra `|| {}` only guards configs
30
+ # where stock would crash (bare `RuboCop::Config.new` without the
31
+ # default `PreferredMethods` hash — packing runs for every config,
32
+ # not just the ones that instantiate this cop).
33
+ def self.bundle_args(config)
34
+ preferred =
35
+ (config.for_cop("Style/CollectionMethods")["PreferredMethods"] || {})["detect"] ||
36
+ "detect"
37
+ [preferred.to_s]
38
+ end
39
+
40
+ def on_new_investigation
41
+ buffer = processed_source.buffer
42
+ source = bundle_eligible? ? processed_source.raw_source : buffer.source
43
+ off = SourceOffsets.for(source)
44
+ resolved_offenses.each do |sel_start, sel_end, recv_end, outer_end, message, replacement|
45
+ range = Parser::Source::Range.new(buffer, off[sel_start], off[outer_end])
46
+ add_offense(range, message: message) do |corrector|
47
+ corrector.remove(Parser::Source::Range.new(buffer, off[recv_end], off[outer_end]))
48
+ corrector.replace(
49
+ Parser::Source::Range.new(buffer, off[sel_start], off[sel_end]), replacement
50
+ )
51
+ end
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def resolved_offenses
58
+ if bundle_eligible?
59
+ Dispatch.offenses_for(processed_source, config, :perf_detect)
60
+ else
61
+ Shirobai.check_perf_detect(
62
+ processed_source.buffer.source, self.class.bundle_args(config)[0]
63
+ )
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shirobai
4
+ module Cop
5
+ module Performance
6
+ # Drop-in Rust reimplementation of `Performance/EndWith`
7
+ # (rubocop-performance 1.26.1).
8
+ #
9
+ # Rust replicates the stock pattern union (regexp argument first,
10
+ # then regexp receiver; `&.` only on the argument side) with the
11
+ # `literal_at_end?` gate: content is `LITERAL_REGEX`-only and anchored
12
+ # with `\z` (or `$` when `SafeMultiline` is false). The wrapper
13
+ # rebuilds the replacement exactly like stock — with the
14
+ # rubocop-performance `RegexpMetacharacter` mixin's
15
+ # `drop_end_metacharacter` and RuboCop's own
16
+ # `interpret_string_escapes` / `to_string_literal` — so anchor
17
+ # dropping, escape interpretation and quote selection cannot drift.
18
+ class EndWith < RuboCop::Cop::Base
19
+ include Shirobai::Cop::BundleEligible
20
+ include RuboCop::Cop::RegexpMetacharacter
21
+ extend RuboCop::Cop::AutoCorrector
22
+
23
+ MSG = "Use `String#end_with?` instead of a regex match anchored " \
24
+ "to the end of the string."
25
+
26
+ def self.cop_name = "Performance/EndWith"
27
+ def self.badge = RuboCop::Cop::Badge.parse(cop_name)
28
+
29
+ # Packed args for the bundled run: `[safe_multiline]` (0/1).
30
+ def self.bundle_args(config)
31
+ [config.for_badge(badge).fetch("SafeMultiline", true) ? 1 : 0]
32
+ end
33
+
34
+ def on_new_investigation
35
+ buffer = processed_source.buffer
36
+ source = bundle_eligible? ? processed_source.raw_source : buffer.source
37
+ off = SourceOffsets.for(source)
38
+ resolved_offenses.each do |start, fin, recv_start, recv_end, dot, content|
39
+ range = Parser::Source::Range.new(buffer, off[start], off[fin])
40
+ add_offense(range) do |corrector|
41
+ receiver_source =
42
+ Parser::Source::Range.new(buffer, off[recv_start], off[recv_end]).source
43
+ literal = to_string_literal(
44
+ interpret_string_escapes(drop_end_metacharacter(content))
45
+ )
46
+ corrector.replace(range, "#{receiver_source}#{dot}end_with?(#{literal})")
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def resolved_offenses
54
+ if bundle_eligible?
55
+ Dispatch.offenses_for(processed_source, config, :perf_end_with)
56
+ else
57
+ Shirobai.check_perf_end_with(
58
+ processed_source.buffer.source, self.class.bundle_args(config)[0] == 1
59
+ )
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shirobai
4
+ module Cop
5
+ module Performance
6
+ # Drop-in Rust reimplementation of `Performance/StartWith`
7
+ # (rubocop-performance 1.26.1).
8
+ #
9
+ # Mirror image of `Shirobai::Cop::Performance::EndWith`: the Rust
10
+ # side gates on `literal_at_start?` (`\A`, or `^` when
11
+ # `SafeMultiline` is false) and the wrapper drops the anchor with the
12
+ # stock `drop_start_metacharacter` before rebuilding the replacement
13
+ # with RuboCop's own string helpers.
14
+ class StartWith < RuboCop::Cop::Base
15
+ include Shirobai::Cop::BundleEligible
16
+ include RuboCop::Cop::RegexpMetacharacter
17
+ extend RuboCop::Cop::AutoCorrector
18
+
19
+ MSG = "Use `String#start_with?` instead of a regex match anchored " \
20
+ "to the beginning of the string."
21
+
22
+ def self.cop_name = "Performance/StartWith"
23
+ def self.badge = RuboCop::Cop::Badge.parse(cop_name)
24
+
25
+ # Packed args for the bundled run: `[safe_multiline]` (0/1).
26
+ def self.bundle_args(config)
27
+ [config.for_badge(badge).fetch("SafeMultiline", true) ? 1 : 0]
28
+ end
29
+
30
+ def on_new_investigation
31
+ buffer = processed_source.buffer
32
+ source = bundle_eligible? ? processed_source.raw_source : buffer.source
33
+ off = SourceOffsets.for(source)
34
+ resolved_offenses.each do |start, fin, recv_start, recv_end, dot, content|
35
+ range = Parser::Source::Range.new(buffer, off[start], off[fin])
36
+ add_offense(range) do |corrector|
37
+ receiver_source =
38
+ Parser::Source::Range.new(buffer, off[recv_start], off[recv_end]).source
39
+ literal = to_string_literal(
40
+ interpret_string_escapes(drop_start_metacharacter(content))
41
+ )
42
+ corrector.replace(range, "#{receiver_source}#{dot}start_with?(#{literal})")
43
+ end
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def resolved_offenses
50
+ if bundle_eligible?
51
+ Dispatch.offenses_for(processed_source, config, :perf_start_with)
52
+ else
53
+ Shirobai.check_perf_start_with(
54
+ processed_source.buffer.source, self.class.bundle_args(config)[0] == 1
55
+ )
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shirobai
4
+ module Cop
5
+ module Performance
6
+ # Drop-in Rust reimplementation of `Performance/StringInclude`
7
+ # (rubocop-performance 1.26.1).
8
+ #
9
+ # Rust replicates the stock pattern union in document order (regexp
10
+ # argument first, then regexp receiver; `!~` and `&.` only match on
11
+ # the argument side) and the `Util::LITERAL_REGEX` literal-only gate
12
+ # over the raw pattern source. The wrapper rebuilds the replacement
13
+ # exactly like stock — with RuboCop's own `interpret_string_escapes`
14
+ # and `to_string_literal` helpers (available through
15
+ # `RuboCop::Cop::Base` -> `include Util`) — so escape interpretation
16
+ # and quote selection cannot drift from stock byte behavior.
17
+ class StringInclude < RuboCop::Cop::Base
18
+ include Shirobai::Cop::BundleEligible
19
+ extend RuboCop::Cop::AutoCorrector
20
+
21
+ MSG = "Use `%<negation>sString#include?` instead of a regex match " \
22
+ "with literal-only pattern."
23
+
24
+ def self.cop_name = "Performance/StringInclude"
25
+ def self.badge = RuboCop::Cop::Badge.parse(cop_name)
26
+
27
+ # Config-less: nothing to pack (the shared segment only carries the
28
+ # department enable flag for this cop).
29
+ def self.bundle_args(_config)
30
+ []
31
+ end
32
+
33
+ def on_new_investigation
34
+ buffer = processed_source.buffer
35
+ source = bundle_eligible? ? processed_source.raw_source : buffer.source
36
+ off = SourceOffsets.for(source)
37
+ resolved_offenses.each do |start, fin, negation, recv_start, recv_end, dot, content|
38
+ negation = negation == 1
39
+ range = Parser::Source::Range.new(buffer, off[start], off[fin])
40
+ message = format(MSG, negation: (negation ? "!" : ""))
41
+ add_offense(range, message: message) do |corrector|
42
+ receiver_source =
43
+ Parser::Source::Range.new(buffer, off[recv_start], off[recv_end]).source
44
+ literal = to_string_literal(interpret_string_escapes(content))
45
+ new_source =
46
+ "#{'!' if negation}#{receiver_source}#{dot}include?(#{literal})"
47
+ corrector.replace(range, new_source)
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def resolved_offenses
55
+ if bundle_eligible?
56
+ Dispatch.offenses_for(processed_source, config, :perf_string_include)
57
+ else
58
+ Shirobai.check_perf_string_include(processed_source.buffer.source)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shirobai
4
+ module Cop
5
+ module Performance
6
+ # Drop-in Rust reimplementation of `Performance/TimesMap`
7
+ # (rubocop-performance 1.26.1).
8
+ #
9
+ # Rust replicates the stock `times_map_call` pattern (literal block on
10
+ # `x.times.map` / `x.times.collect`, or a sole block-pass argument)
11
+ # with the `handleable_receiver?` gate (int/float literal receiver of
12
+ # `times`, or an explicit `.`-dispatched `times` call) and builds both
13
+ # the message (`only if ... 0 or more` for non-literal counts) and the
14
+ # `Array.new(...)` replacement from source slices. The wrapper applies
15
+ # the replacement to the parser-send range (the call without its
16
+ # literal block), exactly like stock's
17
+ # `corrector.replace(map_or_collect, ...)`.
18
+ class TimesMap < RuboCop::Cop::Base
19
+ include Shirobai::Cop::BundleEligible
20
+ extend RuboCop::Cop::AutoCorrector
21
+
22
+ def self.cop_name = "Performance/TimesMap"
23
+ def self.badge = RuboCop::Cop::Badge.parse(cop_name)
24
+
25
+ # Config-less: nothing to pack (the shared segment only carries the
26
+ # department enable flag for this cop).
27
+ def self.bundle_args(_config)
28
+ []
29
+ end
30
+
31
+ def on_new_investigation
32
+ buffer = processed_source.buffer
33
+ source = bundle_eligible? ? processed_source.raw_source : buffer.source
34
+ off = SourceOffsets.for(source)
35
+ resolved_offenses.each do |start, fin, replace_start, replace_end, message, replacement|
36
+ range = Parser::Source::Range.new(buffer, off[start], off[fin])
37
+ add_offense(range, message: message) do |corrector|
38
+ corrector.replace(
39
+ Parser::Source::Range.new(buffer, off[replace_start], off[replace_end]),
40
+ replacement
41
+ )
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def resolved_offenses
49
+ if bundle_eligible?
50
+ Dispatch.offenses_for(processed_source, config, :perf_times_map)
51
+ else
52
+ Shirobai.check_perf_times_map(processed_source.buffer.source)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shirobai
4
+ module Performance
5
+ # Locked to the shirobai core gem version (release train: both gems
6
+ # ship together and the gemspec pins `shirobai` to this exact version).
7
+ VERSION = "2026.0709.0000"
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Load order matters, and this file owns it so users don't have to:
4
+ #
5
+ # 1. `shirobai` first. The core gem loads the native extension, replaces
6
+ # the core cops, and defines `Shirobai::Dispatch` — the registration
7
+ # point for this gem's packed-config segment.
8
+ # 2. `rubocop-performance` second. Stock Performance cop classes must be
9
+ # enlisted in RuboCop's registry BEFORE the wrappers below:
10
+ # `Registry#clear_enrollment_queue` resolves same-badge collisions by
11
+ # last-write-wins, so whoever is defined later owns the badge.
12
+ # Requiring it here (the gemspec pins the exact version) makes the
13
+ # replacement order independent of `.rubocop.yml` require order.
14
+ # 3. Wrapper cop classes last. Defining each class auto-enlists it
15
+ # (`RuboCop::Cop::Base.inherited`) and replaces the stock cop under
16
+ # the same badge.
17
+ #
18
+ # Requiring rubocop-performance here does NOT merge its config/default.yml
19
+ # into RuboCop's default configuration — that is the plugin system's job.
20
+ # Users still declare `plugins: [rubocop-performance]` in `.rubocop.yml`
21
+ # (or legacy `require:`, which RuboCop auto-promotes to a plugin with a
22
+ # deprecation warning) and add `require: [shirobai-performance]`.
23
+ require "shirobai"
24
+ require "rubocop-performance"
25
+
26
+ require_relative "shirobai/performance/version"
27
+ require_relative "shirobai/cop/performance/detect"
28
+ require_relative "shirobai/cop/performance/string_include"
29
+ require_relative "shirobai/cop/performance/end_with"
30
+ require_relative "shirobai/cop/performance/start_with"
31
+ require_relative "shirobai/cop/performance/times_map"
32
+
33
+ # Wake up the Performance origin in the shared bundle: from now on every
34
+ # packed config carries this origin's segment with `enabled=1` plus the
35
+ # department's cop settings (segment layout:
36
+ # crates/shirobai-core/src/rules/bundle.rs BundleConfig). Without this gem
37
+ # the core packs the dormant segment and the Rust side skips the
38
+ # Performance rules entirely.
39
+ Shirobai::Dispatch.register_plugin_packer(:performance) do |config|
40
+ detect = Shirobai::Cop::Performance::Detect.bundle_args(config)
41
+ end_with = Shirobai::Cop::Performance::EndWith.bundle_args(config)
42
+ start_with = Shirobai::Cop::Performance::StartWith.bundle_args(config)
43
+ [[1, end_with[0], start_with[0]], [[detect[0]]]]
44
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shirobai-performance
3
+ version: !ruby/object:Gem::Version
4
+ version: 2026.0709.0000
5
+ platform: ruby
6
+ authors:
7
+ - fusagiko / takayamaki
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: shirobai
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '='
17
+ - !ruby/object:Gem::Version
18
+ version: 2026.0709.0000
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - '='
24
+ - !ruby/object:Gem::Version
25
+ version: 2026.0709.0000
26
+ - !ruby/object:Gem::Dependency
27
+ name: rubocop-performance
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.26.1
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '='
38
+ - !ruby/object:Gem::Version
39
+ version: 1.26.1
40
+ executables: []
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - LICENSE.txt
45
+ - lib/shirobai-performance.rb
46
+ - lib/shirobai/cop/performance/detect.rb
47
+ - lib/shirobai/cop/performance/end_with.rb
48
+ - lib/shirobai/cop/performance/start_with.rb
49
+ - lib/shirobai/cop/performance/string_include.rb
50
+ - lib/shirobai/cop/performance/times_map.rb
51
+ - lib/shirobai/performance/version.rb
52
+ homepage: https://github.com/takayamaki/shirobai
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '3.1'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubygems_version: 4.0.10
71
+ specification_version: 4
72
+ summary: Drop-in Rust replacement for rubocop-performance cops
73
+ test_files: []