rubocop-legion 0.1.2 → 0.1.3

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: 1d2c3a1967dcc9bd66a2c806d2b471b59594d51ae9fec7c2c3eaad9946898932
4
- data.tar.gz: cdd7fcb62b6b0ff1eb17d595aa6a7b76259fdefa7ae5ecd6d6b1306f98e817c1
3
+ metadata.gz: b8cc626a680f38939c6212bd03e40249c354e24e8d4d8415aee6aa00c449e67e
4
+ data.tar.gz: 3eaed689593c5ec2ec4e24c89104c856ff0bff298302c278f1ca296d7278161f
5
5
  SHA512:
6
- metadata.gz: 0515bb7d5ea06e80069a937b9899e23bf281366660d718cd707460b0ed63a9955ed4ff531f6e592c9b203ea090bda1ba620d5d80fbb4b758dab3b91f9190dc71
7
- data.tar.gz: 673910f539a627bd4697e1bfd86ee8c8b0f9644d257090fafcad43907bd080af80be71e961340e53be6077251dd8dd302b957fcb8d74a4418be228b3f6fd175c
6
+ metadata.gz: 8ac7d705d82418617f8d9ff3e67524911ff1c947a381c1ab61fcbdc35a1fa5c7537e9dc017f7118ca0037eebe27ab52d352e08a7433fde06cf641b48e8e13006
7
+ data.tar.gz: ea1138ce50b98a013ea6b4de431eebb336a087ef3204b6be1c20061786d3e8c43f589958bc03050f1ed4d3f5bb9e9808b8da50eafbeeff323455a494be76e7bd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.3] - 2026-03-29
4
+
5
+ ### Added
6
+ - Shared config profiles: `config/lex.yml` for lex-* gems, `config/core.yml` for legion-* gems
7
+ - Use `inherit_gem: { rubocop-legion: config/lex.yml }` to replace 60-line .rubocop.yml with 2 lines
8
+
3
9
  ## [0.1.2] - 2026-03-29
4
10
 
5
11
  ### Added
data/CLAUDE.md ADDED
@@ -0,0 +1,96 @@
1
+ # rubocop-legion
2
+
3
+ **Parent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
4
+
5
+ ## What is This?
6
+
7
+ Custom RuboCop plugin gem for the LegionIO ecosystem. Provides 32 AST-based cops across 6 departments. Uses the new RuboCop Plugin API (1.72+, lint_roller-based) with auto-discovery via gemspec metadata.
8
+
9
+ **GitHub**: https://github.com/LegionIO/rubocop-legion
10
+ **RubyGems**: https://rubygems.org/gems/rubocop-legion
11
+ **License**: MIT
12
+
13
+ ## Cop Scoping
14
+
15
+ Cops are scoped by gem type — no per-repo configuration needed:
16
+
17
+ - **Universal** (9 cops): Fire on all LegionIO gems
18
+ - **Library-specific** (6 cops): Fire on all gems but only trigger when using Sequel, Sinatra, Thor, Faraday, or cache
19
+ - **LEX-only** (17 cops): Scoped to `lib/legion/extensions/**/*.rb` via Include directive — never fire on core `legion-*` libraries
20
+
21
+ ## Departments and Cops
22
+
23
+ ### Universal — 9 cops
24
+
25
+ - **ConstantSafety** (4): `BareDataDefine`, `BareProcess`, `BareJson` (all error, auto-fix) — prefix with `::` inside `module Legion`. `InheritParam` (convention, auto-fix) — pass `false` to `const_defined?`/`const_get`.
26
+ - **RescueLogging** (3): `BareRescue` (warning, auto-fix) — capture with `=> e`. `NoCapture` (convention, no auto-fix) — exception class without capture. `SilentCapture` (warning, no auto-fix) — captured but never logged/re-raised. Skips `_`-prefixed vars. All skip inline rescue modifiers.
27
+ - **Singleton** (1): `UseInstance` (error, auto-fix) — `.instance` not `.new` for configurable singleton classes.
28
+ - **Framework/ModuleFunctionPrivate** (1): `private` after `module_function` resets visibility.
29
+
30
+ ### Library-Specific — 6 cops
31
+
32
+ - `EagerSequelModel` — `Sequel::Model(:table)` at require time
33
+ - `SinatraHostAuth` — Sinatra 4.0+ `set :host_authorization`
34
+ - `ThorReservedRun` — Thor 1.5+ reserves `run`
35
+ - `FaradayXmlMiddleware` — Faraday 2.0+ removed `:xml`
36
+ - `CacheTimeCoercion` — Time→String after cache round-trip
37
+ - `ApiStringKeys` — `Legion::JSON.load` returns symbol keys (scoped to `lib/legion/extensions/**/*.rb`)
38
+
39
+ ### LEX-Only — 17 cops
40
+
41
+ - **HelperMigration** (7): `DirectLogging`, `OldLoggingMethods`, `DirectJson`, `DirectCache`, `DirectLocalCache`, `DirectCrypt` (all auto-fix) — use per-extension helpers, not global singletons. `LoggingGuard` (no auto-fix) — remove unnecessary `respond_to?(:log_warn)` / `defined?(Legion::Logging)` guards.
42
+ - **Extension** (10): `ActorSingularModule` (auto-fix), `CoreExtendGuard` (auto-fix), `RunnerMustBeModule`, `RunnerIncludeHelpers`, `SelfContainedActorRunnerClass`, `RunnerReturnHash`, `SettingsKeyMethod` (auto-fix), `SettingsBracketMultiArg` (auto-fix), `LlmAskKwargs`, `DataRequiredWithoutMigrations`.
43
+
44
+ ## Architecture
45
+
46
+ ```
47
+ rubocop-legion/
48
+ ├── lib/
49
+ │ ├── rubocop-legion.rb # Entry point, requires all cops
50
+ │ └── rubocop/
51
+ │ ├── legion.rb # Namespace declarations
52
+ │ ├── legion/
53
+ │ │ ├── version.rb
54
+ │ │ └── plugin.rb # LintRoller::Plugin (auto-discovery)
55
+ │ └── cop/legion/
56
+ │ ├── helper_migration/ # 7 cops (lex-only)
57
+ │ ├── constant_safety/ # 4 cops (universal)
58
+ │ ├── singleton/ # 1 cop (universal)
59
+ │ ├── rescue_logging/ # 3 cops (universal)
60
+ │ ├── framework/ # 7 cops (universal + library-specific)
61
+ │ └── extension/ # 10 cops (lex-only)
62
+ ├── config/
63
+ │ └── default.yml # All cop defaults, Include/Exclude scoping
64
+ └── spec/ # 233 specs, mirrors lib/ structure
65
+ ```
66
+
67
+ ## Key Implementation Details
68
+
69
+ - Plugin entry point: `RuboCop::Legion::Plugin` (LintRoller-based, registered via gemspec metadata `default_lint_roller_plugin`)
70
+ - All cops inherit from `RuboCop::Cop::Base`
71
+ - Auto-correctable cops use `extend AutoCorrector`
72
+ - AST matching via `def_node_matcher` and `def_node_search`
73
+ - Specs use `RuboCop::RSpec::Support` with `:config` shared context and `expect_offense`/`expect_correction`
74
+ - `BareRescue` and `NoCapture` skip rescue modifiers (inline `rescue`) to avoid syntax corruption
75
+ - `NoCapture` has no auto-correct to prevent correction loop with `Lint/UselessAssignment`
76
+ - `SilentCapture` skips `_`-prefixed variables (Ruby unused convention)
77
+
78
+ ## Development
79
+
80
+ ```bash
81
+ bundle install
82
+ bundle exec rspec # 233 specs
83
+ bundle exec rubocop # Self-linting
84
+ ```
85
+
86
+ ## Common Per-Repo Overrides
87
+
88
+ ```yaml
89
+ # Repos using Faraday JSON middleware (string keys, not Legion::JSON symbol keys)
90
+ Legion/Framework/ApiStringKeys:
91
+ Enabled: false
92
+ ```
93
+
94
+ ---
95
+
96
+ **Maintained By**: Matthew Iverson (@Esity)
data/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  LegionIO code quality cops for [RuboCop](https://rubocop.org/).
4
4
 
5
- Custom cops for the LegionIO async job engine ecosystem. Enforces helper usage, constant safety, rescue logging, framework conventions, and LEX extension structure.
5
+ Custom cops for the LegionIO async job engine ecosystem. Enforces helper usage, constant safety, rescue logging, framework conventions, and LEX extension structure. Replaces the regex-based `lint-patterns.yml` CI workflow with precise AST-based analysis and auto-correction.
6
6
 
7
7
  ## Installation
8
8
 
9
9
  Add to your Gemfile:
10
10
 
11
11
  ```ruby
12
- gem 'rubocop-legion', require: false, group: :development
12
+ gem 'rubocop-legion', '~> 0.1', require: false, group: :development
13
13
  ```
14
14
 
15
15
  ## Usage
@@ -21,16 +21,78 @@ plugins:
21
21
  - rubocop-legion
22
22
  ```
23
23
 
24
- ## Departments
24
+ Requires RuboCop 1.72+ (Plugin API with lint_roller).
25
25
 
26
- | Department | Cops | Description |
27
- |---|---|---|
28
- | `Legion/HelperMigration` | 6 | Use per-extension helpers, not global singletons |
29
- | `Legion/ConstantSafety` | 4 | Prevent namespace resolution bugs inside `module Legion` |
30
- | `Legion/Singleton` | 1 | Enforce `.instance` on singleton classes |
31
- | `Legion/RescueLogging` | 3 | Every rescue must log or re-raise |
32
- | `Legion/Framework` | 7 | Sequel, Sinatra, Thor, Faraday, and API gotchas |
33
- | `Legion/Extension` | 10 | LEX structural convention enforcement |
26
+ ## Cop Scoping
27
+
28
+ Cops are automatically scoped based on where they should apply:
29
+
30
+ - **Universal cops** fire on all LegionIO gems (any code inside `module Legion`)
31
+ - **Library-specific cops** fire on all gems but only trigger when using a specific library (Sequel, Sinatra, Thor, Faraday, etc.)
32
+ - **LEX-only cops** fire only on `lib/legion/extensions/**/*.rb` they don't apply to core `legion-*` libraries
33
+
34
+ No per-repo configuration needed for scoping. If a cop doesn't apply to your gem type, it won't fire.
35
+
36
+ ## Cops
37
+
38
+ ### Universal (all LegionIO gems) — 9 cops
39
+
40
+ | Department | Cop | Severity | Auto-fix | Description |
41
+ |---|---|---|---|---|
42
+ | ConstantSafety | `BareDataDefine` | error | yes | Use `::Data.define` inside `module Legion` to avoid `Legion::Data` |
43
+ | ConstantSafety | `BareProcess` | error | yes | Use `::Process` inside `module Legion` to avoid `Legion::Process` |
44
+ | ConstantSafety | `BareJson` | error | yes | Use `::JSON` inside `module Legion` to avoid `Legion::JSON` |
45
+ | ConstantSafety | `InheritParam` | convention | yes | Pass `false` to `const_defined?`/`const_get` on dynamic modules |
46
+ | RescueLogging | `BareRescue` | warning | yes | Bare `rescue` swallows exceptions — capture with `rescue => e` |
47
+ | RescueLogging | `NoCapture` | convention | no | Exception class specified but not captured (`rescue Error` without `=> e`) |
48
+ | RescueLogging | `SilentCapture` | warning | no | Captured exception never logged or re-raised |
49
+ | Singleton | `UseInstance` | error | yes | Use `.instance` instead of `.new` for singleton classes |
50
+ | Framework | `ModuleFunctionPrivate` | convention | no | `private` after `module_function` resets visibility |
51
+
52
+ ### Library-Specific (all gems, triggers on library usage) — 6 cops
53
+
54
+ | Department | Cop | Triggers on | Severity | Auto-fix | Description |
55
+ |---|---|---|---|---|---|
56
+ | Framework | `EagerSequelModel` | Sequel | warning | no | `Sequel::Model(:table)` introspects schema at require time |
57
+ | Framework | `SinatraHostAuth` | Sinatra | convention | no | Sinatra 4.0+ requires `set :host_authorization` |
58
+ | Framework | `ThorReservedRun` | Thor | warning | no | Thor 1.5+ reserves `run` — rename or use `map` |
59
+ | Framework | `FaradayXmlMiddleware` | Faraday | error | no | Faraday 2.0+ removed built-in `:xml` middleware |
60
+ | Framework | `CacheTimeCoercion` | cache_get | convention | no | Time objects become Strings after cache round-trip |
61
+ | Framework | `ApiStringKeys` | Legion::JSON.load | warning | yes | `Legion::JSON.load` returns symbol keys — use `body[:key]` |
62
+
63
+ ### LEX Extensions Only (`lib/legion/extensions/**/*.rb`) — 17 cops
64
+
65
+ | Department | Cop | Severity | Auto-fix | Description |
66
+ |---|---|---|---|---|
67
+ | HelperMigration | `DirectLogging` | warning | yes | Use `log.method` instead of `Legion::Logging.method` |
68
+ | HelperMigration | `OldLoggingMethods` | warning | yes | Use `log.method` instead of deprecated `log_method` helpers |
69
+ | HelperMigration | `DirectJson` | convention | yes | Use `json_load`/`json_dump` instead of `Legion::JSON` |
70
+ | HelperMigration | `DirectCache` | warning | yes | Use `cache_get`/`cache_set` instead of `Legion::Cache` |
71
+ | HelperMigration | `DirectLocalCache` | warning | yes | Use `local_cache_get`/`local_cache_set` instead of `Legion::Cache::Local` |
72
+ | HelperMigration | `DirectCrypt` | warning | yes | Use `vault_get`/`vault_exist?` instead of `Legion::Crypt` |
73
+ | HelperMigration | `LoggingGuard` | convention | no | Remove unnecessary `respond_to?(:log_warn)` / `defined?(Legion::Logging)` guards |
74
+ | Extension | `ActorSingularModule` | error | yes | Use `module Actor` (singular) — framework discovers `Actor`, not `Actors` |
75
+ | Extension | `CoreExtendGuard` | error | yes | Guard `extend Core` with `const_defined?` for standalone compatibility |
76
+ | Extension | `RunnerMustBeModule` | warning | no | Runners must be modules, not classes |
77
+ | Extension | `RunnerIncludeHelpers` | convention | no | Runner modules need `include Helpers::Lex` or `extend self` |
78
+ | Extension | `SelfContainedActorRunnerClass` | warning | no | Self-contained actors must override `runner_class` |
79
+ | Extension | `RunnerReturnHash` | convention | no | Runner methods must return a Hash |
80
+ | Extension | `SettingsKeyMethod` | error | yes | `Legion::Settings` has no `key?` — use `!Settings[:key].nil?` |
81
+ | Extension | `SettingsBracketMultiArg` | error | yes | `Settings#[]` takes 1 arg — use `Settings.dig(...)` for nested access |
82
+ | Extension | `LlmAskKwargs` | error | no | `Legion::LLM.ask` only accepts `message:` — no extra kwargs |
83
+ | Extension | `DataRequiredWithoutMigrations` | warning | no | `data_required?` returns true but migrations may be missing |
84
+
85
+ **Total: 32 cops** across 6 departments, 15 auto-correctable.
86
+
87
+ ## Per-Repo Overrides
88
+
89
+ Most repos need no overrides. Common exceptions:
90
+
91
+ ```yaml
92
+ # Repos using Faraday JSON middleware (string keys, not Legion::JSON symbol keys)
93
+ Legion/Framework/ApiStringKeys:
94
+ Enabled: false
95
+ ```
34
96
 
35
97
  ## License
36
98
 
data/config/base.yml ADDED
@@ -0,0 +1,60 @@
1
+ # Shared RuboCop configuration for all LegionIO gems.
2
+ # Do not use directly — inherit via config/lex.yml or config/core.yml.
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 3.4
6
+ NewCops: enable
7
+ SuggestExtensions: false
8
+
9
+ Layout/LineLength:
10
+ Max: 160
11
+
12
+ Layout/SpaceAroundEqualsInParameterDefault:
13
+ EnforcedStyle: space
14
+
15
+ Layout/HashAlignment:
16
+ EnforcedHashRocketStyle: table
17
+ EnforcedColonStyle: table
18
+
19
+ Metrics/MethodLength:
20
+ Max: 50
21
+
22
+ Metrics/ClassLength:
23
+ Max: 1500
24
+
25
+ Metrics/ModuleLength:
26
+ Max: 1500
27
+
28
+ Metrics/BlockLength:
29
+ Max: 40
30
+ Exclude:
31
+ - 'spec/**/*'
32
+ - '*.gemspec'
33
+
34
+ Metrics/AbcSize:
35
+ Max: 60
36
+
37
+ Metrics/CyclomaticComplexity:
38
+ Max: 15
39
+
40
+ Metrics/PerceivedComplexity:
41
+ Max: 17
42
+
43
+ Style/Documentation:
44
+ Enabled: false
45
+
46
+ Style/SymbolArray:
47
+ Enabled: true
48
+
49
+ Style/FrozenStringLiteralComment:
50
+ Enabled: true
51
+ EnforcedStyle: always
52
+
53
+ Naming/FileName:
54
+ Enabled: false
55
+
56
+ Naming/PredicateMethod:
57
+ Enabled: false
58
+
59
+ Gemspec/DevelopmentDependencies:
60
+ Enabled: false
data/config/core.yml ADDED
@@ -0,0 +1,17 @@
1
+ # Shared RuboCop configuration for legion-* core library gems.
2
+ #
3
+ # Usage in your .rubocop.yml:
4
+ #
5
+ # inherit_gem:
6
+ # rubocop-legion: config/core.yml
7
+ #
8
+ # # Repo-specific overrides below (if any)
9
+
10
+ inherit_from: base.yml
11
+
12
+ plugins:
13
+ - rubocop-legion
14
+
15
+ Metrics/ParameterLists:
16
+ Max: 10
17
+ CountKeywordArgs: false
data/config/lex.yml ADDED
@@ -0,0 +1,16 @@
1
+ # Shared RuboCop configuration for lex-* extension gems.
2
+ #
3
+ # Usage in your .rubocop.yml:
4
+ #
5
+ # inherit_gem:
6
+ # rubocop-legion: config/lex.yml
7
+ #
8
+ # # Repo-specific overrides below (if any)
9
+
10
+ inherit_from: base.yml
11
+
12
+ plugins:
13
+ - rubocop-legion
14
+
15
+ Metrics/ParameterLists:
16
+ Max: 8
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Legion
5
- VERSION = '0.1.2'
5
+ VERSION = '0.1.3'
6
6
  end
7
7
  end
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.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -78,11 +78,15 @@ files:
78
78
  - ".rspec"
79
79
  - ".rubocop.yml"
80
80
  - CHANGELOG.md
81
+ - CLAUDE.md
81
82
  - Gemfile
82
83
  - LICENSE
83
84
  - README.md
84
85
  - Rakefile
86
+ - config/base.yml
87
+ - config/core.yml
85
88
  - config/default.yml
89
+ - config/lex.yml
86
90
  - lib/rubocop-legion.rb
87
91
  - lib/rubocop/cop/legion/constant_safety/bare_data_define.rb
88
92
  - lib/rubocop/cop/legion/constant_safety/bare_json.rb