rucoa 0.10.0 → 0.12.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -2
  3. data/Gemfile.lock +3 -3
  4. data/README.md +4 -1
  5. data/data/definitions_ruby_3_1 +6594 -6594
  6. data/lib/rucoa/configuration.rb +22 -12
  7. data/lib/rucoa/definition_store.rb +270 -158
  8. data/lib/rucoa/definitions/method_definition.rb +11 -11
  9. data/lib/rucoa/definitions/module_definition.rb +14 -0
  10. data/lib/rucoa/handler_concerns/configuration_requestable.rb +7 -7
  11. data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +11 -11
  12. data/lib/rucoa/handler_concerns/text_document_position_parameters.rb +29 -0
  13. data/lib/rucoa/handler_concerns/text_document_uri_parameters.rb +21 -0
  14. data/lib/rucoa/handler_concerns.rb +2 -0
  15. data/lib/rucoa/handlers/base.rb +9 -9
  16. data/lib/rucoa/handlers/initialize_handler.rb +1 -0
  17. data/lib/rucoa/handlers/initialized_handler.rb +16 -16
  18. data/lib/rucoa/handlers/text_document_code_action_handler.rb +12 -12
  19. data/lib/rucoa/handlers/text_document_completion_handler.rb +85 -99
  20. data/lib/rucoa/handlers/text_document_definition_handler.rb +11 -30
  21. data/lib/rucoa/handlers/text_document_did_close_handler.rb +2 -8
  22. data/lib/rucoa/handlers/text_document_did_open_handler.rb +3 -7
  23. data/lib/rucoa/handlers/text_document_document_highlight_handler.rb +256 -0
  24. data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +47 -76
  25. data/lib/rucoa/handlers/text_document_formatting_handler.rb +15 -23
  26. data/lib/rucoa/handlers/text_document_hover_handler.rb +24 -43
  27. data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +17 -25
  28. data/lib/rucoa/handlers/text_document_selection_range_handler.rb +11 -19
  29. data/lib/rucoa/handlers/text_document_signature_help_handler.rb +17 -36
  30. data/lib/rucoa/handlers.rb +1 -0
  31. data/lib/rucoa/node_concerns/body.rb +1 -1
  32. data/lib/rucoa/node_concerns/qualified_name.rb +5 -5
  33. data/lib/rucoa/node_concerns/rescue.rb +21 -0
  34. data/lib/rucoa/node_concerns.rb +1 -0
  35. data/lib/rucoa/node_inspector.rb +17 -6
  36. data/lib/rucoa/nodes/base.rb +48 -48
  37. data/lib/rucoa/nodes/begin_node.rb +2 -0
  38. data/lib/rucoa/nodes/block_node.rb +24 -0
  39. data/lib/rucoa/nodes/case_node.rb +24 -0
  40. data/lib/rucoa/nodes/const_node.rb +26 -26
  41. data/lib/rucoa/nodes/def_node.rb +14 -13
  42. data/lib/rucoa/nodes/ensure_node.rb +19 -0
  43. data/lib/rucoa/nodes/for_node.rb +8 -0
  44. data/lib/rucoa/nodes/if_node.rb +32 -0
  45. data/lib/rucoa/nodes/resbody_node.rb +8 -0
  46. data/lib/rucoa/nodes/rescue_node.rb +17 -0
  47. data/lib/rucoa/nodes/send_node.rb +40 -0
  48. data/lib/rucoa/nodes/until_node.rb +8 -0
  49. data/lib/rucoa/nodes/when_node.rb +8 -0
  50. data/lib/rucoa/nodes/while_node.rb +8 -0
  51. data/lib/rucoa/nodes.rb +10 -1
  52. data/lib/rucoa/parser_builder.rb +16 -2
  53. data/lib/rucoa/range.rb +9 -3
  54. data/lib/rucoa/rbs/class_definition_mapper.rb +1 -0
  55. data/lib/rucoa/rbs/constant_definition_mapper.rb +5 -5
  56. data/lib/rucoa/rbs/method_definition_mapper.rb +18 -18
  57. data/lib/rucoa/rbs/module_definition_mapper.rb +17 -12
  58. data/lib/rucoa/rbs/ruby_definitions_loader.rb +5 -5
  59. data/lib/rucoa/rubocop/configuration_checker.rb +7 -7
  60. data/lib/rucoa/server.rb +25 -24
  61. data/lib/rucoa/source.rb +5 -5
  62. data/lib/rucoa/source_store.rb +8 -8
  63. data/lib/rucoa/version.rb +1 -1
  64. data/lib/rucoa/yard/definition_generators/attribute_reader_definition_generator.rb +17 -1
  65. data/lib/rucoa/yard/definition_generators/attribute_writer_definition_generator.rb +17 -1
  66. data/lib/rucoa/yard/definition_generators/class_definition_generator.rb +1 -0
  67. data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +14 -1
  68. data/lib/rucoa/yard/definition_generators/module_definition_generator.rb +6 -0
  69. metadata +16 -3
  70. data/lib/rucoa/nodes/defs_node.rb +0 -33
@@ -36,6 +36,11 @@ module Rucoa
36
36
  disable_feature('formatting')
37
37
  end
38
38
 
39
+ # @return [void]
40
+ def disable_highlight
41
+ disable_feature('highlight')
42
+ end
43
+
39
44
  # @return [void]
40
45
  def disable_hover
41
46
  disable_feature('hover')
@@ -58,18 +63,6 @@ module Rucoa
58
63
  @settings['base']['debug'] = true
59
64
  end
60
65
 
61
- # @return [Boolean]
62
- # @example returns false if the configuration is empty
63
- # configuration = Rucoa::Configuration.new
64
- # expect(configuration).not_to be_enables_debug
65
- # @example returns true if the configuration enables debug
66
- # configuration = Rucoa::Configuration.new
67
- # configuration.update('base' => { 'debug' => true })
68
- # expect(configuration).to be_enables_debug
69
- def enables_debug?
70
- fetch('base', 'debug', default: false)
71
- end
72
-
73
66
  # @return [Boolean]
74
67
  # @example returns true if the configuration is empty
75
68
  # configuration = Rucoa::Configuration.new
@@ -87,6 +80,18 @@ module Rucoa
87
80
  enables_feature?('completion')
88
81
  end
89
82
 
83
+ # @return [Boolean]
84
+ # @example returns false if the configuration is empty
85
+ # configuration = Rucoa::Configuration.new
86
+ # expect(configuration).not_to be_enables_debug
87
+ # @example returns true if the configuration enables debug
88
+ # configuration = Rucoa::Configuration.new
89
+ # configuration.update('base' => { 'debug' => true })
90
+ # expect(configuration).to be_enables_debug
91
+ def enables_debug?
92
+ fetch('base', 'debug', default: false)
93
+ end
94
+
90
95
  # @return [Boolean]
91
96
  def enables_definition?
92
97
  enables_feature?('definition')
@@ -107,6 +112,11 @@ module Rucoa
107
112
  enables_feature?('formatting')
108
113
  end
109
114
 
115
+ # @return [Boolean]
116
+ def enables_highlight?
117
+ enables_feature?('highlight')
118
+ end
119
+
110
120
  # @return [Boolean]
111
121
  def enables_hover?
112
122
  enables_feature?('hover')
@@ -7,11 +7,6 @@ module Rucoa
7
7
  @qualified_names_by_uri = ::Hash.new { |hash, key| hash[key] = [] }
8
8
  end
9
9
 
10
- # @return [String]
11
- def inspect
12
- "#<#{self.class} definitions_count=#{@definition_by_qualified_name.count}>"
13
- end
14
-
15
10
  # @param definitions [Array<Rucoa::Definition::Base>]
16
11
  # @return [void]
17
12
  def bulk_add(definitions)
@@ -23,61 +18,12 @@ module Rucoa
23
18
  end
24
19
  end
25
20
 
26
- # @param source [Rucoa::Source]
27
- # @return [void]
28
- # @example resolves super class name from definitions
29
- # definition_store = Rucoa::DefinitionStore.new
30
- # foo = Rucoa::Source.new(
31
- # content: <<~RUBY,
32
- # module A
33
- # class Foo
34
- # end
35
- # end
36
- # RUBY
37
- # uri: 'file:///path/to/a/foo.rb',
38
- # )
39
- # definition_store.update_from(foo)
40
- # bar = Rucoa::Source.new(
41
- # content: <<~RUBY,
42
- # module A
43
- # class Bar < Foo
44
- # end
45
- # end
46
- # RUBY
47
- # uri: 'file:///path/to/a/bar.rb',
48
- # )
49
- # definition_store.update_from(bar)
50
- # definition = definition_store.find_definition_by_qualified_name('A::Bar')
51
- # expect(definition.super_class_qualified_name).to eq('A::Foo')
52
- # @example resolves included module names from definitions
53
- # definition_store = Rucoa::DefinitionStore.new
54
- # foo = Rucoa::Source.new(
55
- # content: <<~RUBY,
56
- # module A
57
- # module Foo
58
- # end
59
- # end
60
- # RUBY
61
- # uri: 'file:///path/to/a/foo.rb',
62
- # )
63
- # definition_store.update_from(foo)
64
- # bar = Rucoa::Source.new(
65
- # content: <<~RUBY,
66
- # module A
67
- # class Bar
68
- # include Foo
69
- # end
70
- # end
71
- # RUBY
72
- # uri: 'file:///path/to/a/bar.rb',
73
- # )
74
- # definition_store.update_from(bar)
75
- # definition = definition_store.find_definition_by_qualified_name('A::Bar')
76
- # expect(definition.included_module_qualified_names).to eq(%w[A::Foo])
77
- def update_from(source)
78
- delete_definitions_in(source)
79
- add_definitions_in(source)
80
- resolve_constants_in(source)
21
+ # @param namespace [String]
22
+ # @return [Array<Rucoa::Definitions::ConstantDefinition>] e.g. File::Separator, File::SEPARATOR, etc.
23
+ def constant_definitions_under(namespace)
24
+ constant_definitions.select do |constant_definition|
25
+ constant_definition.namespace == namespace
26
+ end
81
27
  end
82
28
 
83
29
  # @param qualified_name [String]
@@ -178,18 +124,83 @@ module Rucoa
178
124
  end
179
125
  end
180
126
 
127
+ # @return [String]
128
+ def inspect
129
+ "#<#{self.class} definitions_count=#{@definition_by_qualified_name.count}>"
130
+ end
131
+
181
132
  # @param type [String]
182
133
  # @return [Array<Rucoa::Definitions::MethodDefinition>]
183
- # @example includes ancestors' methods
134
+ # @example supports simple instance method
135
+ # source = Rucoa::Source.new(
136
+ # content: <<~RUBY,
137
+ # class A
138
+ # def foo
139
+ # end
140
+ # end
141
+ # RUBY
142
+ # uri: 'file:///path/to/example.rb'
143
+ # )
184
144
  # definition_store = Rucoa::DefinitionStore.new
185
- # definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
186
- # subject = definition_store.instance_method_definitions_of('File')
187
- # expect(subject.map(&:qualified_name)).to include('IO#raw')
188
- # @example responds to `singleton<File>`
145
+ # definition_store.update_from(source)
146
+ # subject = definition_store.instance_method_definitions_of('A')
147
+ # expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
148
+ # @example supports inheritance
149
+ # source = Rucoa::Source.new(
150
+ # content: <<~RUBY,
151
+ # class A
152
+ # def foo
153
+ # end
154
+ # end
155
+ #
156
+ # class B < A
157
+ # end
158
+ # RUBY
159
+ # uri: 'file:///path/to/example.rb'
160
+ # )
161
+ # definition_store = Rucoa::DefinitionStore.new
162
+ # definition_store.update_from(source)
163
+ # subject = definition_store.instance_method_definitions_of('B')
164
+ # expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
165
+ # @example supports `include`
166
+ # source = Rucoa::Source.new(
167
+ # content: <<~RUBY,
168
+ # module A
169
+ # def foo
170
+ # end
171
+ # end
172
+ #
173
+ # class B
174
+ # include A
175
+ # end
176
+ # RUBY
177
+ # uri: 'file:///path/to/example.rb'
178
+ # )
179
+ # definition_store = Rucoa::DefinitionStore.new
180
+ # definition_store.update_from(source)
181
+ # subject = definition_store.instance_method_definitions_of('B')
182
+ # expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
183
+ # @example supports `prepend`
184
+ # source = Rucoa::Source.new(
185
+ # content: <<~RUBY,
186
+ # module A
187
+ # def foo
188
+ # end
189
+ # end
190
+ #
191
+ # class B
192
+ # prepend A
193
+ #
194
+ # def foo
195
+ # end
196
+ # end
197
+ # RUBY
198
+ # uri: 'file:///path/to/example.rb'
199
+ # )
189
200
  # definition_store = Rucoa::DefinitionStore.new
190
- # definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
191
- # subject = definition_store.instance_method_definitions_of('singleton<File>')
192
- # expect(subject.map(&:qualified_name)).to include('IO.write')
201
+ # definition_store.update_from(source)
202
+ # subject = definition_store.instance_method_definitions_of('B')
203
+ # expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
193
204
  def instance_method_definitions_of(type)
194
205
  singleton_class_name = singleton_class_name_from(type)
195
206
  return singleton_method_definitions_of(singleton_class_name) if singleton_class_name
@@ -197,68 +208,172 @@ module Rucoa
197
208
  class_or_module_definition = find_definition_by_qualified_name(type)
198
209
  return [] unless class_or_module_definition
199
210
 
200
- method_definitions = instance_method_definitions
211
+ method_definitions = self.method_definitions
201
212
  ancestors_of(class_or_module_definition).flat_map do |ancestor|
202
213
  method_definitions.select do |method_definition|
203
- method_definition.namespace == ancestor.qualified_name
214
+ method_definition.namespace == ancestor.qualified_name &&
215
+ method_definition.instance_method?
204
216
  end
205
- end
217
+ end.uniq(&:method_name)
218
+ end
219
+
220
+ # @todo Search ancestors.
221
+ # @param unqualified_name [Rucoa::UnqualifiedName]
222
+ # @return [String]
223
+ def resolve_constant(unqualified_name)
224
+ (
225
+ unqualified_name.module_nesting.map do |prefix|
226
+ "#{prefix}::#{unqualified_name.chained_name}"
227
+ end + [unqualified_name.chained_name]
228
+ ).find do |candidate|
229
+ find_definition_by_qualified_name(candidate)
230
+ end || unqualified_name.chained_name
206
231
  end
207
232
 
208
233
  # @param type [String]
209
234
  # @return [Array<Rucoa::Definitions::MethodDefinition>]
210
- # @example returns singleton method definitions of File
235
+ # @example supports simple singleton method
236
+ # source = Rucoa::Source.new(
237
+ # content: <<~RUBY,
238
+ # class A
239
+ # def self.foo
240
+ # end
241
+ # end
242
+ # RUBY
243
+ # uri: 'file:///path/to/example.rb'
244
+ # )
211
245
  # definition_store = Rucoa::DefinitionStore.new
212
- # definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
213
- # subject = definition_store.singleton_method_definitions_of('File')
214
- # expect(subject.map(&:qualified_name)).to include('IO.write')
246
+ # definition_store.update_from(source)
247
+ # subject = definition_store.singleton_method_definitions_of('A')
248
+ # expect(subject.map(&:qualified_name)).to include('A.foo')
249
+ # @example supports super class's singleton method
250
+ # source = Rucoa::Source.new(
251
+ # content: <<~RUBY,
252
+ # class A
253
+ # def self.foo
254
+ # end
255
+ # end
256
+ #
257
+ # class B < A
258
+ # end
259
+ # RUBY
260
+ # uri: 'file:///path/to/example.rb'
261
+ # )
262
+ # definition_store = Rucoa::DefinitionStore.new
263
+ # definition_store.update_from(source)
264
+ # subject = definition_store.singleton_method_definitions_of('B')
265
+ # expect(subject.map(&:qualified_name)).to include('A.foo')
266
+ # @example supports extended module's instance method
267
+ # source = Rucoa::Source.new(
268
+ # content: <<~RUBY,
269
+ # module A
270
+ # def foo
271
+ # end
272
+ # end
273
+ #
274
+ # class B
275
+ # def self.foo
276
+ # end
277
+ # end
278
+ #
279
+ # class C < B
280
+ # extend A
281
+ # end
282
+ # RUBY
283
+ # uri: 'file:///path/to/example.rb'
284
+ # )
285
+ # definition_store = Rucoa::DefinitionStore.new
286
+ # definition_store.update_from(source)
287
+ # subject = definition_store.singleton_method_definitions_of('C')
288
+ # expect(subject.map(&:qualified_name)).to eq(%w[A#foo])
215
289
  def singleton_method_definitions_of(type)
216
290
  class_or_module_definition = find_definition_by_qualified_name(type)
217
291
  return [] unless class_or_module_definition
218
292
 
219
- method_definitions = singleton_method_definitions
293
+ method_definitions = self.method_definitions
220
294
  ancestors_of(class_or_module_definition).flat_map do |ancestor|
221
295
  method_definitions.select do |method_definition|
222
- method_definition.namespace == ancestor.qualified_name
296
+ method_definition.namespace == ancestor.qualified_name &&
297
+ method_definition.singleton_method?
298
+ end + ancestor.extended_module_qualified_names.flat_map do |extended_module_qualified_name|
299
+ method_definitions.select do |method_definition|
300
+ method_definition.namespace == extended_module_qualified_name &&
301
+ method_definition.instance_method?
302
+ end
223
303
  end
224
- end
225
- end
226
-
227
- # @param namespace [String]
228
- # @return [Array<Rucoa::Definitions::ConstantDefinition>] e.g. File::Separator, File::SEPARATOR, etc.
229
- def constant_definitions_under(namespace)
230
- constant_definitions.select do |constant_definition|
231
- constant_definition.namespace == namespace
232
- end
304
+ end.uniq(&:method_name)
233
305
  end
234
306
 
235
- # @param unqualified_name [Rucoa::UnqualifiedName]
236
- # @return [String]
237
- def resolve_constant(unqualified_name)
238
- (
239
- unqualified_name.module_nesting.map do |prefix|
240
- "#{prefix}::#{unqualified_name.chained_name}"
241
- end + [unqualified_name.chained_name]
242
- ).find do |candidate|
243
- find_definition_by_qualified_name(candidate)
244
- end || unqualified_name.chained_name
307
+ # @param source [Rucoa::Source]
308
+ # @return [void]
309
+ # @example resolves super class name from definitions
310
+ # definition_store = Rucoa::DefinitionStore.new
311
+ # foo = Rucoa::Source.new(
312
+ # content: <<~RUBY,
313
+ # module A
314
+ # class Foo
315
+ # end
316
+ # end
317
+ # RUBY
318
+ # uri: 'file:///path/to/a/foo.rb',
319
+ # )
320
+ # definition_store.update_from(foo)
321
+ # bar = Rucoa::Source.new(
322
+ # content: <<~RUBY,
323
+ # module A
324
+ # class Bar < Foo
325
+ # end
326
+ # end
327
+ # RUBY
328
+ # uri: 'file:///path/to/a/bar.rb',
329
+ # )
330
+ # definition_store.update_from(bar)
331
+ # definition = definition_store.find_definition_by_qualified_name('A::Bar')
332
+ # expect(definition.super_class_qualified_name).to eq('A::Foo')
333
+ # @example resolves included module names from definitions
334
+ # definition_store = Rucoa::DefinitionStore.new
335
+ # foo = Rucoa::Source.new(
336
+ # content: <<~RUBY,
337
+ # module A
338
+ # module Foo
339
+ # end
340
+ # end
341
+ # RUBY
342
+ # uri: 'file:///path/to/a/foo.rb',
343
+ # )
344
+ # definition_store.update_from(foo)
345
+ # bar = Rucoa::Source.new(
346
+ # content: <<~RUBY,
347
+ # module A
348
+ # class Bar
349
+ # include Foo
350
+ # end
351
+ # end
352
+ # RUBY
353
+ # uri: 'file:///path/to/a/bar.rb',
354
+ # )
355
+ # definition_store.update_from(bar)
356
+ # definition = definition_store.find_definition_by_qualified_name('A::Bar')
357
+ # expect(definition.included_module_qualified_names).to eq(%w[A::Foo])
358
+ def update_from(source)
359
+ delete_definitions_in(source)
360
+ add_definitions_in(source)
361
+ resolve_constants_in(source)
245
362
  end
246
363
 
247
364
  private
248
365
 
249
366
  # @param source [Rucoa::Source]
250
367
  # @return [void]
251
- def delete_definitions_in(source)
252
- @qualified_names_by_uri[source.uri].each do |qualified_name|
253
- @definition_by_qualified_name.delete(qualified_name)
368
+ def add_definitions_in(source)
369
+ source.definitions.group_by do |definition|
370
+ definition.location.uri
371
+ end.each do |uri, definitions|
372
+ @qualified_names_by_uri[uri] += definitions.map(&:qualified_name)
373
+ definitions.each do |definition|
374
+ @definition_by_qualified_name[definition.qualified_name] = definition
375
+ end
254
376
  end
255
- @qualified_names_by_uri.delete(source.uri)
256
- end
257
-
258
- # @param type [String]
259
- # @return [String, nil]
260
- def singleton_class_name_from(type)
261
- type[/singleton<(\w+)>/, 1]
262
377
  end
263
378
 
264
379
  # @param definition [Rucoa::Definitions::Class, Rucoa::Definitions::Module]
@@ -273,32 +388,9 @@ module Rucoa
273
388
  end
274
389
  end
275
390
 
276
- # @param definition [Rucoa::Definitions::Class, Rucoa::Definitions::Module]
277
- # @return [Array<Rucoa::Definitions::Class, Rucoa::Definitions::Module>] An array of prepended, itself, and included definitions
278
- def module_ancestors_of(definition)
279
- [
280
- *definition.prepended_module_qualified_names.filter_map do |qualified_name|
281
- find_definition_by_qualified_name(qualified_name)
282
- end.reverse,
283
- definition,
284
- *definition.included_module_qualified_names.filter_map do |qualified_name|
285
- find_definition_by_qualified_name(qualified_name)
286
- end.reverse
287
- ]
288
- end
289
-
290
- # @param definition [Rucoa::Definitions::Class]
291
- # @return [Array<Rucoa::Definitions::Class>] super "class"es (not including modules) in closest-first order
292
- def super_class_definitions_of(definition)
293
- result = []
294
- while (super_class_qualified_name = definition.super_class_qualified_name)
295
- super_definition = find_definition_by_qualified_name(super_class_qualified_name)
296
- break unless super_definition
297
-
298
- result << super_definition
299
- definition = super_definition
300
- end
301
- result
391
+ # @return [Array<Rucoa::Definition::ConstantDefinition>]
392
+ def constant_definitions
393
+ definitions.grep(Definitions::ConstantDefinition)
302
394
  end
303
395
 
304
396
  # @return [Array<Rucoa::Definitions::Base>]
@@ -306,37 +398,32 @@ module Rucoa
306
398
  @definition_by_qualified_name.values
307
399
  end
308
400
 
309
- # @return [Array<Rucoa::Definition::MethodDefinition>]
310
- def method_definitions
311
- definitions.grep(Definitions::MethodDefinition)
312
- end
313
-
314
- # @return [Array<Rucoa::Definition::MethodDefinition>]
315
- def instance_method_definitions
316
- method_definitions.select(&:instance_method?)
401
+ # @param source [Rucoa::Source]
402
+ # @return [void]
403
+ def delete_definitions_in(source)
404
+ @qualified_names_by_uri[source.uri].each do |qualified_name|
405
+ @definition_by_qualified_name.delete(qualified_name)
406
+ end
407
+ @qualified_names_by_uri.delete(source.uri)
317
408
  end
318
409
 
319
410
  # @return [Array<Rucoa::Definition::MethodDefinition>]
320
- def singleton_method_definitions
321
- method_definitions.select(&:singleton_method?)
322
- end
323
-
324
- # @return [Array<Rucoa::Definition::ConstantDefinition>]
325
- def constant_definitions
326
- definitions.grep(Definitions::ConstantDefinition)
411
+ def method_definitions
412
+ definitions.grep(Definitions::MethodDefinition)
327
413
  end
328
414
 
329
- # @param source [Rucoa::Source]
330
- # @return [void]
331
- def add_definitions_in(source)
332
- source.definitions.group_by do |definition|
333
- definition.location.uri
334
- end.each do |uri, definitions|
335
- @qualified_names_by_uri[uri] += definitions.map(&:qualified_name)
336
- definitions.each do |definition|
337
- @definition_by_qualified_name[definition.qualified_name] = definition
338
- end
339
- end
415
+ # @param definition [Rucoa::Definitions::Class, Rucoa::Definitions::Module]
416
+ # @return [Array<Rucoa::Definitions::Class, Rucoa::Definitions::Module>] An array of prepended, itself, and included definitions
417
+ def module_ancestors_of(definition)
418
+ [
419
+ *definition.prepended_module_qualified_names.filter_map do |qualified_name|
420
+ find_definition_by_qualified_name(qualified_name)
421
+ end.reverse,
422
+ definition,
423
+ *definition.included_module_qualified_names.filter_map do |qualified_name|
424
+ find_definition_by_qualified_name(qualified_name)
425
+ end.reverse
426
+ ]
340
427
  end
341
428
 
342
429
  # @param source [Rucoa::Source]
@@ -348,6 +435,11 @@ module Rucoa
348
435
  definition.super_class_qualified_name = resolve_constant(definition.super_class_unqualified_name)
349
436
  definition.super_class_unqualified_name = nil
350
437
 
438
+ definition.extended_module_qualified_names = definition.extended_module_unqualified_names.map do |unqualified_name|
439
+ resolve_constant(unqualified_name)
440
+ end
441
+ definition.extended_module_unqualified_names = []
442
+
351
443
  definition.included_module_qualified_names = definition.included_module_unqualified_names.map do |unqualified_name|
352
444
  resolve_constant(unqualified_name)
353
445
  end
@@ -359,5 +451,25 @@ module Rucoa
359
451
  definition.prepended_module_unqualified_names = []
360
452
  end
361
453
  end
454
+
455
+ # @param type [String]
456
+ # @return [String, nil]
457
+ def singleton_class_name_from(type)
458
+ type[/singleton<([\w:]+)>/, 1]
459
+ end
460
+
461
+ # @param definition [Rucoa::Definitions::Class]
462
+ # @return [Array<Rucoa::Definitions::Class>] super "class"es (not including modules) in closest-first order
463
+ def super_class_definitions_of(definition)
464
+ result = []
465
+ while (super_class_qualified_name = definition.super_class_qualified_name)
466
+ super_definition = find_definition_by_qualified_name(super_class_qualified_name)
467
+ break unless super_definition
468
+
469
+ result << super_definition
470
+ definition = super_definition
471
+ end
472
+ result
473
+ end
362
474
  end
363
475
  end
@@ -30,6 +30,17 @@ module Rucoa
30
30
  @types = types
31
31
  end
32
32
 
33
+ # @return [Boolean]
34
+ def instance_method?
35
+ @kind == :instance
36
+ end
37
+
38
+ # @todo
39
+ # @return [Array<Rucoa::Definitions::MethodParameter>]
40
+ def parameters
41
+ []
42
+ end
43
+
33
44
  # @return [String]
34
45
  # @example returns qualified name of method
35
46
  # definition = Rucoa::Source.new(
@@ -52,12 +63,6 @@ module Rucoa
52
63
  ].join
53
64
  end
54
65
 
55
- # @todo
56
- # @return [Array<Rucoa::Definitions::MethodParameter>]
57
- def parameters
58
- []
59
- end
60
-
61
66
  # @return [Array<String>]
62
67
  # @example returns return types
63
68
  # definition = Rucoa::Source.new(
@@ -105,11 +110,6 @@ module Rucoa
105
110
  end
106
111
  end
107
112
 
108
- # @return [Boolean]
109
- def instance_method?
110
- @kind == :instance
111
- end
112
-
113
113
  # @return [Boolean]
114
114
  def singleton_method?
115
115
  !instance_method?
@@ -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
@@ -7,6 +7,13 @@ module Rucoa
7
7
 
8
8
  private
9
9
 
10
+ # @return [void]
11
+ def publish_diagnostics_on_each_source
12
+ source_store.each_uri do |uri|
13
+ publish_diagnostics_on(uri)
14
+ end
15
+ end
16
+
10
17
  # @return [void]
11
18
  def request_workspace_configuration
12
19
  write(
@@ -23,13 +30,6 @@ module Rucoa
23
30
  publish_diagnostics_on_each_source
24
31
  end
25
32
  end
26
-
27
- # @return [void]
28
- def publish_diagnostics_on_each_source
29
- source_store.each_uri do |uri|
30
- publish_diagnostics_on(uri)
31
- end
32
- end
33
33
  end
34
34
  end
35
35
  end