rucoa 0.9.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/Gemfile.lock +8 -8
- data/data/definitions_ruby_3_1 +0 -0
- data/lib/rucoa/configuration.rb +4 -1
- data/lib/rucoa/definition_store.rb +350 -105
- data/lib/rucoa/definitions/base.rb +14 -3
- data/lib/rucoa/definitions/class_definition.rb +14 -64
- data/lib/rucoa/definitions/constant_definition.rb +31 -19
- data/lib/rucoa/definitions/method_definition.rb +44 -52
- data/lib/rucoa/definitions/method_parameter_definition.rb +4 -1
- data/lib/rucoa/definitions/module_definition.rb +53 -0
- data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +14 -3
- data/lib/rucoa/handlers/base.rb +12 -3
- data/lib/rucoa/handlers/text_document_definition_handler.rb +3 -99
- data/lib/rucoa/handlers/text_document_hover_handler.rb +21 -13
- data/lib/rucoa/handlers/text_document_selection_range_handler.rb +8 -2
- data/lib/rucoa/location.rb +37 -0
- data/lib/rucoa/node_concerns/body.rb +24 -0
- data/lib/rucoa/node_concerns/{name_fully_qualifiable.rb → qualified_name.rb} +2 -2
- data/lib/rucoa/node_concerns.rb +2 -1
- data/lib/rucoa/node_inspector.rb +29 -23
- data/lib/rucoa/nodes/base.rb +22 -6
- data/lib/rucoa/nodes/begin_node.rb +8 -0
- data/lib/rucoa/nodes/casgn_node.rb +1 -1
- data/lib/rucoa/nodes/class_node.rb +2 -1
- data/lib/rucoa/nodes/const_node.rb +33 -15
- data/lib/rucoa/nodes/def_node.rb +2 -2
- data/lib/rucoa/nodes/defs_node.rb +1 -1
- data/lib/rucoa/nodes/module_node.rb +2 -1
- data/lib/rucoa/nodes.rb +2 -1
- data/lib/rucoa/parser.rb +14 -14
- data/lib/rucoa/parser_builder.rb +6 -1
- data/lib/rucoa/position.rb +10 -1
- data/lib/rucoa/range.rb +11 -1
- data/lib/rucoa/rbs/class_definition_mapper.rb +14 -28
- data/lib/rucoa/rbs/constant_definition_mapper.rb +12 -6
- data/lib/rucoa/rbs/method_definition_mapper.rb +12 -6
- data/lib/rucoa/rbs/module_definition_mapper.rb +39 -6
- data/lib/rucoa/rubocop/investigator.rb +4 -1
- data/lib/rucoa/server.rb +9 -3
- data/lib/rucoa/source.rb +19 -4
- data/lib/rucoa/unqualified_name.rb +9 -0
- data/lib/rucoa/version.rb +1 -1
- data/lib/rucoa/yard/definition_generators/attribute_reader_definition_generator.rb +76 -0
- data/lib/rucoa/yard/definition_generators/attribute_writer_definition_generator.rb +76 -0
- data/lib/rucoa/yard/definition_generators/base.rb +117 -0
- data/lib/rucoa/yard/definition_generators/class_definition_generator.rb +67 -0
- data/lib/rucoa/yard/definition_generators/constant_assignment_definition_generator.rb +29 -0
- data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +60 -0
- data/lib/rucoa/yard/definition_generators/module_definition_generator.rb +68 -0
- data/lib/rucoa/yard/definition_generators.rb +15 -0
- data/lib/rucoa/yard/definitions_loader.rb +1 -271
- data/lib/rucoa/yard.rb +1 -0
- data/lib/rucoa.rb +4 -2
- metadata +15 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cec8d0284ecf97b03cd43de02d36c16263910dba3c5a1052f73df0bf0fd51f68
|
4
|
+
data.tar.gz: b83c8aad102fbd510a0f7474394ab8cf91cd17976bbc365e188c276789815e9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3042168fc7a78f71854f96d8367f9f4e1e0c62d4300b4feef36b6596e602b3c40c5150d1d6f0902ab5d7b1015179cdf10c2d1e6beabe68cbf3fa1114f6cdb00e
|
7
|
+
data.tar.gz: 6721bdccd41cb883d6b6ab97a5a990b878e088a7832ccb6c42bcc642ff13f1ab3126d8893a43b47a29295caa0ff14ed4b59bdf5ab0ca95c14a4536dee11eb899
|
data/.rubocop.yml
CHANGED
@@ -32,9 +32,18 @@ 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/MethodDefinitionKeywordArgumentsOrdered:
|
42
|
+
Enabled: true
|
43
|
+
|
44
|
+
Sevencop/MethodDefinitionMultilineArguments:
|
45
|
+
Enabled: true
|
46
|
+
|
38
47
|
Style/Documentation:
|
39
48
|
Enabled: false
|
40
49
|
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rucoa (0.
|
4
|
+
rucoa (0.11.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.
|
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.
|
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.
|
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.
|
55
|
-
rubocop (~> 1.
|
54
|
+
rubocop-rspec (2.13.2)
|
55
|
+
rubocop (~> 1.33)
|
56
56
|
ruby-progressbar (1.11.0)
|
57
|
-
sevencop (0.
|
57
|
+
sevencop (0.13.0)
|
58
58
|
rubocop
|
59
|
-
unicode-display_width (2.
|
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)
|
data/data/definitions_ruby_3_1
CHANGED
Binary file
|
data/lib/rucoa/configuration.rb
CHANGED
@@ -3,22 +3,29 @@
|
|
3
3
|
module Rucoa
|
4
4
|
class DefinitionStore
|
5
5
|
def initialize
|
6
|
-
@
|
7
|
-
@
|
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.
|
14
|
-
|
15
|
-
|
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
|
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,115 +47,297 @@ module Rucoa
|
|
40
47
|
# uri: 'file:///path/to/a/bar.rb',
|
41
48
|
# )
|
42
49
|
# definition_store.update_from(bar)
|
43
|
-
# definition = definition_store.
|
44
|
-
# expect(definition.
|
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
|
-
|
47
|
-
|
48
|
-
|
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
|
83
|
+
# @param qualified_name [String]
|
65
84
|
# @return [Rucoa::Definitions::Base, nil]
|
66
|
-
def
|
67
|
-
@
|
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
|
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.
|
107
|
+
# definition_store.update_from(source)
|
77
108
|
# subject = definition_store.find_method_definition_by(
|
78
|
-
# method_name: '
|
79
|
-
# namespace: '
|
80
|
-
# singleton:
|
109
|
+
# method_name: 'foo',
|
110
|
+
# namespace: 'B',
|
111
|
+
# singleton: false
|
81
112
|
# )
|
82
|
-
# expect(subject.
|
83
|
-
|
84
|
-
|
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
|
-
|
93
|
-
|
171
|
+
qualified_method_name = [
|
172
|
+
ancestor.qualified_name,
|
94
173
|
method_marker,
|
95
174
|
method_name
|
96
175
|
].join
|
97
|
-
|
98
|
-
break
|
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
|
|
102
181
|
# @param type [String]
|
103
182
|
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
104
|
-
# @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
|
+
# )
|
105
228
|
# definition_store = Rucoa::DefinitionStore.new
|
106
|
-
# definition_store.
|
107
|
-
# subject = definition_store.instance_method_definitions_of('
|
108
|
-
# expect(subject.map(&:
|
109
|
-
# @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
|
+
# )
|
110
249
|
# definition_store = Rucoa::DefinitionStore.new
|
111
|
-
# definition_store.
|
112
|
-
# subject = definition_store.instance_method_definitions_of('
|
113
|
-
# expect(subject.map(&:
|
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])
|
114
253
|
def instance_method_definitions_of(type)
|
115
254
|
singleton_class_name = singleton_class_name_from(type)
|
116
255
|
return singleton_method_definitions_of(singleton_class_name) if singleton_class_name
|
117
256
|
|
118
|
-
class_or_module_definition =
|
257
|
+
class_or_module_definition = find_definition_by_qualified_name(type)
|
119
258
|
return [] unless class_or_module_definition
|
120
259
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
definitions.select do |definition|
|
127
|
-
definition.namespace == fully_qualified_type_name
|
260
|
+
method_definitions = self.method_definitions
|
261
|
+
ancestors_of(class_or_module_definition).flat_map do |ancestor|
|
262
|
+
method_definitions.select do |method_definition|
|
263
|
+
method_definition.namespace == ancestor.qualified_name &&
|
264
|
+
method_definition.instance_method?
|
128
265
|
end
|
129
|
-
end
|
266
|
+
end.uniq(&:method_name)
|
130
267
|
end
|
131
268
|
|
132
269
|
# @param type [String]
|
133
270
|
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
134
|
-
# @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
|
+
# )
|
135
298
|
# definition_store = Rucoa::DefinitionStore.new
|
136
|
-
# definition_store.
|
137
|
-
# subject = definition_store.singleton_method_definitions_of('
|
138
|
-
# expect(subject.map(&:
|
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
|
+
# )
|
321
|
+
# definition_store = Rucoa::DefinitionStore.new
|
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])
|
139
325
|
def singleton_method_definitions_of(type)
|
140
|
-
class_or_module_definition =
|
326
|
+
class_or_module_definition = find_definition_by_qualified_name(type)
|
141
327
|
return [] unless class_or_module_definition
|
142
328
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
329
|
+
method_definitions = self.method_definitions
|
330
|
+
ancestors_of(class_or_module_definition).flat_map do |ancestor|
|
331
|
+
method_definitions.select do |method_definition|
|
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
|
150
339
|
end
|
151
|
-
end
|
340
|
+
end.uniq(&:method_name)
|
152
341
|
end
|
153
342
|
|
154
343
|
# @param namespace [String]
|
@@ -159,42 +348,79 @@ module Rucoa
|
|
159
348
|
end
|
160
349
|
end
|
161
350
|
|
351
|
+
# @todo Search ancestors.
|
352
|
+
# @param unqualified_name [Rucoa::UnqualifiedName]
|
353
|
+
# @return [String]
|
354
|
+
def resolve_constant(unqualified_name)
|
355
|
+
(
|
356
|
+
unqualified_name.module_nesting.map do |prefix|
|
357
|
+
"#{prefix}::#{unqualified_name.chained_name}"
|
358
|
+
end + [unqualified_name.chained_name]
|
359
|
+
).find do |candidate|
|
360
|
+
find_definition_by_qualified_name(candidate)
|
361
|
+
end || unqualified_name.chained_name
|
362
|
+
end
|
363
|
+
|
162
364
|
private
|
163
365
|
|
164
366
|
# @param source [Rucoa::Source]
|
165
367
|
# @return [void]
|
166
|
-
def
|
167
|
-
@
|
168
|
-
@
|
368
|
+
def delete_definitions_in(source)
|
369
|
+
@qualified_names_by_uri[source.uri].each do |qualified_name|
|
370
|
+
@definition_by_qualified_name.delete(qualified_name)
|
169
371
|
end
|
170
|
-
@
|
372
|
+
@qualified_names_by_uri.delete(source.uri)
|
171
373
|
end
|
172
374
|
|
173
375
|
# @param type [String]
|
174
376
|
# @return [String, nil]
|
175
377
|
def singleton_class_name_from(type)
|
176
|
-
type[/singleton<(\w+)>/, 1]
|
378
|
+
type[/singleton<([\w:]+)>/, 1]
|
379
|
+
end
|
380
|
+
|
381
|
+
# @param definition [Rucoa::Definitions::Class, Rucoa::Definitions::Module]
|
382
|
+
# @return [Array<Rucoa::Definitions::Class>] The classes and modules that are traced in method search (as `Module#ancestors` in Ruby)
|
383
|
+
def ancestors_of(definition)
|
384
|
+
if definition.is_a?(Rucoa::Definitions::ClassDefinition)
|
385
|
+
[definition, *super_class_definitions_of(definition)]
|
386
|
+
else
|
387
|
+
[definition]
|
388
|
+
end.flat_map do |base|
|
389
|
+
module_ancestors_of(base)
|
390
|
+
end
|
177
391
|
end
|
178
392
|
|
179
|
-
# @param
|
180
|
-
# @return [Array<Rucoa::Definitions::Class>]
|
181
|
-
def
|
182
|
-
|
393
|
+
# @param definition [Rucoa::Definitions::Class, Rucoa::Definitions::Module]
|
394
|
+
# @return [Array<Rucoa::Definitions::Class, Rucoa::Definitions::Module>] An array of prepended, itself, and included definitions
|
395
|
+
def module_ancestors_of(definition)
|
396
|
+
[
|
397
|
+
*definition.prepended_module_qualified_names.filter_map do |qualified_name|
|
398
|
+
find_definition_by_qualified_name(qualified_name)
|
399
|
+
end.reverse,
|
400
|
+
definition,
|
401
|
+
*definition.included_module_qualified_names.filter_map do |qualified_name|
|
402
|
+
find_definition_by_qualified_name(qualified_name)
|
403
|
+
end.reverse
|
404
|
+
]
|
405
|
+
end
|
183
406
|
|
407
|
+
# @param definition [Rucoa::Definitions::Class]
|
408
|
+
# @return [Array<Rucoa::Definitions::Class>] super "class"es (not including modules) in closest-first order
|
409
|
+
def super_class_definitions_of(definition)
|
184
410
|
result = []
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
break unless class_definition
|
411
|
+
while (super_class_qualified_name = definition.super_class_qualified_name)
|
412
|
+
super_definition = find_definition_by_qualified_name(super_class_qualified_name)
|
413
|
+
break unless super_definition
|
189
414
|
|
190
|
-
result <<
|
415
|
+
result << super_definition
|
416
|
+
definition = super_definition
|
191
417
|
end
|
192
418
|
result
|
193
419
|
end
|
194
420
|
|
195
421
|
# @return [Array<Rucoa::Definitions::Base>]
|
196
422
|
def definitions
|
197
|
-
@
|
423
|
+
@definition_by_qualified_name.values
|
198
424
|
end
|
199
425
|
|
200
426
|
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
@@ -202,29 +428,48 @@ module Rucoa
|
|
202
428
|
definitions.grep(Definitions::MethodDefinition)
|
203
429
|
end
|
204
430
|
|
205
|
-
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
206
|
-
def instance_method_definitions
|
207
|
-
method_definitions.select(&:instance_method?)
|
208
|
-
end
|
209
|
-
|
210
|
-
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
211
|
-
def singleton_method_definitions
|
212
|
-
method_definitions.select(&:singleton_method?)
|
213
|
-
end
|
214
|
-
|
215
431
|
# @return [Array<Rucoa::Definition::ConstantDefinition>]
|
216
432
|
def constant_definitions
|
217
433
|
definitions.grep(Definitions::ConstantDefinition)
|
218
434
|
end
|
219
435
|
|
220
|
-
# @param
|
221
|
-
# @return [
|
222
|
-
def
|
223
|
-
|
436
|
+
# @param source [Rucoa::Source]
|
437
|
+
# @return [void]
|
438
|
+
def add_definitions_in(source)
|
439
|
+
source.definitions.group_by do |definition|
|
440
|
+
definition.location.uri
|
441
|
+
end.each do |uri, definitions|
|
442
|
+
@qualified_names_by_uri[uri] += definitions.map(&:qualified_name)
|
443
|
+
definitions.each do |definition|
|
444
|
+
@definition_by_qualified_name[definition.qualified_name] = definition
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
# @param source [Rucoa::Source]
|
450
|
+
# @return [void]
|
451
|
+
def resolve_constants_in(source)
|
452
|
+
source.definitions.each do |definition|
|
453
|
+
next unless definition.is_a?(Definitions::ClassDefinition)
|
454
|
+
|
455
|
+
definition.super_class_qualified_name = resolve_constant(definition.super_class_unqualified_name)
|
456
|
+
definition.super_class_unqualified_name = nil
|
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 = []
|
224
462
|
|
225
|
-
|
226
|
-
|
227
|
-
|
463
|
+
definition.included_module_qualified_names = definition.included_module_unqualified_names.map do |unqualified_name|
|
464
|
+
resolve_constant(unqualified_name)
|
465
|
+
end
|
466
|
+
definition.included_module_unqualified_names = []
|
467
|
+
|
468
|
+
definition.prepended_module_qualified_names = definition.prepended_module_unqualified_names.map do |unqualified_name|
|
469
|
+
resolve_constant(unqualified_name)
|
470
|
+
end
|
471
|
+
definition.prepended_module_unqualified_names = []
|
472
|
+
end
|
228
473
|
end
|
229
474
|
end
|
230
475
|
end
|
@@ -3,9 +3,20 @@
|
|
3
3
|
module Rucoa
|
4
4
|
module Definitions
|
5
5
|
class Base
|
6
|
-
# @return [String]
|
7
|
-
|
8
|
-
|
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
|