rucoa 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/Gemfile.lock +8 -8
  4. data/data/definitions_ruby_3_1 +0 -0
  5. data/lib/rucoa/configuration.rb +4 -1
  6. data/lib/rucoa/definition_store.rb +216 -83
  7. data/lib/rucoa/definitions/base.rb +14 -3
  8. data/lib/rucoa/definitions/class_definition.rb +14 -64
  9. data/lib/rucoa/definitions/constant_definition.rb +31 -19
  10. data/lib/rucoa/definitions/method_definition.rb +44 -52
  11. data/lib/rucoa/definitions/method_parameter_definition.rb +4 -1
  12. data/lib/rucoa/definitions/module_definition.rb +39 -0
  13. data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +14 -3
  14. data/lib/rucoa/handlers/base.rb +12 -3
  15. data/lib/rucoa/handlers/text_document_definition_handler.rb +3 -99
  16. data/lib/rucoa/handlers/text_document_hover_handler.rb +21 -13
  17. data/lib/rucoa/handlers/text_document_selection_range_handler.rb +8 -2
  18. data/lib/rucoa/location.rb +37 -0
  19. data/lib/rucoa/node_concerns/body.rb +24 -0
  20. data/lib/rucoa/node_concerns/{name_fully_qualifiable.rb → qualified_name.rb} +2 -2
  21. data/lib/rucoa/node_concerns.rb +2 -1
  22. data/lib/rucoa/node_inspector.rb +17 -22
  23. data/lib/rucoa/nodes/base.rb +22 -6
  24. data/lib/rucoa/nodes/begin_node.rb +8 -0
  25. data/lib/rucoa/nodes/casgn_node.rb +1 -1
  26. data/lib/rucoa/nodes/class_node.rb +2 -1
  27. data/lib/rucoa/nodes/const_node.rb +33 -15
  28. data/lib/rucoa/nodes/def_node.rb +2 -2
  29. data/lib/rucoa/nodes/defs_node.rb +1 -1
  30. data/lib/rucoa/nodes/module_node.rb +2 -1
  31. data/lib/rucoa/nodes.rb +2 -1
  32. data/lib/rucoa/parser.rb +14 -14
  33. data/lib/rucoa/parser_builder.rb +6 -1
  34. data/lib/rucoa/position.rb +10 -1
  35. data/lib/rucoa/range.rb +11 -1
  36. data/lib/rucoa/rbs/class_definition_mapper.rb +13 -28
  37. data/lib/rucoa/rbs/constant_definition_mapper.rb +12 -6
  38. data/lib/rucoa/rbs/method_definition_mapper.rb +12 -6
  39. data/lib/rucoa/rbs/module_definition_mapper.rb +34 -6
  40. data/lib/rucoa/rubocop/investigator.rb +4 -1
  41. data/lib/rucoa/server.rb +8 -2
  42. data/lib/rucoa/source.rb +19 -4
  43. data/lib/rucoa/unqualified_name.rb +9 -0
  44. data/lib/rucoa/version.rb +1 -1
  45. data/lib/rucoa/yard/definition_generators/attribute_reader_definition_generator.rb +60 -0
  46. data/lib/rucoa/yard/definition_generators/attribute_writer_definition_generator.rb +60 -0
  47. data/lib/rucoa/yard/definition_generators/base.rb +117 -0
  48. data/lib/rucoa/yard/definition_generators/class_definition_generator.rb +66 -0
  49. data/lib/rucoa/yard/definition_generators/constant_assignment_definition_generator.rb +29 -0
  50. data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +47 -0
  51. data/lib/rucoa/yard/definition_generators/module_definition_generator.rb +62 -0
  52. data/lib/rucoa/yard/definition_generators.rb +15 -0
  53. data/lib/rucoa/yard/definitions_loader.rb +1 -271
  54. data/lib/rucoa/yard.rb +1 -0
  55. data/lib/rucoa.rb +4 -2
  56. metadata +15 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 237fa68185426d66437c43fc2a3f34f7f85ee7309eb4ed6bb6ce4e31b5dfbb6e
4
- data.tar.gz: e9f96daf65c7ccef564b2e06756497fd4d98bd946911487ca2fdd32740436e4b
3
+ metadata.gz: 3344309136313473ea6d4fecd4c57745fb4bc8fc1404c40f7126c0a5d5eef440
4
+ data.tar.gz: 1bfb57eee21c860f54b8c82452717d987a31bc977a5a7853b6e08b0d486fd5ac
5
5
  SHA512:
6
- metadata.gz: 3698e9db246d46ce64314df9b4a7418278a6e9f65cc2e80dfece624b547c5ab238af42b456370d1096e872f6e30aefdb132b5b2bd435ec03d1e6cccdac0a908a
7
- data.tar.gz: 5088d4dcc1fa5ad6e053a155246da87602071fa8283b4f42e1b4e9040b222be5f82622343ad2467b5cdf8003b02293e70ea8d391dc99f478ee36a1389311a9d4
6
+ metadata.gz: 4e9efaf6fd608590febfdc450ba487306d35832196f026a77e6ce8b314b78f477a1a79179637153a3977be407ab0f7079ff8bdb23611a0ea2e0f89681bb9637d
7
+ data.tar.gz: cef07b36f534e390a977f694bf5ce97010b14fce34b990b19742682112a741b17914750e1c8de2e881da03620e8d01bce5d0014bc284b1afc725a0de91a8b88b
data/.rubocop.yml CHANGED
@@ -32,9 +32,15 @@ RSpec/NamedSubject:
32
32
  Security/MarshalLoad:
33
33
  Enabled: false
34
34
 
35
+ Sevencop/AutoloadOrdered:
36
+ Enabled: true
37
+
35
38
  Sevencop/HashLiteralOrder:
36
39
  Enabled: true
37
40
 
41
+ Sevencop/MethodDefinitionMultilineArguments:
42
+ Enabled: true
43
+
38
44
  Style/Documentation:
39
45
  Enabled: false
40
46
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rucoa (0.9.0)
4
+ rucoa (0.10.0)
5
5
  parser
6
6
  rbs
7
7
  rubocop
@@ -27,13 +27,13 @@ GEM
27
27
  rspec-mocks (~> 3.11.0)
28
28
  rspec-core (3.11.0)
29
29
  rspec-support (~> 3.11.0)
30
- rspec-expectations (3.11.0)
30
+ rspec-expectations (3.11.1)
31
31
  diff-lcs (>= 1.2.0, < 2.0)
32
32
  rspec-support (~> 3.11.0)
33
33
  rspec-mocks (3.11.1)
34
34
  diff-lcs (>= 1.2.0, < 2.0)
35
35
  rspec-support (~> 3.11.0)
36
- rspec-support (3.11.0)
36
+ rspec-support (3.11.1)
37
37
  rubocop (1.36.0)
38
38
  json (~> 2.3)
39
39
  parallel (~> 1.10)
@@ -46,17 +46,17 @@ GEM
46
46
  unicode-display_width (>= 1.4.0, < 3.0)
47
47
  rubocop-ast (1.21.0)
48
48
  parser (>= 3.1.1.0)
49
- rubocop-performance (1.14.3)
49
+ rubocop-performance (1.15.0)
50
50
  rubocop (>= 1.7.0, < 2.0)
51
51
  rubocop-ast (>= 0.4.0)
52
52
  rubocop-rake (0.6.0)
53
53
  rubocop (~> 1.0)
54
- rubocop-rspec (2.12.1)
55
- rubocop (~> 1.31)
54
+ rubocop-rspec (2.13.2)
55
+ rubocop (~> 1.33)
56
56
  ruby-progressbar (1.11.0)
57
- sevencop (0.10.0)
57
+ sevencop (0.12.1)
58
58
  rubocop
59
- unicode-display_width (2.2.0)
59
+ unicode-display_width (2.3.0)
60
60
  webrick (1.7.0)
61
61
  yard (0.9.28)
62
62
  webrick (~> 1.7.0)
Binary file
@@ -148,7 +148,10 @@ module Rucoa
148
148
  # @param keys [Array<String>]
149
149
  # @param default [Object]
150
150
  # @return [Object]
151
- def fetch(*keys, default:)
151
+ def fetch(
152
+ *keys,
153
+ default:
154
+ )
152
155
  value = @settings.dig(*keys)
153
156
  if value.nil?
154
157
  default
@@ -3,22 +3,29 @@
3
3
  module Rucoa
4
4
  class DefinitionStore
5
5
  def initialize
6
- @definition_by_full_qualified_name = {}
7
- @fully_qualified_names_by_uri = ::Hash.new { |hash, key| hash[key] = [] }
6
+ @definition_by_qualified_name = {}
7
+ @qualified_names_by_uri = ::Hash.new { |hash, key| hash[key] = [] }
8
+ end
9
+
10
+ # @return [String]
11
+ def inspect
12
+ "#<#{self.class} definitions_count=#{@definition_by_qualified_name.count}>"
8
13
  end
9
14
 
10
15
  # @param definitions [Array<Rucoa::Definition::Base>]
11
16
  # @return [void]
12
17
  def bulk_add(definitions)
13
- definitions.each do |definition|
14
- @fully_qualified_names_by_uri["file://#{definition.source_path}"] << definition.fully_qualified_name
15
- @definition_by_full_qualified_name[definition.fully_qualified_name] = definition
18
+ definitions.group_by(&:qualified_name).each_value.map do |grouped_definitions|
19
+ grouped_definitions.reduce(:merge!)
20
+ end.each do |definition|
21
+ @qualified_names_by_uri[definition.location.uri] << definition.qualified_name if definition.location
22
+ @definition_by_qualified_name[definition.qualified_name] = definition
16
23
  end
17
24
  end
18
25
 
19
26
  # @param source [Rucoa::Source]
20
27
  # @return [void]
21
- # @example resolves super class name correctly by using existent definitions
28
+ # @example resolves super class name from definitions
22
29
  # definition_store = Rucoa::DefinitionStore.new
23
30
  # foo = Rucoa::Source.new(
24
31
  # content: <<~RUBY,
@@ -40,62 +47,134 @@ module Rucoa
40
47
  # uri: 'file:///path/to/a/bar.rb',
41
48
  # )
42
49
  # definition_store.update_from(bar)
43
- # definition = definition_store.find_definition_by_fully_qualified_name('A::Bar')
44
- # expect(definition.super_class_fully_qualified_name).to eq('A::Foo')
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])
45
77
  def update_from(source)
46
- delete_definitions_about(source)
47
-
48
- # Need to store definitions before super class resolution.
49
- source.definitions.group_by(&:source_path).each do |source_path, definitions|
50
- @fully_qualified_names_by_uri["file://#{source_path}"] += definitions.map(&:fully_qualified_name)
51
- definitions.each do |definition|
52
- @definition_by_full_qualified_name[definition.fully_qualified_name] = definition
53
- end
54
- end
55
-
56
- source.definitions.each do |definition|
57
- next unless definition.is_a?(Definitions::ClassDefinition)
58
- next if definition.super_class_resolved?
59
-
60
- definition.super_class_fully_qualified_name = resolve_super_class_of(definition)
61
- end
78
+ delete_definitions_in(source)
79
+ add_definitions_in(source)
80
+ resolve_constants_in(source)
62
81
  end
63
82
 
64
- # @param fully_qualified_name [String]
83
+ # @param qualified_name [String]
65
84
  # @return [Rucoa::Definitions::Base, nil]
66
- def find_definition_by_fully_qualified_name(fully_qualified_name)
67
- @definition_by_full_qualified_name[fully_qualified_name]
85
+ def find_definition_by_qualified_name(qualified_name)
86
+ @definition_by_qualified_name[qualified_name]
68
87
  end
69
88
 
70
89
  # @param method_name [String]
71
90
  # @param namespace [String]
72
91
  # @param singleton [Boolean]
73
92
  # @return [Rucoa::Definition::MethodDefinition, nil]
74
- # @example has the ability to find `IO.write` from `File.write`
93
+ # @example Supports inheritance
94
+ # source = Rucoa::Source.new(
95
+ # content: <<~RUBY,
96
+ # class A
97
+ # def foo
98
+ # end
99
+ # end
100
+ #
101
+ # class B < A
102
+ # end
103
+ # RUBY
104
+ # uri: 'file:///path/to/example.rb'
105
+ # )
75
106
  # definition_store = Rucoa::DefinitionStore.new
76
- # definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
107
+ # definition_store.update_from(source)
77
108
  # subject = definition_store.find_method_definition_by(
78
- # method_name: 'write',
79
- # namespace: 'File',
80
- # singleton: true
109
+ # method_name: 'foo',
110
+ # namespace: 'B',
111
+ # singleton: false
81
112
  # )
82
- # expect(subject.fully_qualified_name).to eq('IO.write')
83
- def find_method_definition_by(method_name:, namespace:, singleton: false)
84
- definition = find_definition_by_fully_qualified_name(namespace)
113
+ # expect(subject.qualified_name).to eq('A#foo')
114
+ # @example supports `include`
115
+ # source = Rucoa::Source.new(
116
+ # content: <<~RUBY,
117
+ # module A
118
+ # def foo
119
+ # end
120
+ # end
121
+ #
122
+ # class B
123
+ # include A
124
+ # end
125
+ # RUBY
126
+ # uri: 'file:///path/to/example.rb'
127
+ # )
128
+ # definition_store = Rucoa::DefinitionStore.new
129
+ # definition_store.update_from(source)
130
+ # subject = definition_store.find_method_definition_by(
131
+ # method_name: 'foo',
132
+ # namespace: 'B',
133
+ # singleton: false
134
+ # )
135
+ # expect(subject.qualified_name).to eq('A#foo')
136
+ # @example supports `prepend`
137
+ # source = Rucoa::Source.new(
138
+ # content: <<~RUBY,
139
+ # module A
140
+ # def foo
141
+ # end
142
+ # end
143
+ #
144
+ # class B
145
+ # prepend A
146
+ #
147
+ # def foo
148
+ # end
149
+ # end
150
+ # RUBY
151
+ # uri: 'file:///path/to/example.rb'
152
+ # )
153
+ # definition_store = Rucoa::DefinitionStore.new
154
+ # definition_store.update_from(source)
155
+ # subject = definition_store.find_method_definition_by(
156
+ # method_name: 'foo',
157
+ # namespace: 'B',
158
+ # singleton: false
159
+ # )
160
+ # expect(subject.qualified_name).to eq('A#foo')
161
+ def find_method_definition_by(
162
+ method_name:,
163
+ namespace:,
164
+ singleton: false
165
+ )
166
+ definition = find_definition_by_qualified_name(namespace)
85
167
  return unless definition
86
168
 
87
- [
88
- namespace,
89
- *ancestor_definitions_of(definition).map(&:fully_qualified_name)
90
- ].find do |fully_qualified_name|
169
+ ancestors_of(definition).find do |ancestor|
91
170
  method_marker = singleton ? '.' : '#'
92
- fully_qualified_method_name = [
93
- fully_qualified_name,
171
+ qualified_method_name = [
172
+ ancestor.qualified_name,
94
173
  method_marker,
95
174
  method_name
96
175
  ].join
97
- definition = find_definition_by_fully_qualified_name(fully_qualified_method_name)
98
- break definition if definition
176
+ method_definition = find_definition_by_qualified_name(qualified_method_name)
177
+ break method_definition if method_definition
99
178
  end
100
179
  end
101
180
 
@@ -105,26 +184,23 @@ module Rucoa
105
184
  # definition_store = Rucoa::DefinitionStore.new
106
185
  # definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
107
186
  # subject = definition_store.instance_method_definitions_of('File')
108
- # expect(subject.map(&:fully_qualified_name)).to include('IO#raw')
187
+ # expect(subject.map(&:qualified_name)).to include('IO#raw')
109
188
  # @example responds to `singleton<File>`
110
189
  # definition_store = Rucoa::DefinitionStore.new
111
190
  # definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
112
191
  # subject = definition_store.instance_method_definitions_of('singleton<File>')
113
- # expect(subject.map(&:fully_qualified_name)).to include('IO.write')
192
+ # expect(subject.map(&:qualified_name)).to include('IO.write')
114
193
  def instance_method_definitions_of(type)
115
194
  singleton_class_name = singleton_class_name_from(type)
116
195
  return singleton_method_definitions_of(singleton_class_name) if singleton_class_name
117
196
 
118
- class_or_module_definition = find_definition_by_fully_qualified_name(type)
197
+ class_or_module_definition = find_definition_by_qualified_name(type)
119
198
  return [] unless class_or_module_definition
120
199
 
121
- definitions = instance_method_definitions
122
- [
123
- class_or_module_definition,
124
- *ancestor_definitions_of(class_or_module_definition)
125
- ].map(&:fully_qualified_name).flat_map do |fully_qualified_type_name|
126
- definitions.select do |definition|
127
- definition.namespace == fully_qualified_type_name
200
+ method_definitions = instance_method_definitions
201
+ ancestors_of(class_or_module_definition).flat_map do |ancestor|
202
+ method_definitions.select do |method_definition|
203
+ method_definition.namespace == ancestor.qualified_name
128
204
  end
129
205
  end
130
206
  end
@@ -135,18 +211,15 @@ module Rucoa
135
211
  # definition_store = Rucoa::DefinitionStore.new
136
212
  # definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
137
213
  # subject = definition_store.singleton_method_definitions_of('File')
138
- # expect(subject.map(&:fully_qualified_name)).to include('IO.write')
214
+ # expect(subject.map(&:qualified_name)).to include('IO.write')
139
215
  def singleton_method_definitions_of(type)
140
- class_or_module_definition = find_definition_by_fully_qualified_name(type)
216
+ class_or_module_definition = find_definition_by_qualified_name(type)
141
217
  return [] unless class_or_module_definition
142
218
 
143
- definitions = singleton_method_definitions
144
- [
145
- class_or_module_definition,
146
- *ancestor_definitions_of(class_or_module_definition)
147
- ].map(&:fully_qualified_name).flat_map do |fully_qualified_type_name|
148
- definitions.select do |definition|
149
- definition.namespace == fully_qualified_type_name
219
+ method_definitions = singleton_method_definitions
220
+ ancestors_of(class_or_module_definition).flat_map do |ancestor|
221
+ method_definitions.select do |method_definition|
222
+ method_definition.namespace == ancestor.qualified_name
150
223
  end
151
224
  end
152
225
  end
@@ -159,15 +232,27 @@ module Rucoa
159
232
  end
160
233
  end
161
234
 
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
245
+ end
246
+
162
247
  private
163
248
 
164
249
  # @param source [Rucoa::Source]
165
250
  # @return [void]
166
- def delete_definitions_about(source)
167
- @fully_qualified_names_by_uri[source.uri].each do |fully_qualified_name|
168
- @definition_by_full_qualified_name.delete(fully_qualified_name)
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)
169
254
  end
170
- @fully_qualified_names_by_uri.delete(source.uri)
255
+ @qualified_names_by_uri.delete(source.uri)
171
256
  end
172
257
 
173
258
  # @param type [String]
@@ -176,25 +261,49 @@ module Rucoa
176
261
  type[/singleton<(\w+)>/, 1]
177
262
  end
178
263
 
179
- # @param class_or_module_definition [Rucoa::Definitions::Class, Rucoa::Definitions::Module]
180
- # @return [Array<Rucoa::Definitions::Class>]
181
- def ancestor_definitions_of(class_or_module_definition)
182
- return [] unless class_or_module_definition.is_a?(Definitions::ClassDefinition)
264
+ # @param definition [Rucoa::Definitions::Class, Rucoa::Definitions::Module]
265
+ # @return [Array<Rucoa::Definitions::Class>] The classes and modules that are traced in method search (as `Module#ancestors` in Ruby)
266
+ def ancestors_of(definition)
267
+ if definition.is_a?(Rucoa::Definitions::ClassDefinition)
268
+ [definition, *super_class_definitions_of(definition)]
269
+ else
270
+ [definition]
271
+ end.flat_map do |base|
272
+ module_ancestors_of(base)
273
+ end
274
+ end
275
+
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
183
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)
184
293
  result = []
185
- class_definition = class_or_module_definition
186
- while (super_class_fully_qualified_name = class_definition.super_class_fully_qualified_name)
187
- class_definition = find_definition_by_fully_qualified_name(super_class_fully_qualified_name)
188
- break unless class_definition
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
189
297
 
190
- result << class_definition
298
+ result << super_definition
299
+ definition = super_definition
191
300
  end
192
301
  result
193
302
  end
194
303
 
195
304
  # @return [Array<Rucoa::Definitions::Base>]
196
305
  def definitions
197
- @definition_by_full_qualified_name.values
306
+ @definition_by_qualified_name.values
198
307
  end
199
308
 
200
309
  # @return [Array<Rucoa::Definition::MethodDefinition>]
@@ -217,14 +326,38 @@ module Rucoa
217
326
  definitions.grep(Definitions::ConstantDefinition)
218
327
  end
219
328
 
220
- # @param class_definition [Rucoa::Definitions::ClassDefinition]
221
- # @return [String]
222
- def resolve_super_class_of(class_definition)
223
- return 'Object' unless class_definition.super_class_chained_name
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
340
+ end
224
341
 
225
- class_definition.super_class_candidates.find do |candidate|
226
- find_definition_by_fully_qualified_name(candidate)
227
- end || class_definition.super_class_chained_name
342
+ # @param source [Rucoa::Source]
343
+ # @return [void]
344
+ def resolve_constants_in(source)
345
+ source.definitions.each do |definition|
346
+ next unless definition.is_a?(Definitions::ClassDefinition)
347
+
348
+ definition.super_class_qualified_name = resolve_constant(definition.super_class_unqualified_name)
349
+ definition.super_class_unqualified_name = nil
350
+
351
+ definition.included_module_qualified_names = definition.included_module_unqualified_names.map do |unqualified_name|
352
+ resolve_constant(unqualified_name)
353
+ end
354
+ definition.included_module_unqualified_names = []
355
+
356
+ definition.prepended_module_qualified_names = definition.prepended_module_unqualified_names.map do |unqualified_name|
357
+ resolve_constant(unqualified_name)
358
+ end
359
+ definition.prepended_module_unqualified_names = []
360
+ end
228
361
  end
229
362
  end
230
363
  end
@@ -3,9 +3,20 @@
3
3
  module Rucoa
4
4
  module Definitions
5
5
  class Base
6
- # @return [String]
7
- def source_path
8
- raise ::NotImplementedError
6
+ # @return [String, nil]
7
+ attr_reader :description
8
+
9
+ # @return [Rucoa::Location, nil]
10
+ attr_accessor :location
11
+
12
+ # @param description [String, nil]
13
+ # @param location [Rucoa::Location, nil]
14
+ def initialize(
15
+ description:,
16
+ location:
17
+ )
18
+ @description = description
19
+ @location = location
9
20
  end
10
21
  end
11
22
  end
@@ -3,79 +3,29 @@
3
3
  module Rucoa
4
4
  module Definitions
5
5
  class ClassDefinition < ModuleDefinition
6
- # @return [Arra<String>, nil]
7
- attr_reader :module_nesting
8
-
9
6
  # @return [String, nil]
10
- attr_reader :super_class_chained_name
7
+ attr_accessor :super_class_qualified_name
11
8
 
12
- # @return [String, nil]
13
- attr_accessor :super_class_fully_qualified_name
9
+ # @return [Rucoa::UnqualifiedName, nil]
10
+ attr_accessor :super_class_unqualified_name
14
11
 
15
- # @param module_nesting [Array<String>, nil]
16
- # @param super_class_chained_name [String, nil]
17
- # @param super_class_fully_qualified_name [String, nil]
12
+ # @param super_class_qualified_name [String, nil]
13
+ # @param super_class_unqualified_name [Rucoa::UnqualifiedName, nil]
18
14
  def initialize(
19
- module_nesting: nil,
20
- super_class_chained_name: nil,
21
- super_class_fully_qualified_name: nil,
15
+ super_class_qualified_name: nil,
16
+ super_class_unqualified_name: nil,
22
17
  **keyword_arguments
23
18
  )
24
19
  super(**keyword_arguments)
25
- @module_nesting = module_nesting
26
- @super_class_chained_name = super_class_chained_name
27
- @super_class_fully_qualified_name = super_class_fully_qualified_name
20
+ @super_class_qualified_name = super_class_qualified_name
21
+ @super_class_unqualified_name = super_class_unqualified_name
28
22
  end
29
23
 
30
- # @return [Boolean]
31
- # @example returns false on not-resolved case
32
- # definition = Rucoa::Definitions::ClassDefinition.new(
33
- # fully_qualified_name: 'Foo',
34
- # source_path: '/path/to/foo.rb',
35
- # super_class_chained_name: 'Bar'
36
- # )
37
- # expect(definition).not_to be_super_class_resolved
38
- # @example returns true on resolved case
39
- # definition = Rucoa::Definitions::ClassDefinition.new(
40
- # fully_qualified_name: 'Foo',
41
- # source_path: '/path/to/foo.rb',
42
- # super_class_chained_name: 'Bar',
43
- # super_class_fully_qualified_name: 'Bar'
44
- # )
45
- # expect(definition).to be_super_class_resolved
46
- def super_class_resolved?
47
- !@super_class_fully_qualified_name.nil?
48
- end
49
-
50
- # @return [Array<String>]
51
- # @example returns candidates of super class fully qualified name
52
- # class_definition = Rucoa::Definitions::ClassDefinition.new(
53
- # fully_qualified_name: nil,
54
- # module_nesting: %w[B::A B],
55
- # source_path: '/path/to/b/a/c.rb',
56
- # super_class_chained_name: 'C'
57
- # )
58
- # expect(class_definition.super_class_candidates).to eq(
59
- # %w[B::A::C B::C C]
60
- # )
61
- # @example returns only correct answer if it's already resolved
62
- # class_definition = Rucoa::Definitions::ClassDefinition.new(
63
- # fully_qualified_name: 'B::A::C',
64
- # source_path: '/path/to/b/a/c.rb',
65
- # super_class_fully_qualified_name: 'B::A::C'
66
- # )
67
- # expect(class_definition.super_class_candidates).to eq(
68
- # %w[B::A::C]
69
- # )
70
- def super_class_candidates
71
- return [super_class_fully_qualified_name] if super_class_resolved?
72
-
73
- module_nesting.map do |chained_name|
74
- [
75
- chained_name,
76
- super_class_chained_name
77
- ].join('::')
78
- end + [super_class_chained_name]
24
+ # @param other [Rucoa::Definitions::ClassDefinition]
25
+ def merge!(other)
26
+ self.super_class_qualified_name ||= other.super_class_qualified_name
27
+ self.super_class_unqualified_name ||= other.super_class_unqualified_name
28
+ super
79
29
  end
80
30
  end
81
31
  end