rubocop-legion 0.1.6 → 0.1.7
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 +4 -4
- data/CHANGELOG.md +13 -0
- data/CLAUDE.md +5 -5
- data/README.md +9 -7
- data/config/default.yml +23 -6
- data/lib/rubocop/cop/legion/helper_migration/direct_cache.rb +17 -7
- data/lib/rubocop/cop/legion/helper_migration/direct_crypt.rb +8 -5
- data/lib/rubocop/cop/legion/helper_migration/direct_json.rb +14 -5
- data/lib/rubocop/cop/legion/helper_migration/direct_knowledge.rb +82 -0
- data/lib/rubocop/cop/legion/helper_migration/direct_llm.rb +61 -0
- data/lib/rubocop/cop/legion/helper_migration/direct_local_cache.rb +11 -5
- data/lib/rubocop/cop/legion/helper_migration/direct_transport.rb +76 -0
- data/lib/rubocop/legion/version.rb +1 -1
- data/lib/rubocop-legion.rb +3 -1
- metadata +4 -2
- data/lib/rubocop/cop/legion/helper_migration/direct_llm_embed.rb +0 -43
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cd43ed49ee3f7013316b5650cfb288d60fd6e1807532acb1f8978865a39a519e
|
|
4
|
+
data.tar.gz: a620ac1fc4debec154a69eb72a75b5df1c0a2fb8f7974e5a29fbefed46604549
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bf447d4891c6c75429b9f0fe92a3f3fc441c11782d6bf97d9b57cc45c1ac77fbbf5314319f9aa2af9681701d4af99a609a8d56cddd63415a01db17bc6ae35ff3
|
|
7
|
+
data.tar.gz: 239ebbc2294b1ac2b366894ea17d7699a3c3532d672677d34cf8c562497bc2a51367ca6f01984af291d955d310df7fbb95bf257085bb5a37531fa10fb038ae7f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.7] - 2026-03-29
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- New cop `Legion/HelperMigration/DirectTransport`: use `transport_*` helpers instead of `Legion::Transport::Connection`/`Spool` methods (auto-fix)
|
|
7
|
+
- New cop `Legion/HelperMigration/DirectKnowledge`: use `query_knowledge`/`ingest_knowledge` helpers instead of `Legion::Apollo`/`Legion::Apollo::Local` methods (auto-fix)
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Renamed `Legion/HelperMigration/DirectLlmEmbed` to `Legion/HelperMigration/DirectLlm` — now covers `chat`, `ask`, `structured`, `embed_batch` in addition to `embed`
|
|
11
|
+
- Expanded `Legion/HelperMigration/DirectJson` to cover `parse`, `generate`, `pretty_generate`
|
|
12
|
+
- Expanded `Legion/HelperMigration/DirectCache` to cover `fetch`, `connected?`
|
|
13
|
+
- Expanded `Legion/HelperMigration/DirectLocalCache` to cover `delete`, `fetch`
|
|
14
|
+
- Expanded `Legion/HelperMigration/DirectCrypt` to cover `write`
|
|
15
|
+
|
|
3
16
|
## [0.1.6] - 2026-03-29
|
|
4
17
|
|
|
5
18
|
### Added
|
data/CLAUDE.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## What is This?
|
|
6
6
|
|
|
7
|
-
Custom RuboCop plugin gem for the LegionIO ecosystem. Provides
|
|
7
|
+
Custom RuboCop plugin gem for the LegionIO ecosystem. Provides 47 AST-based cops across 6 departments. Uses the new RuboCop Plugin API (1.72+, lint_roller-based) with auto-discovery via gemspec metadata.
|
|
8
8
|
|
|
9
9
|
**GitHub**: https://github.com/LegionIO/rubocop-legion
|
|
10
10
|
**RubyGems**: https://rubygems.org/gems/rubocop-legion
|
|
@@ -33,7 +33,7 @@ Cops are scoped by gem type — no per-repo configuration needed:
|
|
|
33
33
|
|
|
34
34
|
- **Universal** (9 cops): Fire on all LegionIO gems
|
|
35
35
|
- **Library-specific** (6 cops): Fire on all gems but only trigger when using Sequel, Sinatra, Thor, Faraday, or cache
|
|
36
|
-
- **LEX-only** (
|
|
36
|
+
- **LEX-only** (31 cops): Scoped to `lib/legion/extensions/**/*.rb` via Include directive — never fire on core `legion-*` libraries
|
|
37
37
|
|
|
38
38
|
## Departments and Cops
|
|
39
39
|
|
|
@@ -56,7 +56,7 @@ Cops are scoped by gem type — no per-repo configuration needed:
|
|
|
56
56
|
|
|
57
57
|
### LEX-Only — 29 cops
|
|
58
58
|
|
|
59
|
-
- **HelperMigration** (
|
|
59
|
+
- **HelperMigration** (13): `DirectLogging`, `OldLoggingMethods`, `DirectJson`, `DirectCache`, `DirectLocalCache`, `DirectCrypt`, `DirectData`, `DirectLlm`, `DirectTransport`, `DirectKnowledge`, `RequireDefinedGuard` (all auto-fix) — use per-extension helpers, not global singletons. `LoggingGuard` (no auto-fix) — remove unnecessary `respond_to?(:log_warn)` / `defined?(Legion::Logging)` guards. `DefinedTransportGuard` (no auto-fix) — use `transport_connected?` instead of `defined?(Legion::Transport)`.
|
|
60
60
|
- **Extension** (18): `ActorSingularModule` (auto-fix), `RunnerPluralModule` (auto-fix), `CoreExtendGuard` (auto-fix), `RunnerMustBeModule`, `RunnerIncludeHelpers`, `ActorInheritance`, `EveryActorRequiresTime`, `SelfContainedActorRunnerClass`, `HookMissingRunnerClass`, `AbsorberMissingPattern`, `AbsorberMissingAbsorbMethod`, `DefinitionCallMismatched`, `RunnerReturnHash`, `SettingsKeyMethod` (auto-fix), `SettingsBracketMultiArg` (auto-fix), `LlmAskKwargs`, `ActorEnabledSideEffects`, `DataRequiredWithoutMigrations`.
|
|
61
61
|
|
|
62
62
|
## Architecture
|
|
@@ -71,7 +71,7 @@ rubocop-legion/
|
|
|
71
71
|
│ │ ├── version.rb
|
|
72
72
|
│ │ └── plugin.rb # LintRoller::Plugin (auto-discovery)
|
|
73
73
|
│ └── cop/legion/
|
|
74
|
-
│ ├── helper_migration/ #
|
|
74
|
+
│ ├── helper_migration/ # 13 cops (lex-only)
|
|
75
75
|
│ ├── constant_safety/ # 4 cops (universal)
|
|
76
76
|
│ ├── singleton/ # 1 cop (universal)
|
|
77
77
|
│ ├── rescue_logging/ # 3 cops (universal)
|
|
@@ -97,7 +97,7 @@ rubocop-legion/
|
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
99
|
bundle install
|
|
100
|
-
bundle exec rspec #
|
|
100
|
+
bundle exec rspec # 350 specs
|
|
101
101
|
bundle exec rubocop # Self-linting
|
|
102
102
|
```
|
|
103
103
|
|
data/README.md
CHANGED
|
@@ -85,19 +85,21 @@ No per-repo configuration needed for scoping. If a cop doesn't apply to your gem
|
|
|
85
85
|
| Framework | `CacheTimeCoercion` | cache_get | convention | no | Time objects become Strings after cache round-trip |
|
|
86
86
|
| Framework | `ApiStringKeys` | Legion::JSON.load | warning | yes | `Legion::JSON.load` returns symbol keys — use `body[:key]` |
|
|
87
87
|
|
|
88
|
-
### LEX Extensions Only (`lib/legion/extensions/**/*.rb`) —
|
|
88
|
+
### LEX Extensions Only (`lib/legion/extensions/**/*.rb`) — 31 cops
|
|
89
89
|
|
|
90
90
|
| Department | Cop | Severity | Auto-fix | Description |
|
|
91
91
|
|---|---|---|---|---|
|
|
92
92
|
| HelperMigration | `DirectLogging` | warning | yes | Use `log.method` instead of `Legion::Logging.method` |
|
|
93
93
|
| HelperMigration | `OldLoggingMethods` | warning | yes | Use `log.method` instead of deprecated `log_method` helpers |
|
|
94
|
-
| HelperMigration | `DirectJson` | convention | yes | Use `
|
|
95
|
-
| HelperMigration | `DirectCache` | warning | yes | Use `
|
|
96
|
-
| HelperMigration | `DirectLocalCache` | warning | yes | Use `
|
|
97
|
-
| HelperMigration | `DirectCrypt` | warning | yes | Use `
|
|
94
|
+
| HelperMigration | `DirectJson` | convention | yes | Use `json_*` helpers instead of `Legion::JSON` methods |
|
|
95
|
+
| HelperMigration | `DirectCache` | warning | yes | Use `cache_*` helpers instead of `Legion::Cache` methods |
|
|
96
|
+
| HelperMigration | `DirectLocalCache` | warning | yes | Use `local_cache_*` helpers instead of `Legion::Cache::Local` methods |
|
|
97
|
+
| HelperMigration | `DirectCrypt` | warning | yes | Use `vault_*` helpers instead of `Legion::Crypt` methods |
|
|
98
98
|
| HelperMigration | `LoggingGuard` | convention | no | Remove unnecessary `respond_to?(:log_warn)` / `defined?(Legion::Logging)` guards |
|
|
99
99
|
| HelperMigration | `DirectData` | convention | yes | Use `data_connection`/`local_data_*` instead of `Legion::Data::Connection`/`Local` |
|
|
100
|
-
| HelperMigration | `
|
|
100
|
+
| HelperMigration | `DirectLlm` | convention | yes | Use `llm_*` helpers instead of `Legion::LLM` methods |
|
|
101
|
+
| HelperMigration | `DirectTransport` | convention | yes | Use `transport_*` helpers instead of `Legion::Transport::Connection`/`Spool` |
|
|
102
|
+
| HelperMigration | `DirectKnowledge` | convention | yes | Use `query_knowledge`/`ingest_knowledge` instead of `Legion::Apollo` methods |
|
|
101
103
|
| HelperMigration | `RequireDefinedGuard` | convention | yes | Remove `if defined?(Legion::...)` guard from `require` statements |
|
|
102
104
|
| HelperMigration | `DefinedTransportGuard` | convention | no | Use `transport_connected?` instead of `defined?(Legion::Transport)` |
|
|
103
105
|
| Extension | `ActorSingularModule` | error | yes | Use `module Actor` (singular) — framework discovers `Actor`, not `Actors` |
|
|
@@ -119,7 +121,7 @@ No per-repo configuration needed for scoping. If a cop doesn't apply to your gem
|
|
|
119
121
|
| Extension | `ActorEnabledSideEffects` | convention | no | `enabled?` runs during boot — keep side-effect-free |
|
|
120
122
|
| Extension | `DataRequiredWithoutMigrations` | warning | no | `data_required?` returns true but migrations may be missing |
|
|
121
123
|
|
|
122
|
-
**Total:
|
|
124
|
+
**Total: 47 custom cops** across 6 departments, 21 auto-correctable.
|
|
123
125
|
|
|
124
126
|
### Bundled Plugins
|
|
125
127
|
|
data/config/default.yml
CHANGED
|
@@ -20,28 +20,32 @@ Legion/HelperMigration/OldLoggingMethods:
|
|
|
20
20
|
VersionAdded: '0.1'
|
|
21
21
|
|
|
22
22
|
Legion/HelperMigration/DirectJson:
|
|
23
|
-
Description: 'Use `
|
|
23
|
+
Description: 'Use `json_*` helpers instead of `Legion::JSON` methods.'
|
|
24
24
|
Enabled: true
|
|
25
25
|
Severity: convention
|
|
26
26
|
VersionAdded: '0.1'
|
|
27
|
+
VersionChanged: '0.1.7'
|
|
27
28
|
|
|
28
29
|
Legion/HelperMigration/DirectCache:
|
|
29
|
-
Description: 'Use `
|
|
30
|
+
Description: 'Use `cache_*` helpers instead of `Legion::Cache` methods.'
|
|
30
31
|
Enabled: true
|
|
31
32
|
Severity: warning
|
|
32
33
|
VersionAdded: '0.1'
|
|
34
|
+
VersionChanged: '0.1.7'
|
|
33
35
|
|
|
34
36
|
Legion/HelperMigration/DirectLocalCache:
|
|
35
|
-
Description: 'Use `
|
|
37
|
+
Description: 'Use `local_cache_*` helpers instead of `Legion::Cache::Local` methods.'
|
|
36
38
|
Enabled: true
|
|
37
39
|
Severity: warning
|
|
38
40
|
VersionAdded: '0.1'
|
|
41
|
+
VersionChanged: '0.1.7'
|
|
39
42
|
|
|
40
43
|
Legion/HelperMigration/DirectCrypt:
|
|
41
|
-
Description: 'Use `
|
|
44
|
+
Description: 'Use `vault_*` helpers instead of `Legion::Crypt` methods.'
|
|
42
45
|
Enabled: true
|
|
43
46
|
Severity: warning
|
|
44
47
|
VersionAdded: '0.1'
|
|
48
|
+
VersionChanged: '0.1.7'
|
|
45
49
|
|
|
46
50
|
Legion/HelperMigration/LoggingGuard:
|
|
47
51
|
Description: 'Remove unnecessary `respond_to?(:log_warn)` or `defined?(Legion::Logging)` guards.'
|
|
@@ -55,11 +59,24 @@ Legion/HelperMigration/DirectData:
|
|
|
55
59
|
Severity: convention
|
|
56
60
|
VersionAdded: '0.1.4'
|
|
57
61
|
|
|
58
|
-
Legion/HelperMigration/
|
|
59
|
-
Description: 'Use `
|
|
62
|
+
Legion/HelperMigration/DirectLlm:
|
|
63
|
+
Description: 'Use `llm_*` helpers instead of `Legion::LLM` methods.'
|
|
60
64
|
Enabled: true
|
|
61
65
|
Severity: convention
|
|
62
66
|
VersionAdded: '0.1.4'
|
|
67
|
+
VersionChanged: '0.1.7'
|
|
68
|
+
|
|
69
|
+
Legion/HelperMigration/DirectTransport:
|
|
70
|
+
Description: 'Use `transport_*` helpers instead of `Legion::Transport::Connection`/`Spool` methods.'
|
|
71
|
+
Enabled: true
|
|
72
|
+
Severity: convention
|
|
73
|
+
VersionAdded: '0.1.7'
|
|
74
|
+
|
|
75
|
+
Legion/HelperMigration/DirectKnowledge:
|
|
76
|
+
Description: 'Use `query_knowledge`/`ingest_knowledge` helpers instead of `Legion::Apollo` methods.'
|
|
77
|
+
Enabled: true
|
|
78
|
+
Severity: convention
|
|
79
|
+
VersionAdded: '0.1.7'
|
|
63
80
|
|
|
64
81
|
Legion/HelperMigration/RequireDefinedGuard:
|
|
65
82
|
Description: 'Remove `if defined?(Legion::...)` guard from `require`/`require_relative` statements.'
|
|
@@ -4,36 +4,42 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Legion
|
|
6
6
|
module HelperMigration
|
|
7
|
-
# Detects direct calls to `Legion::Cache
|
|
8
|
-
#
|
|
7
|
+
# Detects direct calls to `Legion::Cache` methods and suggests using
|
|
8
|
+
# the `cache_*` helpers instead.
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
# # bad
|
|
12
12
|
# Legion::Cache.get('key')
|
|
13
13
|
# Legion::Cache.set('key', value)
|
|
14
14
|
# Legion::Cache.delete('key')
|
|
15
|
+
# Legion::Cache.fetch('key') { compute }
|
|
16
|
+
# Legion::Cache.connected?
|
|
15
17
|
#
|
|
16
18
|
# # good
|
|
17
19
|
# cache_get('key')
|
|
18
20
|
# cache_set('key', value)
|
|
19
21
|
# cache_delete('key')
|
|
22
|
+
# cache_fetch('key') { compute }
|
|
23
|
+
# cache_connected?
|
|
20
24
|
class DirectCache < RuboCop::Cop::Base
|
|
21
25
|
extend AutoCorrector
|
|
22
26
|
|
|
23
27
|
MSG = 'Use `%<helper>s` instead of `Legion::Cache.%<method>s`. ' \
|
|
24
28
|
'Include the appropriate cache helper mixin.'
|
|
25
29
|
|
|
26
|
-
RESTRICT_ON_SEND = %i[get set delete].freeze
|
|
30
|
+
RESTRICT_ON_SEND = %i[get set delete fetch connected?].freeze
|
|
27
31
|
|
|
28
32
|
HELPER_MAP = {
|
|
29
33
|
get: 'cache_get',
|
|
30
34
|
set: 'cache_set',
|
|
31
|
-
delete: 'cache_delete'
|
|
35
|
+
delete: 'cache_delete',
|
|
36
|
+
fetch: 'cache_fetch',
|
|
37
|
+
connected?: 'cache_connected?'
|
|
32
38
|
}.freeze
|
|
33
39
|
|
|
34
40
|
# @!method legion_cache_call?(node)
|
|
35
41
|
def_node_matcher :legion_cache_call?, <<~PATTERN
|
|
36
|
-
(send (const (const nil? :Legion) :Cache) {:get :set :delete} ...)
|
|
42
|
+
(send (const (const nil? :Legion) :Cache) {:get :set :delete :fetch :connected?} ...)
|
|
37
43
|
PATTERN
|
|
38
44
|
|
|
39
45
|
def on_send(node)
|
|
@@ -44,8 +50,12 @@ module RuboCop
|
|
|
44
50
|
message = format(MSG, helper: helper, method: method_name)
|
|
45
51
|
|
|
46
52
|
add_offense(node, message: message) do |corrector|
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
if node.arguments.empty?
|
|
54
|
+
corrector.replace(node, helper)
|
|
55
|
+
else
|
|
56
|
+
args_source = node.arguments.map(&:source).join(', ')
|
|
57
|
+
corrector.replace(node, "#{helper}(#{args_source})")
|
|
58
|
+
end
|
|
49
59
|
end
|
|
50
60
|
end
|
|
51
61
|
end
|
|
@@ -4,33 +4,36 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Legion
|
|
6
6
|
module HelperMigration
|
|
7
|
-
# Detects direct calls to `Legion::Crypt
|
|
8
|
-
#
|
|
7
|
+
# Detects direct calls to `Legion::Crypt` methods and suggests using
|
|
8
|
+
# the `vault_*` helpers instead.
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
# # bad
|
|
12
12
|
# Legion::Crypt.get('secret/path')
|
|
13
13
|
# Legion::Crypt.exist?('secret/path')
|
|
14
|
+
# Legion::Crypt.write('secret/path', data)
|
|
14
15
|
#
|
|
15
16
|
# # good
|
|
16
17
|
# vault_get('secret/path')
|
|
17
18
|
# vault_exist?('secret/path')
|
|
19
|
+
# vault_write('secret/path', data)
|
|
18
20
|
class DirectCrypt < RuboCop::Cop::Base
|
|
19
21
|
extend AutoCorrector
|
|
20
22
|
|
|
21
23
|
MSG = 'Use `%<helper>s` instead of `Legion::Crypt.%<method>s`. ' \
|
|
22
24
|
'Include the appropriate Vault/Crypt helper mixin.'
|
|
23
25
|
|
|
24
|
-
RESTRICT_ON_SEND = %i[get exist?].freeze
|
|
26
|
+
RESTRICT_ON_SEND = %i[get exist? write].freeze
|
|
25
27
|
|
|
26
28
|
HELPER_MAP = {
|
|
27
29
|
get: 'vault_get',
|
|
28
|
-
exist?: 'vault_exist?'
|
|
30
|
+
exist?: 'vault_exist?',
|
|
31
|
+
write: 'vault_write'
|
|
29
32
|
}.freeze
|
|
30
33
|
|
|
31
34
|
# @!method legion_crypt_call?(node)
|
|
32
35
|
def_node_matcher :legion_crypt_call?, <<~PATTERN
|
|
33
|
-
(send (const (const nil? :Legion) :Crypt) {:get :exist?} ...)
|
|
36
|
+
(send (const (const nil? :Legion) :Crypt) {:get :exist? :write} ...)
|
|
34
37
|
PATTERN
|
|
35
38
|
|
|
36
39
|
def on_send(node)
|
|
@@ -4,33 +4,42 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Legion
|
|
6
6
|
module HelperMigration
|
|
7
|
-
# Detects direct calls to `Legion::JSON
|
|
8
|
-
#
|
|
7
|
+
# Detects direct calls to `Legion::JSON` methods and suggests using
|
|
8
|
+
# the `json_*` helpers instead.
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
# # bad
|
|
12
12
|
# Legion::JSON.load(str)
|
|
13
13
|
# Legion::JSON.dump(obj)
|
|
14
|
+
# Legion::JSON.parse(str)
|
|
15
|
+
# Legion::JSON.generate(obj)
|
|
16
|
+
# Legion::JSON.pretty_generate(obj)
|
|
14
17
|
#
|
|
15
18
|
# # good
|
|
16
19
|
# json_load(str)
|
|
17
20
|
# json_dump(obj)
|
|
21
|
+
# json_parse(str)
|
|
22
|
+
# json_generate(obj)
|
|
23
|
+
# json_pretty_generate(obj)
|
|
18
24
|
class DirectJson < RuboCop::Cop::Base
|
|
19
25
|
extend AutoCorrector
|
|
20
26
|
|
|
21
27
|
MSG = 'Use `%<helper>s` instead of `Legion::JSON.%<method>s`. ' \
|
|
22
28
|
'Include the appropriate JSON helper mixin.'
|
|
23
29
|
|
|
24
|
-
RESTRICT_ON_SEND = %i[load dump].freeze
|
|
30
|
+
RESTRICT_ON_SEND = %i[load dump parse generate pretty_generate].freeze
|
|
25
31
|
|
|
26
32
|
HELPER_MAP = {
|
|
27
33
|
load: 'json_load',
|
|
28
|
-
dump: 'json_dump'
|
|
34
|
+
dump: 'json_dump',
|
|
35
|
+
parse: 'json_parse',
|
|
36
|
+
generate: 'json_generate',
|
|
37
|
+
pretty_generate: 'json_pretty_generate'
|
|
29
38
|
}.freeze
|
|
30
39
|
|
|
31
40
|
# @!method legion_json_call?(node)
|
|
32
41
|
def_node_matcher :legion_json_call?, <<~PATTERN
|
|
33
|
-
(send (const (const nil? :Legion) :JSON) {:load :dump} ...)
|
|
42
|
+
(send (const (const nil? :Legion) :JSON) {:load :dump :parse :generate :pretty_generate} ...)
|
|
34
43
|
PATTERN
|
|
35
44
|
|
|
36
45
|
def on_send(node)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Legion
|
|
6
|
+
module HelperMigration
|
|
7
|
+
# Detects direct calls to `Legion::Apollo` and `Legion::Apollo::Local`
|
|
8
|
+
# methods and suggests using the `query_knowledge` / `ingest_knowledge`
|
|
9
|
+
# helpers instead.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# # bad
|
|
13
|
+
# Legion::Apollo.query(text: 'search')
|
|
14
|
+
# Legion::Apollo.ingest(content, tags: [:foo])
|
|
15
|
+
# Legion::Apollo::Local.query(text: 'search')
|
|
16
|
+
# Legion::Apollo::Local.ingest(content)
|
|
17
|
+
#
|
|
18
|
+
# # good
|
|
19
|
+
# query_knowledge(text: 'search')
|
|
20
|
+
# ingest_knowledge(content, tags: [:foo])
|
|
21
|
+
# query_knowledge(text: 'search', scope: :local)
|
|
22
|
+
# ingest_knowledge(content, scope: :local)
|
|
23
|
+
class DirectKnowledge < RuboCop::Cop::Base
|
|
24
|
+
extend AutoCorrector
|
|
25
|
+
|
|
26
|
+
MSG = 'Use `%<helper>s` instead of `%<receiver>s.%<method>s`. ' \
|
|
27
|
+
'Include the knowledge helper mixin.'
|
|
28
|
+
|
|
29
|
+
RESTRICT_ON_SEND = %i[query ingest].freeze
|
|
30
|
+
|
|
31
|
+
GLOBAL_MAP = {
|
|
32
|
+
query: 'query_knowledge',
|
|
33
|
+
ingest: 'ingest_knowledge'
|
|
34
|
+
}.freeze
|
|
35
|
+
|
|
36
|
+
# @!method apollo_global_call?(node)
|
|
37
|
+
def_node_matcher :apollo_global_call?, <<~PATTERN
|
|
38
|
+
(send (const (const nil? :Legion) :Apollo) {:query :ingest} ...)
|
|
39
|
+
PATTERN
|
|
40
|
+
|
|
41
|
+
# @!method apollo_local_call?(node)
|
|
42
|
+
def_node_matcher :apollo_local_call?, <<~PATTERN
|
|
43
|
+
(send (const (const (const nil? :Legion) :Apollo) :Local) {:query :ingest} ...)
|
|
44
|
+
PATTERN
|
|
45
|
+
|
|
46
|
+
def on_send(node)
|
|
47
|
+
if apollo_global_call?(node)
|
|
48
|
+
register_global_offense(node)
|
|
49
|
+
elsif apollo_local_call?(node)
|
|
50
|
+
register_local_offense(node)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def register_global_offense(node)
|
|
57
|
+
method_name = node.method_name
|
|
58
|
+
helper = GLOBAL_MAP[method_name]
|
|
59
|
+
message = format(MSG, helper: helper, receiver: 'Legion::Apollo', method: method_name)
|
|
60
|
+
|
|
61
|
+
add_offense(node, message: message) do |corrector|
|
|
62
|
+
args_source = node.arguments.map(&:source).join(', ')
|
|
63
|
+
corrector.replace(node, "#{helper}(#{args_source})")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def register_local_offense(node)
|
|
68
|
+
method_name = node.method_name
|
|
69
|
+
helper = GLOBAL_MAP[method_name]
|
|
70
|
+
message = format(MSG, helper: helper, receiver: 'Legion::Apollo::Local', method: method_name)
|
|
71
|
+
|
|
72
|
+
add_offense(node, message: message) do |corrector|
|
|
73
|
+
args_source = node.arguments.map(&:source).join(', ')
|
|
74
|
+
scope_arg = args_source.empty? ? 'scope: :local' : "#{args_source}, scope: :local"
|
|
75
|
+
corrector.replace(node, "#{helper}(#{scope_arg})")
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Legion
|
|
6
|
+
module HelperMigration
|
|
7
|
+
# Detects direct calls to `Legion::LLM` methods and suggests using
|
|
8
|
+
# the `llm_*` helpers from `Legion::Extensions::Helpers::LLM`.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# # bad
|
|
12
|
+
# Legion::LLM.embed(text)
|
|
13
|
+
# Legion::LLM.chat(message, intent: :moderate)
|
|
14
|
+
# Legion::LLM.ask(message: 'hello')
|
|
15
|
+
# Legion::LLM.structured(messages: [], schema: {})
|
|
16
|
+
# Legion::LLM.embed_batch(texts)
|
|
17
|
+
#
|
|
18
|
+
# # good
|
|
19
|
+
# llm_embed(text)
|
|
20
|
+
# llm_chat(message, intent: :moderate)
|
|
21
|
+
# llm_ask(message: 'hello')
|
|
22
|
+
# llm_structured(messages: [], schema: {})
|
|
23
|
+
# llm_embed_batch(texts)
|
|
24
|
+
class DirectLlm < RuboCop::Cop::Base
|
|
25
|
+
extend AutoCorrector
|
|
26
|
+
|
|
27
|
+
MSG = 'Use `%<helper>s` instead of `Legion::LLM.%<method>s`. ' \
|
|
28
|
+
'Include the LLM helper mixin.'
|
|
29
|
+
|
|
30
|
+
RESTRICT_ON_SEND = %i[embed chat ask structured embed_batch].freeze
|
|
31
|
+
|
|
32
|
+
HELPER_MAP = {
|
|
33
|
+
embed: 'llm_embed',
|
|
34
|
+
chat: 'llm_chat',
|
|
35
|
+
ask: 'llm_ask',
|
|
36
|
+
structured: 'llm_structured',
|
|
37
|
+
embed_batch: 'llm_embed_batch'
|
|
38
|
+
}.freeze
|
|
39
|
+
|
|
40
|
+
# @!method legion_llm_call?(node)
|
|
41
|
+
def_node_matcher :legion_llm_call?, <<~PATTERN
|
|
42
|
+
(send (const (const nil? :Legion) :LLM) {:embed :chat :ask :structured :embed_batch} ...)
|
|
43
|
+
PATTERN
|
|
44
|
+
|
|
45
|
+
def on_send(node)
|
|
46
|
+
return unless legion_llm_call?(node)
|
|
47
|
+
|
|
48
|
+
method_name = node.method_name
|
|
49
|
+
helper = HELPER_MAP[method_name]
|
|
50
|
+
message = format(MSG, helper: helper, method: method_name)
|
|
51
|
+
|
|
52
|
+
add_offense(node, message: message) do |corrector|
|
|
53
|
+
args_source = node.arguments.map(&:source).join(', ')
|
|
54
|
+
corrector.replace(node, "#{helper}(#{args_source})")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -4,33 +4,39 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
module Legion
|
|
6
6
|
module HelperMigration
|
|
7
|
-
# Detects direct calls to `Legion::Cache::Local
|
|
8
|
-
#
|
|
7
|
+
# Detects direct calls to `Legion::Cache::Local` methods and suggests
|
|
8
|
+
# using the `local_cache_*` helpers instead.
|
|
9
9
|
#
|
|
10
10
|
# @example
|
|
11
11
|
# # bad
|
|
12
12
|
# Legion::Cache::Local.get('key')
|
|
13
13
|
# Legion::Cache::Local.set('key', value)
|
|
14
|
+
# Legion::Cache::Local.delete('key')
|
|
15
|
+
# Legion::Cache::Local.fetch('key') { compute }
|
|
14
16
|
#
|
|
15
17
|
# # good
|
|
16
18
|
# local_cache_get('key')
|
|
17
19
|
# local_cache_set('key', value)
|
|
20
|
+
# local_cache_delete('key')
|
|
21
|
+
# local_cache_fetch('key') { compute }
|
|
18
22
|
class DirectLocalCache < RuboCop::Cop::Base
|
|
19
23
|
extend AutoCorrector
|
|
20
24
|
|
|
21
25
|
MSG = 'Use `%<helper>s` instead of `Legion::Cache::Local.%<method>s`. ' \
|
|
22
26
|
'Include the appropriate local cache helper mixin.'
|
|
23
27
|
|
|
24
|
-
RESTRICT_ON_SEND = %i[get set].freeze
|
|
28
|
+
RESTRICT_ON_SEND = %i[get set delete fetch].freeze
|
|
25
29
|
|
|
26
30
|
HELPER_MAP = {
|
|
27
31
|
get: 'local_cache_get',
|
|
28
|
-
set: 'local_cache_set'
|
|
32
|
+
set: 'local_cache_set',
|
|
33
|
+
delete: 'local_cache_delete',
|
|
34
|
+
fetch: 'local_cache_fetch'
|
|
29
35
|
}.freeze
|
|
30
36
|
|
|
31
37
|
# @!method legion_local_cache_call?(node)
|
|
32
38
|
def_node_matcher :legion_local_cache_call?, <<~PATTERN
|
|
33
|
-
(send (const (const (const nil? :Legion) :Cache) :Local) {:get :set} ...)
|
|
39
|
+
(send (const (const (const nil? :Legion) :Cache) :Local) {:get :set :delete :fetch} ...)
|
|
34
40
|
PATTERN
|
|
35
41
|
|
|
36
42
|
def on_send(node)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Legion
|
|
6
|
+
module HelperMigration
|
|
7
|
+
# Detects direct calls to `Legion::Transport::Connection` methods
|
|
8
|
+
# and suggests using the `transport_*` helpers instead.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# # bad
|
|
12
|
+
# Legion::Transport::Connection.session_open?
|
|
13
|
+
# Legion::Transport::Connection.channel_open?
|
|
14
|
+
# Legion::Transport::Connection.lite_mode?
|
|
15
|
+
# Legion::Transport::Connection.channel
|
|
16
|
+
#
|
|
17
|
+
# # good
|
|
18
|
+
# transport_session_open?
|
|
19
|
+
# transport_channel_open?
|
|
20
|
+
# transport_lite_mode?
|
|
21
|
+
# transport_channel
|
|
22
|
+
class DirectTransport < RuboCop::Cop::Base
|
|
23
|
+
extend AutoCorrector
|
|
24
|
+
|
|
25
|
+
MSG = 'Use `%<helper>s` instead of `%<receiver>s.%<method>s`. ' \
|
|
26
|
+
'Include the transport helper mixin.'
|
|
27
|
+
|
|
28
|
+
RESTRICT_ON_SEND = %i[session_open? channel_open? lite_mode? channel count].freeze
|
|
29
|
+
|
|
30
|
+
CONNECTION_MAP = {
|
|
31
|
+
session_open?: 'transport_session_open?',
|
|
32
|
+
channel_open?: 'transport_channel_open?',
|
|
33
|
+
lite_mode?: 'transport_lite_mode?',
|
|
34
|
+
channel: 'transport_channel'
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
SPOOL_MAP = {
|
|
38
|
+
count: 'transport_spool_count'
|
|
39
|
+
}.freeze
|
|
40
|
+
|
|
41
|
+
# @!method transport_connection_call?(node)
|
|
42
|
+
def_node_matcher :transport_connection_call?, <<~PATTERN
|
|
43
|
+
(send (const (const (const nil? :Legion) :Transport) :Connection) {:session_open? :channel_open? :lite_mode? :channel} ...)
|
|
44
|
+
PATTERN
|
|
45
|
+
|
|
46
|
+
# @!method transport_spool_call?(node)
|
|
47
|
+
def_node_matcher :transport_spool_call?, <<~PATTERN
|
|
48
|
+
(send (const (const (const nil? :Legion) :Transport) :Spool) :count ...)
|
|
49
|
+
PATTERN
|
|
50
|
+
|
|
51
|
+
def on_send(node)
|
|
52
|
+
if transport_connection_call?(node)
|
|
53
|
+
register_offense(node, 'Legion::Transport::Connection', CONNECTION_MAP)
|
|
54
|
+
elsif transport_spool_call?(node)
|
|
55
|
+
register_offense(node, 'Legion::Transport::Spool', SPOOL_MAP)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def register_offense(node, receiver, helper_map)
|
|
62
|
+
method_name = node.method_name
|
|
63
|
+
helper = helper_map[method_name]
|
|
64
|
+
message = format(MSG, helper: helper, receiver: receiver, method: method_name)
|
|
65
|
+
|
|
66
|
+
add_offense(node, message: message) do |corrector|
|
|
67
|
+
args_source = node.arguments.map(&:source).join(', ')
|
|
68
|
+
replacement = node.arguments.empty? ? helper : "#{helper}(#{args_source})"
|
|
69
|
+
corrector.replace(node, replacement)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/rubocop-legion.rb
CHANGED
|
@@ -15,7 +15,9 @@ require 'rubocop/cop/legion/helper_migration/direct_local_cache'
|
|
|
15
15
|
require 'rubocop/cop/legion/helper_migration/direct_crypt'
|
|
16
16
|
require 'rubocop/cop/legion/helper_migration/logging_guard'
|
|
17
17
|
require 'rubocop/cop/legion/helper_migration/direct_data'
|
|
18
|
-
require 'rubocop/cop/legion/helper_migration/
|
|
18
|
+
require 'rubocop/cop/legion/helper_migration/direct_llm'
|
|
19
|
+
require 'rubocop/cop/legion/helper_migration/direct_transport'
|
|
20
|
+
require 'rubocop/cop/legion/helper_migration/direct_knowledge'
|
|
19
21
|
require 'rubocop/cop/legion/helper_migration/require_defined_guard'
|
|
20
22
|
require 'rubocop/cop/legion/helper_migration/defined_transport_guard'
|
|
21
23
|
|
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.
|
|
4
|
+
version: 0.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -151,9 +151,11 @@ files:
|
|
|
151
151
|
- lib/rubocop/cop/legion/helper_migration/direct_crypt.rb
|
|
152
152
|
- lib/rubocop/cop/legion/helper_migration/direct_data.rb
|
|
153
153
|
- lib/rubocop/cop/legion/helper_migration/direct_json.rb
|
|
154
|
-
- lib/rubocop/cop/legion/helper_migration/
|
|
154
|
+
- lib/rubocop/cop/legion/helper_migration/direct_knowledge.rb
|
|
155
|
+
- lib/rubocop/cop/legion/helper_migration/direct_llm.rb
|
|
155
156
|
- lib/rubocop/cop/legion/helper_migration/direct_local_cache.rb
|
|
156
157
|
- lib/rubocop/cop/legion/helper_migration/direct_logging.rb
|
|
158
|
+
- lib/rubocop/cop/legion/helper_migration/direct_transport.rb
|
|
157
159
|
- lib/rubocop/cop/legion/helper_migration/logging_guard.rb
|
|
158
160
|
- lib/rubocop/cop/legion/helper_migration/old_logging_methods.rb
|
|
159
161
|
- lib/rubocop/cop/legion/helper_migration/require_defined_guard.rb
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RuboCop
|
|
4
|
-
module Cop
|
|
5
|
-
module Legion
|
|
6
|
-
module HelperMigration
|
|
7
|
-
# Detects direct calls to `Legion::LLM.embed` and suggests using the
|
|
8
|
-
# `llm_embed` helper from `Legion::Extensions::Helpers::LLM`.
|
|
9
|
-
#
|
|
10
|
-
# @example
|
|
11
|
-
# # bad
|
|
12
|
-
# Legion::LLM.embed(text)
|
|
13
|
-
# Legion::LLM.embed(text, provider: :bedrock)
|
|
14
|
-
#
|
|
15
|
-
# # good
|
|
16
|
-
# llm_embed(text)
|
|
17
|
-
# llm_embed(text, provider: :bedrock)
|
|
18
|
-
class DirectLlmEmbed < RuboCop::Cop::Base
|
|
19
|
-
extend AutoCorrector
|
|
20
|
-
|
|
21
|
-
MSG = 'Use `llm_embed` instead of `Legion::LLM.embed`. ' \
|
|
22
|
-
'Include `Legion::Extensions::Helpers::LLM` via the LLM helper mixin.'
|
|
23
|
-
|
|
24
|
-
RESTRICT_ON_SEND = %i[embed].freeze
|
|
25
|
-
|
|
26
|
-
# @!method legion_llm_embed?(node)
|
|
27
|
-
def_node_matcher :legion_llm_embed?, <<~PATTERN
|
|
28
|
-
(send (const (const nil? :Legion) :LLM) :embed ...)
|
|
29
|
-
PATTERN
|
|
30
|
-
|
|
31
|
-
def on_send(node)
|
|
32
|
-
return unless legion_llm_embed?(node)
|
|
33
|
-
|
|
34
|
-
add_offense(node, message: MSG) do |corrector|
|
|
35
|
-
args_source = node.arguments.map(&:source).join(', ')
|
|
36
|
-
corrector.replace(node, "llm_embed(#{args_source})")
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|