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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f841ecd6e5821651ad020bd243791971cf7ab5dca138178d90d216e8a58a48ba
4
- data.tar.gz: acd221dbf9f924e6f81b21569262ea6a8aebbe42d4753356f9750cd3cc0c13a0
3
+ metadata.gz: cd43ed49ee3f7013316b5650cfb288d60fd6e1807532acb1f8978865a39a519e
4
+ data.tar.gz: a620ac1fc4debec154a69eb72a75b5df1c0a2fb8f7974e5a29fbefed46604549
5
5
  SHA512:
6
- metadata.gz: 5933d7f5010bc89b49a95e3d4c0080d752d583fab9a4c11e5fc3a244a0e45938be35eeb6f6851386452d72eca5c135434b6fe1d7dc6cb2a5be163bf7a0213576
7
- data.tar.gz: 62b31e59d175e345383a02764b3c1c32a7599e70af80e31d8f0685730579c5396d9cdd783e19fb16ca18809e43b33cead79b6ad03f444acc77045fe4c2dd6399
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 45 AST-based cops across 6 departments. Uses the new RuboCop Plugin API (1.72+, lint_roller-based) with auto-discovery via gemspec metadata.
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** (28 cops): Scoped to `lib/legion/extensions/**/*.rb` via Include directive — never fire on core `legion-*` libraries
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** (11): `DirectLogging`, `OldLoggingMethods`, `DirectJson`, `DirectCache`, `DirectLocalCache`, `DirectCrypt`, `DirectData`, `DirectLlmEmbed`, `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)`.
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/ # 7 cops (lex-only)
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 # 322 specs
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`) — 29 cops
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 `json_load`/`json_dump` instead of `Legion::JSON` |
95
- | HelperMigration | `DirectCache` | warning | yes | Use `cache_get`/`cache_set` instead of `Legion::Cache` |
96
- | HelperMigration | `DirectLocalCache` | warning | yes | Use `local_cache_get`/`local_cache_set` instead of `Legion::Cache::Local` |
97
- | HelperMigration | `DirectCrypt` | warning | yes | Use `vault_get`/`vault_exist?` instead of `Legion::Crypt` |
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 | `DirectLlmEmbed` | convention | yes | Use `llm_embed` instead of `Legion::LLM.embed` |
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: 45 custom cops** across 6 departments, 19 auto-correctable.
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 `json_load`/`json_dump` helpers instead of `Legion::JSON.load`/`.dump`.'
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 `cache_get`/`cache_set`/`cache_delete` helpers instead of `Legion::Cache` methods.'
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 `local_cache_get`/`local_cache_set` helpers instead of `Legion::Cache::Local` methods.'
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 `vault_get`/`vault_exist?` helpers instead of `Legion::Crypt` methods.'
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/DirectLlmEmbed:
59
- Description: 'Use `llm_embed` helper instead of `Legion::LLM.embed`.'
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.get`, `.set`, and `.delete`
8
- # and suggests using the `cache_get`, `cache_set`, `cache_delete` helpers.
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
- args_source = node.arguments.map(&:source).join(', ')
48
- corrector.replace(node, "#{helper}(#{args_source})")
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.get` and `Legion::Crypt.exist?`
8
- # and suggests using the `vault_get` / `vault_exist?` helpers instead.
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.load` and `Legion::JSON.dump`
8
- # and suggests using the `json_load` / `json_dump` helpers instead.
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.get` and `.set`
8
- # and suggests using the `local_cache_get` / `local_cache_set` helpers.
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Legion
5
- VERSION = '0.1.6'
5
+ VERSION = '0.1.7'
6
6
  end
7
7
  end
@@ -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/direct_llm_embed'
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.6
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/direct_llm_embed.rb
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