type-guessr 0.0.3 → 0.0.5

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: 8ff8e62640844d1f305406b2ecf2c67d139e20aa1710e245b9650ce89f051c2d
4
- data.tar.gz: ce2659a63614befd227cd54e2755dcda8a32dfd88640665b09101d97cc211071
3
+ metadata.gz: 7783e3a53037ee36f81b86f0d78518ad46cdbf84ba63e3de3262114d82773873
4
+ data.tar.gz: 00d1c370e84981d176b78d39a10aeb0b7371ff8e8f4f046bb1cc9e7d7aad0031
5
5
  SHA512:
6
- metadata.gz: b075460f82c3d9a9046e5b2e6ca87173fe84dd62244f240654bea83a7afbb4f1de785d53b2907030b37d6bdd4004a68fda4ca38a2ce4ea1e2720ed5534d30a32
7
- data.tar.gz: 80468b024537670450a638f51cfae739ef1efe68227b89c675f095d9ecf1e57dbf648d65f15526f8cce8b5a9d2b9e74313c5f9dc7da9191e5221a2c4f9f6517b
6
+ metadata.gz: 1a0f3223ed5c77a2601e9649181aea9b2db9d9e977374ccbda3a832cadf61b123b046f040ccd654c49ea1516a928d565543b1b8e80bf5d6ca630e90c29346e66
7
+ data.tar.gz: 749c0256b9402d1885a00dcf3b52f662e77bae6bccdd1d797920af0930bd875605248eb00d9e8a43a47b8626164c28ec161bd3bd72e4fda6392ceb19f58a3c38
@@ -119,7 +119,7 @@ module RubyLsp
119
119
  entries = if @member_index
120
120
  @member_index[pivot.name.to_s] || []
121
121
  else
122
- @index.fuzzy_search(pivot.name.to_s) do |entry|
122
+ @index.fuzzy_search(pivot.name.to_s).select do |entry|
123
123
  entry.is_a?(RubyIndexer::Entry::Member) && entry.name == pivot.name.to_s
124
124
  end
125
125
  end
@@ -202,6 +202,12 @@ module TypeGuessr
202
202
  nested_classes = []
203
203
  if prism_node.body.is_a?(Prism::StatementsNode)
204
204
  prism_node.body.body.each do |stmt|
205
+ if attr_accessor_call?(stmt)
206
+ # attr_reader/attr_accessor/attr_writer DSL → 合成DefNodeを生成
207
+ methods.concat(synthesize_attr_defs(stmt, class_context))
208
+ next
209
+ end
210
+
205
211
  node = convert(stmt, class_context)
206
212
  if node.is_a?(IR::DefNode)
207
213
  methods << node
@@ -217,6 +223,66 @@ module TypeGuessr
217
223
  IR::ClassModuleNode.new(name, methods, [], convert_loc(prism_node.constant_path&.location || prism_node.location))
218
224
  end
219
225
 
226
+ ATTR_DSL_NAMES = %i[attr_reader attr_writer attr_accessor].freeze
227
+ private_constant :ATTR_DSL_NAMES
228
+
229
+ private def attr_accessor_call?(prism_node)
230
+ return false unless prism_node.is_a?(Prism::CallNode)
231
+ return false unless prism_node.receiver.nil?
232
+
233
+ ATTR_DSL_NAMES.include?(prism_node.name)
234
+ end
235
+
236
+ # attr_reader/attr_writer/attr_accessor呼び出しから合成DefNodeを生成する
237
+ # @return [Array<IR::DefNode>]
238
+ private def synthesize_attr_defs(prism_node, context)
239
+ dsl_name = prism_node.name
240
+ args = prism_node.arguments&.arguments || []
241
+
242
+ args.flat_map do |arg|
243
+ attr_name = extract_attr_name(arg)
244
+ next [] unless attr_name
245
+
246
+ loc = convert_loc(arg.location)
247
+ case dsl_name
248
+ when :attr_reader
249
+ [build_reader_def(attr_name, context.current_class_name, loc)]
250
+ when :attr_writer
251
+ [build_writer_def(attr_name, context.current_class_name, loc)]
252
+ when :attr_accessor
253
+ [
254
+ build_reader_def(attr_name, context.current_class_name, loc),
255
+ build_writer_def(attr_name, context.current_class_name, loc),
256
+ ]
257
+ end
258
+ end
259
+ end
260
+
261
+ # 記号/文字列リテラル引数から属性名を取り出す
262
+ # @return [Symbol, nil] シンボルで返す。リテラルでない場合はnil
263
+ private def extract_attr_name(arg)
264
+ case arg
265
+ when Prism::SymbolNode
266
+ arg.value&.to_sym
267
+ when Prism::StringNode
268
+ arg.unescaped.to_sym
269
+ end
270
+ end
271
+
272
+ # attr_readerに対応する合成DefNode (引数なし、@ivarを返す)
273
+ private def build_reader_def(attr_name, class_name, loc)
274
+ ivar_name = :"@#{attr_name}"
275
+ ivar_read = IR::InstanceVariableReadNode.new(ivar_name, class_name, nil, [], loc)
276
+ IR::DefNode.new(attr_name, class_name, [], ivar_read, [ivar_read], [], loc, false)
277
+ end
278
+
279
+ # attr_writerに対応する合成DefNode (name= :引数を返す)
280
+ private def build_writer_def(attr_name, class_name, loc)
281
+ setter_name = :"#{attr_name}="
282
+ param = IR::ParamNode.new(:value, :required, nil, [], loc)
283
+ IR::DefNode.new(setter_name, class_name, [param], param, [param], [], loc, false)
284
+ end
285
+
220
286
  private def convert_singleton_class(prism_node, context)
221
287
  # Create a new context for singleton class scope
222
288
  singleton_context = context.fork(:class)
@@ -669,12 +669,25 @@ module TypeGuessr
669
669
  )
670
670
  end
671
671
 
672
- # Try project class methods first (includes extended module methods)
673
- # Use code_index adapter to find method owner
674
- owner_name = @code_index&.class_method_owner(class_name, node.method.to_s)
672
+ # ConstantName.method is always a class method or module function, so the
673
+ # method's owner must be the receiver's singleton class. Look up the registry
674
+ # directly to avoid depending on ruby-lsp's indexer state for methods we
675
+ # ourselves registered.
676
+ singleton_scope = "#{class_name}::<Class:#{IR.extract_last_name(class_name)}>"
677
+ def_node = @method_registry.lookup(singleton_scope, node.method.to_s)
678
+ if def_node
679
+ return_result = infer(def_node)
680
+ return Result.new(
681
+ return_result.type,
682
+ "#{class_name}.#{node.method} (project)",
683
+ :project
684
+ )
685
+ end
675
686
 
676
- # Early return: project class method found
677
- if owner_name
687
+ # Fall back to code_index for inherited class methods (the method is defined
688
+ # on an ancestor, so its singleton scope differs from the receiver's).
689
+ owner_name = @code_index&.class_method_owner(class_name, node.method.to_s)
690
+ if owner_name && owner_name != singleton_scope
678
691
  def_node = @method_registry.lookup(owner_name, node.method.to_s)
679
692
  if def_node
680
693
  return_result = infer(def_node)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TypeGuessr
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.5"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: type-guessr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - riseshia
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
126
  requirements: []
127
- rubygems_version: 4.0.3
127
+ rubygems_version: 3.6.9
128
128
  specification_version: 4
129
129
  summary: A heuristic type inference tool for Ruby
130
130
  test_files: []