rucoa 0.10.0 → 0.11.0
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/.rubocop.yml +3 -0
- data/Gemfile.lock +2 -2
- data/data/definitions_ruby_3_1 +6594 -6594
- data/lib/rucoa/definition_store.rb +141 -29
- data/lib/rucoa/definitions/module_definition.rb +14 -0
- data/lib/rucoa/node_inspector.rb +12 -1
- data/lib/rucoa/rbs/class_definition_mapper.rb +1 -0
- data/lib/rucoa/rbs/module_definition_mapper.rb +12 -7
- data/lib/rucoa/server.rb +1 -1
- data/lib/rucoa/version.rb +1 -1
- data/lib/rucoa/yard/definition_generators/attribute_reader_definition_generator.rb +17 -1
- data/lib/rucoa/yard/definition_generators/attribute_writer_definition_generator.rb +17 -1
- data/lib/rucoa/yard/definition_generators/class_definition_generator.rb +1 -0
- data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +13 -0
- data/lib/rucoa/yard/definition_generators/module_definition_generator.rb +6 -0
- metadata +2 -2
@@ -180,16 +180,76 @@ module Rucoa
|
|
180
180
|
|
181
181
|
# @param type [String]
|
182
182
|
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
183
|
-
# @example
|
183
|
+
# @example supports simple instance method
|
184
|
+
# source = Rucoa::Source.new(
|
185
|
+
# content: <<~RUBY,
|
186
|
+
# class A
|
187
|
+
# def foo
|
188
|
+
# end
|
189
|
+
# end
|
190
|
+
# RUBY
|
191
|
+
# uri: 'file:///path/to/example.rb'
|
192
|
+
# )
|
193
|
+
# definition_store = Rucoa::DefinitionStore.new
|
194
|
+
# definition_store.update_from(source)
|
195
|
+
# subject = definition_store.instance_method_definitions_of('A')
|
196
|
+
# expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
|
197
|
+
# @example supports inheritance
|
198
|
+
# source = Rucoa::Source.new(
|
199
|
+
# content: <<~RUBY,
|
200
|
+
# class A
|
201
|
+
# def foo
|
202
|
+
# end
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# class B < A
|
206
|
+
# end
|
207
|
+
# RUBY
|
208
|
+
# uri: 'file:///path/to/example.rb'
|
209
|
+
# )
|
210
|
+
# definition_store = Rucoa::DefinitionStore.new
|
211
|
+
# definition_store.update_from(source)
|
212
|
+
# subject = definition_store.instance_method_definitions_of('B')
|
213
|
+
# expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
|
214
|
+
# @example supports `include`
|
215
|
+
# source = Rucoa::Source.new(
|
216
|
+
# content: <<~RUBY,
|
217
|
+
# module A
|
218
|
+
# def foo
|
219
|
+
# end
|
220
|
+
# end
|
221
|
+
#
|
222
|
+
# class B
|
223
|
+
# include A
|
224
|
+
# end
|
225
|
+
# RUBY
|
226
|
+
# uri: 'file:///path/to/example.rb'
|
227
|
+
# )
|
184
228
|
# definition_store = Rucoa::DefinitionStore.new
|
185
|
-
# definition_store.
|
186
|
-
# subject = definition_store.instance_method_definitions_of('
|
187
|
-
# expect(subject.map(&:qualified_name)).to
|
188
|
-
# @example
|
229
|
+
# definition_store.update_from(source)
|
230
|
+
# subject = definition_store.instance_method_definitions_of('B')
|
231
|
+
# expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
|
232
|
+
# @example supports `prepend`
|
233
|
+
# source = Rucoa::Source.new(
|
234
|
+
# content: <<~RUBY,
|
235
|
+
# module A
|
236
|
+
# def foo
|
237
|
+
# end
|
238
|
+
# end
|
239
|
+
#
|
240
|
+
# class B
|
241
|
+
# prepend A
|
242
|
+
#
|
243
|
+
# def foo
|
244
|
+
# end
|
245
|
+
# end
|
246
|
+
# RUBY
|
247
|
+
# uri: 'file:///path/to/example.rb'
|
248
|
+
# )
|
189
249
|
# definition_store = Rucoa::DefinitionStore.new
|
190
|
-
# definition_store.
|
191
|
-
# subject = definition_store.instance_method_definitions_of('
|
192
|
-
# expect(subject.map(&:qualified_name)).to
|
250
|
+
# definition_store.update_from(source)
|
251
|
+
# subject = definition_store.instance_method_definitions_of('B')
|
252
|
+
# expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
|
193
253
|
def instance_method_definitions_of(type)
|
194
254
|
singleton_class_name = singleton_class_name_from(type)
|
195
255
|
return singleton_method_definitions_of(singleton_class_name) if singleton_class_name
|
@@ -197,31 +257,87 @@ module Rucoa
|
|
197
257
|
class_or_module_definition = find_definition_by_qualified_name(type)
|
198
258
|
return [] unless class_or_module_definition
|
199
259
|
|
200
|
-
method_definitions =
|
260
|
+
method_definitions = self.method_definitions
|
201
261
|
ancestors_of(class_or_module_definition).flat_map do |ancestor|
|
202
262
|
method_definitions.select do |method_definition|
|
203
|
-
method_definition.namespace == ancestor.qualified_name
|
263
|
+
method_definition.namespace == ancestor.qualified_name &&
|
264
|
+
method_definition.instance_method?
|
204
265
|
end
|
205
|
-
end
|
266
|
+
end.uniq(&:method_name)
|
206
267
|
end
|
207
268
|
|
208
269
|
# @param type [String]
|
209
270
|
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
210
|
-
# @example
|
271
|
+
# @example supports simple singleton method
|
272
|
+
# source = Rucoa::Source.new(
|
273
|
+
# content: <<~RUBY,
|
274
|
+
# class A
|
275
|
+
# def self.foo
|
276
|
+
# end
|
277
|
+
# end
|
278
|
+
# RUBY
|
279
|
+
# uri: 'file:///path/to/example.rb'
|
280
|
+
# )
|
281
|
+
# definition_store = Rucoa::DefinitionStore.new
|
282
|
+
# definition_store.update_from(source)
|
283
|
+
# subject = definition_store.singleton_method_definitions_of('A')
|
284
|
+
# expect(subject.map(&:qualified_name)).to include('A.foo')
|
285
|
+
# @example supports super class's singleton method
|
286
|
+
# source = Rucoa::Source.new(
|
287
|
+
# content: <<~RUBY,
|
288
|
+
# class A
|
289
|
+
# def self.foo
|
290
|
+
# end
|
291
|
+
# end
|
292
|
+
#
|
293
|
+
# class B < A
|
294
|
+
# end
|
295
|
+
# RUBY
|
296
|
+
# uri: 'file:///path/to/example.rb'
|
297
|
+
# )
|
298
|
+
# definition_store = Rucoa::DefinitionStore.new
|
299
|
+
# definition_store.update_from(source)
|
300
|
+
# subject = definition_store.singleton_method_definitions_of('B')
|
301
|
+
# expect(subject.map(&:qualified_name)).to include('A.foo')
|
302
|
+
# @example supports extended module's instance method
|
303
|
+
# source = Rucoa::Source.new(
|
304
|
+
# content: <<~RUBY,
|
305
|
+
# module A
|
306
|
+
# def foo
|
307
|
+
# end
|
308
|
+
# end
|
309
|
+
#
|
310
|
+
# class B
|
311
|
+
# def self.foo
|
312
|
+
# end
|
313
|
+
# end
|
314
|
+
#
|
315
|
+
# class C < B
|
316
|
+
# extend A
|
317
|
+
# end
|
318
|
+
# RUBY
|
319
|
+
# uri: 'file:///path/to/example.rb'
|
320
|
+
# )
|
211
321
|
# definition_store = Rucoa::DefinitionStore.new
|
212
|
-
# definition_store.
|
213
|
-
# subject = definition_store.singleton_method_definitions_of('
|
214
|
-
# expect(subject.map(&:qualified_name)).to
|
322
|
+
# definition_store.update_from(source)
|
323
|
+
# subject = definition_store.singleton_method_definitions_of('C')
|
324
|
+
# expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
|
215
325
|
def singleton_method_definitions_of(type)
|
216
326
|
class_or_module_definition = find_definition_by_qualified_name(type)
|
217
327
|
return [] unless class_or_module_definition
|
218
328
|
|
219
|
-
method_definitions =
|
329
|
+
method_definitions = self.method_definitions
|
220
330
|
ancestors_of(class_or_module_definition).flat_map do |ancestor|
|
221
331
|
method_definitions.select do |method_definition|
|
222
|
-
method_definition.namespace == ancestor.qualified_name
|
332
|
+
method_definition.namespace == ancestor.qualified_name &&
|
333
|
+
method_definition.singleton_method?
|
334
|
+
end + ancestor.extended_module_qualified_names.flat_map do |extended_module_qualified_name|
|
335
|
+
method_definitions.select do |method_definition|
|
336
|
+
method_definition.namespace == extended_module_qualified_name &&
|
337
|
+
method_definition.instance_method?
|
338
|
+
end
|
223
339
|
end
|
224
|
-
end
|
340
|
+
end.uniq(&:method_name)
|
225
341
|
end
|
226
342
|
|
227
343
|
# @param namespace [String]
|
@@ -232,6 +348,7 @@ module Rucoa
|
|
232
348
|
end
|
233
349
|
end
|
234
350
|
|
351
|
+
# @todo Search ancestors.
|
235
352
|
# @param unqualified_name [Rucoa::UnqualifiedName]
|
236
353
|
# @return [String]
|
237
354
|
def resolve_constant(unqualified_name)
|
@@ -258,7 +375,7 @@ module Rucoa
|
|
258
375
|
# @param type [String]
|
259
376
|
# @return [String, nil]
|
260
377
|
def singleton_class_name_from(type)
|
261
|
-
type[/singleton<(\w+)>/, 1]
|
378
|
+
type[/singleton<([\w:]+)>/, 1]
|
262
379
|
end
|
263
380
|
|
264
381
|
# @param definition [Rucoa::Definitions::Class, Rucoa::Definitions::Module]
|
@@ -311,16 +428,6 @@ module Rucoa
|
|
311
428
|
definitions.grep(Definitions::MethodDefinition)
|
312
429
|
end
|
313
430
|
|
314
|
-
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
315
|
-
def instance_method_definitions
|
316
|
-
method_definitions.select(&:instance_method?)
|
317
|
-
end
|
318
|
-
|
319
|
-
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
320
|
-
def singleton_method_definitions
|
321
|
-
method_definitions.select(&:singleton_method?)
|
322
|
-
end
|
323
|
-
|
324
431
|
# @return [Array<Rucoa::Definition::ConstantDefinition>]
|
325
432
|
def constant_definitions
|
326
433
|
definitions.grep(Definitions::ConstantDefinition)
|
@@ -348,6 +455,11 @@ module Rucoa
|
|
348
455
|
definition.super_class_qualified_name = resolve_constant(definition.super_class_unqualified_name)
|
349
456
|
definition.super_class_unqualified_name = nil
|
350
457
|
|
458
|
+
definition.extended_module_qualified_names = definition.extended_module_unqualified_names.map do |unqualified_name|
|
459
|
+
resolve_constant(unqualified_name)
|
460
|
+
end
|
461
|
+
definition.extended_module_unqualified_names = []
|
462
|
+
|
351
463
|
definition.included_module_qualified_names = definition.included_module_unqualified_names.map do |unqualified_name|
|
352
464
|
resolve_constant(unqualified_name)
|
353
465
|
end
|
@@ -3,6 +3,12 @@
|
|
3
3
|
module Rucoa
|
4
4
|
module Definitions
|
5
5
|
class ModuleDefinition < ConstantDefinition
|
6
|
+
# @return [Array<String>]
|
7
|
+
attr_accessor :extended_module_qualified_names
|
8
|
+
|
9
|
+
# @return [Array<Rucoa::UnqualifiedName>]
|
10
|
+
attr_accessor :extended_module_unqualified_names
|
11
|
+
|
6
12
|
# @return [Array<String>]
|
7
13
|
attr_accessor :included_module_qualified_names
|
8
14
|
|
@@ -15,11 +21,15 @@ module Rucoa
|
|
15
21
|
# @return [Array<Rucoa::UnqualifiedName>]
|
16
22
|
attr_accessor :prepended_module_unqualified_names
|
17
23
|
|
24
|
+
# @param extended_module_qualified_names [Array<String>]
|
25
|
+
# @param extended_module_unqualified_names [Array<String>]
|
18
26
|
# @param included_module_qualified_names [Array<String>]
|
19
27
|
# @param included_module_unqualified_names [Array<String>]
|
20
28
|
# @param prepended_module_qualified_names [Array<String>]
|
21
29
|
# @param prepended_module_unqualified_names [Array<String>]
|
22
30
|
def initialize(
|
31
|
+
extended_module_qualified_names: [],
|
32
|
+
extended_module_unqualified_names: [],
|
23
33
|
included_module_qualified_names: [],
|
24
34
|
included_module_unqualified_names: [],
|
25
35
|
prepended_module_qualified_names: [],
|
@@ -27,6 +37,8 @@ module Rucoa
|
|
27
37
|
**keyword_arguments
|
28
38
|
)
|
29
39
|
super(**keyword_arguments)
|
40
|
+
@extended_module_qualified_names = extended_module_qualified_names
|
41
|
+
@extended_module_unqualified_names = extended_module_unqualified_names
|
30
42
|
@included_module_qualified_names = included_module_qualified_names
|
31
43
|
@included_module_unqualified_names = included_module_unqualified_names
|
32
44
|
@prepended_module_qualified_names = prepended_module_qualified_names
|
@@ -36,6 +48,8 @@ module Rucoa
|
|
36
48
|
# @param other [Rucoa::Definitions::ModuleDefinition]
|
37
49
|
# @return [Rucoa::Definitions::ModuleDefinition]
|
38
50
|
def merge!(other)
|
51
|
+
self.extended_module_qualified_names |= other.extended_module_qualified_names
|
52
|
+
self.extended_module_unqualified_names |= other.extended_module_unqualified_names
|
39
53
|
self.included_module_qualified_names |= other.included_module_qualified_names
|
40
54
|
self.included_module_unqualified_names |= other.included_module_unqualified_names
|
41
55
|
self.prepended_module_qualified_names |= other.prepended_module_qualified_names
|
data/lib/rucoa/node_inspector.rb
CHANGED
@@ -51,7 +51,7 @@ module Rucoa
|
|
51
51
|
def return_types
|
52
52
|
case @node.type
|
53
53
|
when :const
|
54
|
-
|
54
|
+
return_types_for_const
|
55
55
|
when :lvar
|
56
56
|
return_types_for_lvar
|
57
57
|
when :send
|
@@ -113,6 +113,17 @@ module Rucoa
|
|
113
113
|
@node.each_ancestor(:def).first&.qualified_name
|
114
114
|
end
|
115
115
|
|
116
|
+
# @return [Array<String>]
|
117
|
+
def return_types_for_const
|
118
|
+
qualified_name = @definition_store.resolve_constant(
|
119
|
+
UnqualifiedName.new(
|
120
|
+
chained_name: @node.chained_name,
|
121
|
+
module_nesting: @node.module_nesting
|
122
|
+
)
|
123
|
+
)
|
124
|
+
["singleton<#{qualified_name}>"]
|
125
|
+
end
|
126
|
+
|
116
127
|
# @return [Array<String>]
|
117
128
|
def return_types_for_lvar
|
118
129
|
qualified_name = nearest_def_qualified_name
|
@@ -12,6 +12,7 @@ module Rucoa
|
|
12
12
|
def call
|
13
13
|
Definitions::ClassDefinition.new(
|
14
14
|
description: description,
|
15
|
+
extended_module_qualified_names: extended_module_qualified_names,
|
15
16
|
included_module_qualified_names: included_module_qualified_names,
|
16
17
|
location: location,
|
17
18
|
prepended_module_qualified_names: prepended_module_qualified_names,
|
@@ -20,6 +20,7 @@ module Rucoa
|
|
20
20
|
def call
|
21
21
|
Definitions::ModuleDefinition.new(
|
22
22
|
description: description,
|
23
|
+
extended_module_qualified_names: extended_module_qualified_names,
|
23
24
|
included_module_qualified_names: included_module_qualified_names,
|
24
25
|
location: location,
|
25
26
|
prepended_module_qualified_names: prepended_module_qualified_names,
|
@@ -44,21 +45,25 @@ module Rucoa
|
|
44
45
|
Location.from_rbs_location(@declaration.location)
|
45
46
|
end
|
46
47
|
|
48
|
+
# @return [Array<String>]
|
49
|
+
def extended_module_qualified_names
|
50
|
+
module_qualified_names_for(::RBS::AST::Members::Extend)
|
51
|
+
end
|
52
|
+
|
47
53
|
# @return [Array<String>]
|
48
54
|
def included_module_qualified_names
|
49
|
-
|
50
|
-
case member
|
51
|
-
when ::RBS::AST::Members::Include
|
52
|
-
member.name.to_s.delete_prefix('::')
|
53
|
-
end
|
54
|
-
end
|
55
|
+
module_qualified_names_for(::RBS::AST::Members::Include)
|
55
56
|
end
|
56
57
|
|
57
58
|
# @return [Array<String>]
|
58
59
|
def prepended_module_qualified_names
|
60
|
+
module_qualified_names_for(::RBS::AST::Members::Prepend)
|
61
|
+
end
|
62
|
+
|
63
|
+
def module_qualified_names_for(member_class)
|
59
64
|
@declaration.members.filter_map do |member|
|
60
65
|
case member
|
61
|
-
when
|
66
|
+
when member_class
|
62
67
|
member.name.to_s.delete_prefix('::')
|
63
68
|
end
|
64
69
|
end
|
data/lib/rucoa/server.rb
CHANGED
data/lib/rucoa/version.rb
CHANGED
@@ -35,10 +35,26 @@ module Rucoa
|
|
35
35
|
# Foo#bar=
|
36
36
|
# ]
|
37
37
|
# )
|
38
|
+
# @example ignores unrecognizable attributes
|
39
|
+
# definitions = Rucoa::Source.new(
|
40
|
+
# content: <<~RUBY,
|
41
|
+
# class Foo
|
42
|
+
# attr_reader foo
|
43
|
+
# end
|
44
|
+
# RUBY
|
45
|
+
# uri: '/path/to/foo.rb'
|
46
|
+
# ).definitions
|
47
|
+
# expect(definitions.map(&:qualified_name)).to eq(
|
48
|
+
# %w[
|
49
|
+
# Foo
|
50
|
+
# ]
|
51
|
+
# )
|
38
52
|
def call
|
39
53
|
return [] unless @node.is_a?(Nodes::SendNode) && READER_METHOD_NAMES.include?(@node.name)
|
40
54
|
|
41
|
-
@node.arguments.
|
55
|
+
@node.arguments.filter_map do |argument|
|
56
|
+
next unless argument.respond_to?(:value)
|
57
|
+
|
42
58
|
Definitions::MethodDefinition.new(
|
43
59
|
description: description,
|
44
60
|
kind: :instance,
|
@@ -35,10 +35,26 @@ module Rucoa
|
|
35
35
|
# Foo#bar=
|
36
36
|
# ]
|
37
37
|
# )
|
38
|
+
# @example ignores unrecognizable attributes
|
39
|
+
# definitions = Rucoa::Source.new(
|
40
|
+
# content: <<~RUBY,
|
41
|
+
# class Foo
|
42
|
+
# attr_writer foo
|
43
|
+
# end
|
44
|
+
# RUBY
|
45
|
+
# uri: '/path/to/foo.rb'
|
46
|
+
# ).definitions
|
47
|
+
# expect(definitions.map(&:qualified_name)).to eq(
|
48
|
+
# %w[
|
49
|
+
# Foo
|
50
|
+
# ]
|
51
|
+
# )
|
38
52
|
def call
|
39
53
|
return [] unless @node.is_a?(Nodes::SendNode) && WRITER_METHOD_NAMES.include?(@node.name)
|
40
54
|
|
41
|
-
@node.arguments.
|
55
|
+
@node.arguments.filter_map do |argument|
|
56
|
+
next unless argument.respond_to?(:value)
|
57
|
+
|
42
58
|
Definitions::MethodDefinition.new(
|
43
59
|
description: description,
|
44
60
|
kind: :instance,
|
@@ -49,6 +49,7 @@ module Rucoa
|
|
49
49
|
[
|
50
50
|
Definitions::ClassDefinition.new(
|
51
51
|
description: description,
|
52
|
+
extended_module_unqualified_names: extended_module_unqualified_names,
|
52
53
|
included_module_unqualified_names: included_module_unqualified_names,
|
53
54
|
location: location,
|
54
55
|
prepended_module_unqualified_names: prepended_module_unqualified_names,
|
@@ -22,6 +22,19 @@ module Rucoa
|
|
22
22
|
# uri: '/path/to/foo.rb'
|
23
23
|
# ).definitions
|
24
24
|
# expect(definitions[0]).to be_a(Rucoa::Definitions::MethodDefinition)
|
25
|
+
# @example returns method definition for another style of singleton def node
|
26
|
+
# definitions = Rucoa::Source.new(
|
27
|
+
# content: <<~RUBY,
|
28
|
+
# class Foo
|
29
|
+
# class << self
|
30
|
+
# def bar
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
# RUBY
|
35
|
+
# uri: '/path/to/foo.rb'
|
36
|
+
# ).definitions
|
37
|
+
# expect(definitions[1].qualified_name).to eq('Foo.bar')
|
25
38
|
def call
|
26
39
|
return [] unless @node.is_a?(Nodes::DefNode) || @node.is_a?(Nodes::DefsNode)
|
27
40
|
|
@@ -19,6 +19,7 @@ module Rucoa
|
|
19
19
|
[
|
20
20
|
Definitions::ModuleDefinition.new(
|
21
21
|
description: description,
|
22
|
+
extended_module_unqualified_names: extended_module_unqualified_names,
|
22
23
|
included_module_unqualified_names: included_module_unqualified_names,
|
23
24
|
location: location,
|
24
25
|
prepended_module_unqualified_names: prepended_module_unqualified_names,
|
@@ -29,6 +30,11 @@ module Rucoa
|
|
29
30
|
|
30
31
|
private
|
31
32
|
|
33
|
+
# @return [Array<Rucoa::UnqualifiedName>]
|
34
|
+
def extended_module_unqualified_names
|
35
|
+
unqualified_names_for('extend')
|
36
|
+
end
|
37
|
+
|
32
38
|
# @return [Array<Rucoa::UnqualifiedName>]
|
33
39
|
def included_module_unqualified_names
|
34
40
|
unqualified_names_for('include')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rucoa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-09-
|
11
|
+
date: 2022-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|