type-guessr 0.0.2 → 0.0.4

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/lib/ruby_lsp/type_guessr/addon.rb +4 -5
  4. data/lib/ruby_lsp/type_guessr/code_index_adapter.rb +18 -1
  5. data/lib/ruby_lsp/type_guessr/{graph_builder.rb → debug_graph_builder.rb} +3 -3
  6. data/lib/ruby_lsp/type_guessr/debug_server.rb +2 -2
  7. data/lib/ruby_lsp/type_guessr/dsl/activerecord_adapter.rb +404 -0
  8. data/lib/ruby_lsp/type_guessr/dsl/ar_schema_watcher.rb +96 -0
  9. data/lib/ruby_lsp/type_guessr/dsl/ar_type_mapper.rb +51 -0
  10. data/lib/ruby_lsp/type_guessr/dsl.rb +3 -0
  11. data/lib/ruby_lsp/type_guessr/dsl_type_registrar.rb +60 -0
  12. data/lib/ruby_lsp/type_guessr/hover.rb +46 -40
  13. data/lib/ruby_lsp/type_guessr/rails_server_addon.rb +83 -0
  14. data/lib/ruby_lsp/type_guessr/runtime_adapter.rb +90 -16
  15. data/lib/type-guessr.rb +2 -13
  16. data/lib/type_guessr/core/cache/gem_signature_cache.rb +3 -2
  17. data/lib/type_guessr/core/cache.rb +5 -0
  18. data/lib/{ruby_lsp/type_guessr → type_guessr/core}/config.rb +2 -2
  19. data/lib/type_guessr/core/converter/call_converter.rb +161 -0
  20. data/lib/type_guessr/core/converter/container_mutation_converter.rb +241 -0
  21. data/lib/type_guessr/core/converter/context.rb +144 -0
  22. data/lib/type_guessr/core/converter/control_flow_converter.rb +425 -0
  23. data/lib/type_guessr/core/converter/definition_converter.rb +312 -0
  24. data/lib/type_guessr/core/converter/literal_converter.rb +217 -0
  25. data/lib/type_guessr/core/converter/prism_converter.rb +9 -1682
  26. data/lib/type_guessr/core/converter/rbs_converter.rb +15 -1
  27. data/lib/type_guessr/core/converter/registration.rb +100 -0
  28. data/lib/type_guessr/core/converter/variable_converter.rb +225 -0
  29. data/lib/type_guessr/core/converter.rb +4 -0
  30. data/lib/type_guessr/core/index.rb +3 -0
  31. data/lib/type_guessr/core/inference/resolver.rb +206 -208
  32. data/lib/type_guessr/core/inference.rb +4 -0
  33. data/lib/type_guessr/core/ir.rb +3 -0
  34. data/lib/type_guessr/core/logger.rb +3 -5
  35. data/lib/type_guessr/core/registry/method_registry.rb +9 -0
  36. data/lib/type_guessr/core/registry/signature_registry.rb +73 -16
  37. data/lib/type_guessr/core/registry.rb +6 -0
  38. data/lib/type_guessr/core/type_serializer.rb +18 -14
  39. data/lib/type_guessr/core/type_simplifier.rb +5 -5
  40. data/lib/type_guessr/core/types.rb +64 -22
  41. data/lib/type_guessr/core.rb +29 -0
  42. data/lib/type_guessr/mcp/server.rb +55 -46
  43. data/lib/type_guessr/mcp/standalone_runtime.rb +70 -110
  44. data/lib/type_guessr/version.rb +1 -1
  45. metadata +24 -4
  46. data/.mcp.json +0 -9
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../type_guessr/core/types"
4
+
5
+ module RubyLsp
6
+ module TypeGuessr
7
+ module Dsl
8
+ # Maps ActiveRecord column type strings to TypeGuessr Types.
9
+ # Pure mapping with no external dependencies.
10
+ # AR-specific: Mongoid provides Ruby types directly in field declarations.
11
+ module ArTypeMapper
12
+ def self.map(ar_type, nullable: true)
13
+ base = case ar_type.to_s
14
+ when "string", "text"
15
+ ::TypeGuessr::Core::Types::ClassInstance.for("String")
16
+ when "integer", "bigint"
17
+ ::TypeGuessr::Core::Types::ClassInstance.for("Integer")
18
+ when "boolean"
19
+ ::TypeGuessr::Core::Types::Union.new([
20
+ ::TypeGuessr::Core::Types::ClassInstance.for("TrueClass"),
21
+ ::TypeGuessr::Core::Types::ClassInstance.for("FalseClass"),
22
+ ])
23
+ when "float"
24
+ ::TypeGuessr::Core::Types::ClassInstance.for("Float")
25
+ when "decimal"
26
+ ::TypeGuessr::Core::Types::ClassInstance.for("BigDecimal")
27
+ when "date"
28
+ ::TypeGuessr::Core::Types::ClassInstance.for("Date")
29
+ when "datetime", "timestamp"
30
+ ::TypeGuessr::Core::Types::ClassInstance.for("ActiveSupport::TimeWithZone")
31
+ when "json", "jsonb"
32
+ ::TypeGuessr::Core::Types::ClassInstance.for("Hash")
33
+ else
34
+ ::TypeGuessr::Core::Types::Unknown.instance
35
+ end
36
+
37
+ if nullable && !base.is_a?(::TypeGuessr::Core::Types::Unknown)
38
+ nil_type = ::TypeGuessr::Core::Types::ClassInstance.for("NilClass")
39
+ if base.is_a?(::TypeGuessr::Core::Types::Union)
40
+ ::TypeGuessr::Core::Types::Union.new(base.types + [nil_type])
41
+ else
42
+ ::TypeGuessr::Core::Types::Union.new([base, nil_type])
43
+ end
44
+ else
45
+ base
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "dsl/activerecord_adapter"
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "dsl"
4
+
5
+ module RubyLsp
6
+ module TypeGuessr
7
+ # Pure orchestrator for DSL type registration.
8
+ # No framework logic, no cache logic — delegates everything to Adapters.
9
+ class DslTypeRegistrar
10
+ def initialize(signature_registry:, code_index:, project_root:, adapters: nil)
11
+ @signature_registry = signature_registry
12
+ @code_index = code_index
13
+ @project_root = project_root
14
+ @adapters = adapters || default_adapters
15
+ @base_registered = false
16
+ @log_callback = nil
17
+ end
18
+
19
+ def on_log(&block)
20
+ @log_callback = block
21
+ active_adapters.each { |a| a.on_log(&block) }
22
+ end
23
+
24
+ def register_all(runner_client: nil)
25
+ unless @base_registered
26
+ active_adapters.each { |a| a.register_base_methods(signature_registry: @signature_registry) }
27
+ @base_registered = true
28
+ end
29
+
30
+ active_adapters.each do |adapter|
31
+ adapter.register_models(
32
+ runner_client: runner_client,
33
+ signature_registry: @signature_registry,
34
+ code_index: @code_index
35
+ )
36
+ end
37
+ end
38
+
39
+ def check_and_refresh(runner_client: nil)
40
+ active_adapters.each do |adapter|
41
+ next unless adapter.changed?
42
+
43
+ adapter.refresh(
44
+ runner_client: runner_client,
45
+ signature_registry: @signature_registry,
46
+ code_index: @code_index
47
+ )
48
+ end
49
+ end
50
+
51
+ private def active_adapters
52
+ @adapters.select(&:applicable?)
53
+ end
54
+
55
+ private def default_adapters
56
+ [Dsl::ActiveRecordAdapter.new(project_root: @project_root)]
57
+ end
58
+ end
59
+ end
60
+ end
@@ -121,49 +121,55 @@ module RubyLsp
121
121
  class_name = extract_class_name(receiver_type)
122
122
 
123
123
  if class_name
124
- # Try to find DefNode first (for project methods)
125
- # Use the same inference logic as DefNode hover
126
- unless receiver_type.is_a?(Types::SingletonType)
127
- def_node = @runtime_adapter.lookup_method(class_name, call_node.method.to_s)
128
- if def_node
129
- add_def_node_hover(def_node)
130
- return
124
+ method_name_str = call_node.method.to_s
125
+ skip_stdlib_rbs = if receiver_type.is_a?(Types::SingletonType)
126
+ @runtime_adapter.skip_stdlib_rbs_class_method?(class_name, method_name_str)
127
+ else
128
+ @runtime_adapter.skip_stdlib_rbs_method?(class_name, method_name_str)
129
+ end
130
+
131
+ # Methods marked skip_stdlib_rbs skip DefNode + RBS → go straight to fallback (resolver)
132
+ unless skip_stdlib_rbs
133
+ # Try to find DefNode first (for project methods)
134
+ unless receiver_type.is_a?(Types::SingletonType)
135
+ def_node = @runtime_adapter.lookup_method(class_name, method_name_str)
136
+ if def_node
137
+ add_def_node_hover(def_node)
138
+ return
139
+ end
131
140
  end
132
- end
133
141
 
134
- # Fall back to RBS signature lookup (for stdlib/gems)
135
- # Use class method lookup for SingletonType (e.g., RBS::Environment.from_loader)
136
- # RuntimeAdapter resolves the actual method owner (e.g., Object for #tap)
137
- rbs_result = if receiver_type.is_a?(Types::SingletonType)
138
- @runtime_adapter.get_rbs_class_method_signatures(
139
- class_name, call_node.method.to_s
140
- )
141
- else
142
- @runtime_adapter.get_rbs_method_signatures(
143
- class_name, call_node.method.to_s
144
- )
145
- end
146
-
147
- signatures = rbs_result[:signatures]
148
- owner = rbs_result[:owner]
149
-
150
- if signatures.any?
151
- # Format the signature(s)
152
- sig_strs = signatures.map { |sig| sig.method_type.to_s }
153
- content = "**Guessed Signature:** `#{sig_strs.first}`"
154
-
155
- if debug_enabled?
156
- content += "\n\n**[TypeGuessr Debug]**"
157
- content += "\n\n**Receiver:** `#{receiver_type}`"
158
- content += "\n\n**Defined in:** `#{owner}`" if owner != class_name
159
- if sig_strs.size > 1
160
- content += "\n\n**Overloads:**\n"
161
- sig_strs.each { |s| content += "- `#{s}`\n" }
142
+ # Fall back to RBS signature lookup (for stdlib/gems)
143
+ rbs_result = if receiver_type.is_a?(Types::SingletonType)
144
+ @runtime_adapter.get_rbs_class_method_signatures(
145
+ class_name, method_name_str
146
+ )
147
+ else
148
+ @runtime_adapter.get_rbs_method_signatures(
149
+ class_name, method_name_str
150
+ )
151
+ end
152
+
153
+ signatures = rbs_result[:signatures]
154
+ owner = rbs_result[:owner]
155
+
156
+ if signatures.any?
157
+ sig_strs = signatures.map { |sig| sig.method_type.to_s }
158
+ content = "**Guessed Signature:** `#{sig_strs.first}`"
159
+
160
+ if debug_enabled?
161
+ content += "\n\n**[TypeGuessr Debug]**"
162
+ content += "\n\n**Receiver:** `#{receiver_type}`"
163
+ content += "\n\n**Defined in:** `#{owner}`" if owner != class_name
164
+ if sig_strs.size > 1
165
+ content += "\n\n**Overloads:**\n"
166
+ sig_strs.each { |s| content += "- `#{s}`\n" }
167
+ end
162
168
  end
163
- end
164
169
 
165
- @response_builder.push(content, category: :documentation)
166
- return
170
+ @response_builder.push(content, category: :documentation)
171
+ return
172
+ end
167
173
  end
168
174
  end
169
175
  end
@@ -354,7 +360,7 @@ module RubyLsp
354
360
  end
355
361
 
356
362
  private def debug_enabled?
357
- Config.debug?
363
+ ::TypeGuessr::Core::Config.debug?
358
364
  end
359
365
 
360
366
  private def build_debug_info(result, ir_node = nil)
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is loaded in the Rails runner process (not the LSP server)
4
+ # via RunnerClient.register_server_addon.
5
+ # RubyLsp::Rails::ServerAddon is already defined when this file is required.
6
+
7
+ module RubyLsp
8
+ module TypeGuessr
9
+ # ServerAddon that runs inside the Rails runner process.
10
+ # Queries ActiveRecord runtime for model metadata (columns, enums, associations, scopes).
11
+ class RailsServerAddon < ::RubyLsp::Rails::ServerAddon
12
+ def name
13
+ "TypeGuessr"
14
+ end
15
+
16
+ def execute(request, params)
17
+ case request
18
+ when "model_metadata"
19
+ handle_model_metadata(params)
20
+ end
21
+ end
22
+
23
+ private def handle_model_metadata(params)
24
+ class_name = params[:name]
25
+ klass = class_name.constantize
26
+
27
+ return send_error_response("#{class_name} is not an ActiveRecord model") unless active_record_model?(klass)
28
+
29
+ send_result({
30
+ columns: extract_columns(klass),
31
+ enums: extract_enums(klass),
32
+ associations: extract_associations(klass),
33
+ scopes: extract_scopes(klass)
34
+ })
35
+ rescue NameError
36
+ send_error_response("#{class_name} is not a valid class")
37
+ rescue StandardError => e
38
+ send_error_response("#{e.class}: #{e.message}")
39
+ end
40
+
41
+ private def active_record_model?(klass)
42
+ klass < ::ActiveRecord::Base
43
+ rescue StandardError
44
+ false
45
+ end
46
+
47
+ private def extract_columns(klass)
48
+ klass.columns.map do |col|
49
+ [col.name, col.type.to_s, col.null]
50
+ end
51
+ end
52
+
53
+ private def extract_enums(klass)
54
+ return {} unless klass.respond_to?(:defined_enums)
55
+
56
+ klass.defined_enums
57
+ end
58
+
59
+ private def extract_associations(klass)
60
+ klass.reflect_on_all_associations.map do |assoc|
61
+ {
62
+ name: assoc.name.to_s,
63
+ macro: assoc.macro.to_s,
64
+ class_name: assoc.class_name
65
+ }
66
+ end
67
+ rescue StandardError
68
+ []
69
+ end
70
+
71
+ private def extract_scopes(klass)
72
+ enum_values = klass.respond_to?(:defined_enums) ? klass.defined_enums.values.flat_map(&:keys) : []
73
+ exclude = Set.new(enum_values + enum_values.map { |v| "not_#{v}" })
74
+
75
+ klass.singleton_methods(false)
76
+ .map(&:to_s)
77
+ .reject { |m| exclude.include?(m) || m.start_with?("find_by_", "create_", "build_") }
78
+ rescue StandardError
79
+ []
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,19 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "prism"
4
- require_relative "../../type_guessr/core/converter/prism_converter"
5
- require_relative "../../type_guessr/core/index/location_index"
6
- require_relative "../../type_guessr/core/registry/method_registry"
7
- require_relative "../../type_guessr/core/registry/instance_variable_registry"
8
- require_relative "../../type_guessr/core/registry/class_variable_registry"
9
- require_relative "../../type_guessr/core/registry/signature_registry"
10
- require_relative "../../type_guessr/core/inference/resolver"
11
- require_relative "../../type_guessr/core/signature_builder"
12
- require_relative "../../type_guessr/core/type_simplifier"
13
- require_relative "../../type_guessr/core/node_context_helper"
14
- require_relative "../../type_guessr/core/cache/gem_signature_cache"
15
- require_relative "../../type_guessr/core/cache/gem_dependency_resolver"
16
- require_relative "../../type_guessr/core/cache/gem_signature_extractor"
4
+ require_relative "../../type_guessr/core"
5
+ require_relative "dsl_type_registrar"
17
6
  require_relative "code_index_adapter"
18
7
  require_relative "type_inferrer"
19
8
 
@@ -29,7 +18,6 @@ module RubyLsp
29
18
  @message_queue = message_queue
30
19
  @converter = ::TypeGuessr::Core::Converter::PrismConverter.new
31
20
  @location_index = ::TypeGuessr::Core::Index::LocationIndex.new
32
- @signature_registry = ::TypeGuessr::Core::Registry::SignatureRegistry.instance
33
21
  @indexing_completed = false
34
22
  @mutex = Mutex.new
35
23
  @original_type_inferrer = nil
@@ -37,6 +25,10 @@ module RubyLsp
37
25
  # Create CodeIndexAdapter wrapping RubyIndexer
38
26
  @code_index = CodeIndexAdapter.new(global_state&.index)
39
27
 
28
+ # Create SignatureRegistry with code_index for ancestor chain traversal
29
+ @signature_registry = ::TypeGuessr::Core::Registry::SignatureRegistry.new(code_index: @code_index)
30
+ ::TypeGuessr::Core::Registry::SignatureRegistry.instance = @signature_registry
31
+
40
32
  # Create method registry with code_index for inheritance lookup
41
33
  @method_registry = ::TypeGuessr::Core::Registry::MethodRegistry.new(
42
34
  code_index: @code_index
@@ -211,6 +203,19 @@ module RubyLsp
211
203
  end
212
204
  end
213
205
 
206
+ # Check if a method should skip stdlib/gem RBS lookup in hover.
207
+ # Returns true for entries registered by DSL adapters (e.g., AR column accessor)
208
+ # so that hover goes directly to the resolver fallback instead of showing RBS signatures.
209
+ def skip_stdlib_rbs_method?(class_name, method_name)
210
+ entry = @signature_registry.lookup(class_name, method_name)
211
+ entry.is_a?(::TypeGuessr::Core::Registry::SignatureRegistry::GemMethodEntry) && entry.skip_stdlib_rbs?
212
+ end
213
+
214
+ def skip_stdlib_rbs_class_method?(class_name, method_name)
215
+ entry = @signature_registry.lookup_class_method(class_name, method_name)
216
+ entry.is_a?(::TypeGuessr::Core::Registry::SignatureRegistry::GemMethodEntry) && entry.skip_stdlib_rbs?
217
+ end
218
+
214
219
  # Start background indexing of all project files
215
220
  def start_indexing
216
221
  Thread.new do
@@ -248,10 +253,19 @@ module RubyLsp
248
253
  # Connect on-demand inference callback for Unguessed gem methods
249
254
  @signature_registry.on_demand_inferrer = method(:infer_gem_file_on_demand)
250
255
 
256
+ # Register DSL types (AR column accessors, enums, associations, scopes)
257
+ register_dsl_types
258
+
251
259
  @indexing_completed = true
252
260
 
261
+ # Start schema watch loop for auto-refresh
262
+ start_schema_watch_loop
263
+
253
264
  # Background inference: fully infer gems that have Unguessed entries (opt-in)
254
- background_infer_gems(result[:unguessed_gems], result[:cache]) if Config.background_gem_indexing? && result && result[:unguessed_gems].any?
265
+ if ::TypeGuessr::Core::Config.background_gem_indexing? && result && result[:unguessed_gems].any?
266
+ background_infer_gems(result[:unguessed_gems],
267
+ result[:cache])
268
+ end
255
269
  rescue StandardError => e
256
270
  log_message("Error during file indexing: #{e.message}\n#{e.backtrace.first(10).join("\n")}")
257
271
  @indexing_completed = true
@@ -444,7 +458,7 @@ module RubyLsp
444
458
  method_registry: temp_method_registry,
445
459
  location_index: temp_location_index
446
460
  )
447
- timeout = Config.gem_inference_timeout
461
+ timeout = ::TypeGuessr::Core::Config.gem_inference_timeout
448
462
  signatures = extractor.extract(files, timeout: timeout)
449
463
 
450
464
  t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -754,6 +768,66 @@ module RubyLsp
754
768
  log_message("Index stabilized at #{previous_count} entries.")
755
769
  end
756
770
 
771
+ private def discover_runner_client
772
+ rails_addon = ::RubyLsp::Addon.get("Ruby LSP Rails", ">= 0.4.0", "< 0.5.0")
773
+ rails_addon.rails_runner_client
774
+ rescue ::RubyLsp::Addon::AddonNotFoundError, ::RubyLsp::Addon::IncompatibleApiError
775
+ nil
776
+ rescue StandardError => e
777
+ log_message("Failed to discover RunnerClient: #{e.message}")
778
+ nil
779
+ end
780
+
781
+ private def register_dsl_types
782
+ workspace_path = @global_state.workspace_path
783
+ return unless workspace_path
784
+
785
+ @dsl_registrar = DslTypeRegistrar.new(
786
+ signature_registry: @signature_registry,
787
+ code_index: @code_index,
788
+ project_root: workspace_path
789
+ )
790
+ @dsl_registrar.on_log { |msg| log_message("[DSL] #{msg}") }
791
+
792
+ runner_client = wait_for_runner_client
793
+ @dsl_registrar.register_all(runner_client: runner_client)
794
+ rescue StandardError => e
795
+ log_message("DSL type registration failed: #{e.message}\n#{e.backtrace.first(3).join("\n")}")
796
+ end
797
+
798
+ # Wait for ruby-lsp-rails RunnerClient to transition from NullClient.
799
+ # 3s interval × max 10 attempts = max 30s.
800
+ private def wait_for_runner_client
801
+ log_message("[DSL] Waiting for RunnerClient...")
802
+ max_attempts = 10
803
+
804
+ max_attempts.times do |_i|
805
+ client = discover_runner_client
806
+ if client.respond_to?(:connected?) && client.connected?
807
+ log_message("[DSL] RunnerClient ready (#{client.class})")
808
+ return client
809
+ end
810
+
811
+ sleep(3)
812
+ end
813
+
814
+ log_message("[DSL] RunnerClient timeout after #{max_attempts} attempts")
815
+ nil
816
+ end
817
+
818
+ private def start_schema_watch_loop
819
+ return unless @dsl_registrar
820
+
821
+ Thread.new do
822
+ loop do
823
+ sleep(45)
824
+ @dsl_registrar.check_and_refresh(runner_client: discover_runner_client)
825
+ rescue StandardError => e
826
+ log_message("Schema watch error: #{e.message}")
827
+ end
828
+ end
829
+ end
830
+
757
831
  private def log_message(message)
758
832
  return unless @message_queue
759
833
  return if @message_queue.closed?
data/lib/type-guessr.rb CHANGED
@@ -8,23 +8,12 @@ end
8
8
  # Load version
9
9
  require_relative "type_guessr/version"
10
10
 
11
- # Load core components (IR-based architecture)
12
- require_relative "type_guessr/core/types"
13
- require_relative "type_guessr/core/node_key_generator"
14
- require_relative "type_guessr/core/node_context_helper"
15
- require_relative "type_guessr/core/ir/nodes"
16
- require_relative "type_guessr/core/index/location_index"
17
- require_relative "type_guessr/core/converter/prism_converter"
18
- require_relative "type_guessr/core/converter/rbs_converter"
19
- require_relative "type_guessr/core/inference/result"
20
- require_relative "type_guessr/core/inference/resolver"
21
- require_relative "type_guessr/core/registry/signature_registry"
22
- require_relative "type_guessr/core/logger"
11
+ # Load core components
12
+ require_relative "type_guessr/core"
23
13
 
24
14
  # Load Ruby LSP integration
25
15
  # NOTE: addon.rb is NOT required here - it's auto-discovered by Ruby LSP
26
16
  # Requiring it here would cause double activation
27
- require_relative "ruby_lsp/type_guessr/config"
28
17
  require_relative "ruby_lsp/type_guessr/constants"
29
18
  require_relative "ruby_lsp/type_guessr/runtime_adapter"
30
19
  require_relative "ruby_lsp/type_guessr/hover"
@@ -3,6 +3,7 @@
3
3
  require "json"
4
4
  require "digest/sha2"
5
5
  require "fileutils"
6
+ require_relative "../../version"
6
7
 
7
8
  module TypeGuessr
8
9
  module Core
@@ -11,7 +12,7 @@ module TypeGuessr
11
12
  # Cache key = gem name + version + hash of transitive dependencies.
12
13
  # Files stored at: ~/.cache/type-guessr/gem-signatures/{name}-{version}-{dep_hash}.json
13
14
  class GemSignatureCache
14
- CACHE_FORMAT_VERSION = 1
15
+ CACHE_FORMAT_VERSION = 2
15
16
 
16
17
  # @param cache_dir [String, nil] Override cache directory (for testing)
17
18
  def initialize(cache_dir: nil)
@@ -79,7 +80,7 @@ module TypeGuessr
79
80
 
80
81
  private def default_cache_dir
81
82
  xdg_cache = ENV.fetch("XDG_CACHE_HOME", File.join(Dir.home, ".cache"))
82
- File.join(xdg_cache, "type-guessr", "gem-signatures")
83
+ File.join(xdg_cache, "type-guessr", "gem-signatures", TypeGuessr::VERSION)
83
84
  end
84
85
 
85
86
  private def cache_path(gem_name, gem_version, transitive_deps)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cache/gem_signature_cache"
4
+ require_relative "cache/gem_dependency_resolver"
5
+ require_relative "cache/gem_signature_extractor"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RubyLsp
4
- module TypeGuessr
3
+ module TypeGuessr
4
+ module Core
5
5
  # Loads TypeGuessr settings from .type-guessr.yml in the current working directory.
6
6
  #
7
7
  # Defaults: