rucoa 0.8.0 → 0.10.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 +6 -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 +268 -75
- data/lib/rucoa/definitions/base.rb +14 -3
- data/lib/rucoa/definitions/class_definition.rb +20 -4
- 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 +39 -0
- data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +14 -3
- data/lib/rucoa/handlers/base.rb +12 -3
- data/lib/rucoa/handlers/initialized_handler.rb +33 -5
- data/lib/rucoa/handlers/text_document_completion_handler.rb +1 -1
- data/lib/rucoa/handlers/text_document_definition_handler.rb +3 -99
- data/lib/rucoa/handlers/text_document_did_open_handler.rb +1 -4
- 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_full_qualifiable.rb → qualified_name.rb} +2 -2
- data/lib/rucoa/node_concerns.rb +2 -1
- data/lib/rucoa/node_inspector.rb +22 -26
- data/lib/rucoa/nodes/base.rb +51 -10
- data/lib/rucoa/nodes/begin_node.rb +8 -0
- data/lib/rucoa/nodes/casgn_node.rb +1 -1
- data/lib/rucoa/nodes/cbase_node.rb +8 -0
- data/lib/rucoa/nodes/class_node.rb +63 -1
- data/lib/rucoa/nodes/const_node.rb +64 -5
- data/lib/rucoa/nodes/def_node.rb +11 -9
- data/lib/rucoa/nodes/defs_node.rb +21 -0
- data/lib/rucoa/nodes/lvar_node.rb +2 -1
- data/lib/rucoa/nodes/module_node.rb +2 -1
- data/lib/rucoa/nodes/send_node.rb +14 -10
- data/lib/rucoa/nodes.rb +3 -1
- data/lib/rucoa/parse_result.rb +29 -0
- data/lib/rucoa/parser.rb +40 -8
- data/lib/rucoa/parser_builder.rb +7 -1
- data/lib/rucoa/position.rb +10 -1
- data/lib/rucoa/range.rb +11 -1
- data/lib/rucoa/rbs/class_definition_mapper.rb +13 -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 +34 -6
- data/lib/rucoa/rubocop/autocorrector.rb +2 -2
- data/lib/rucoa/rubocop/investigator.rb +6 -3
- data/lib/rucoa/server.rb +9 -3
- data/lib/rucoa/source.rb +57 -27
- data/lib/rucoa/source_store.rb +0 -13
- 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 +60 -0
- data/lib/rucoa/yard/definition_generators/attribute_writer_definition_generator.rb +60 -0
- data/lib/rucoa/yard/definition_generators/base.rb +117 -0
- data/lib/rucoa/yard/definition_generators/class_definition_generator.rb +66 -0
- data/lib/rucoa/yard/definition_generators/constant_assignment_definition_generator.rb +29 -0
- data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +47 -0
- data/lib/rucoa/yard/definition_generators/module_definition_generator.rb +62 -0
- data/lib/rucoa/yard/definition_generators.rb +15 -0
- data/lib/rucoa/yard/definitions_loader.rb +44 -65
- data/lib/rucoa/yard/type.rb +46 -0
- data/lib/rucoa/yard.rb +2 -1
- data/lib/rucoa.rb +4 -1
- metadata +18 -4
- data/lib/rucoa/yard/method_definition_mapper.rb +0 -215
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3344309136313473ea6d4fecd4c57745fb4bc8fc1404c40f7126c0a5d5eef440
|
4
|
+
data.tar.gz: 1bfb57eee21c860f54b8c82452717d987a31bc977a5a7853b6e08b0d486fd5ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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.12.1)
|
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
@@ -2,48 +2,179 @@
|
|
2
2
|
|
3
3
|
module Rucoa
|
4
4
|
class DefinitionStore
|
5
|
-
# @return [Array<Rucoa::Definition::Base>]
|
6
|
-
attr_accessor :definitions
|
7
|
-
|
8
5
|
def initialize
|
9
|
-
@
|
6
|
+
@definition_by_qualified_name = {}
|
7
|
+
@qualified_names_by_uri = ::Hash.new { |hash, key| hash[key] = [] }
|
10
8
|
end
|
11
9
|
|
12
|
-
# @
|
13
|
-
|
14
|
-
|
15
|
-
delete_definitions_defined_in(source_path)
|
16
|
-
@definitions += definitions
|
10
|
+
# @return [String]
|
11
|
+
def inspect
|
12
|
+
"#<#{self.class} definitions_count=#{@definition_by_qualified_name.count}>"
|
17
13
|
end
|
18
14
|
|
19
|
-
# @param
|
20
|
-
# @return [
|
21
|
-
def
|
22
|
-
|
23
|
-
|
15
|
+
# @param definitions [Array<Rucoa::Definition::Base>]
|
16
|
+
# @return [void]
|
17
|
+
def bulk_add(definitions)
|
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
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
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)
|
81
|
+
end
|
82
|
+
|
83
|
+
# @param qualified_name [String]
|
84
|
+
# @return [Rucoa::Definitions::Base, nil]
|
85
|
+
def find_definition_by_qualified_name(qualified_name)
|
86
|
+
@definition_by_qualified_name[qualified_name]
|
87
|
+
end
|
88
|
+
|
27
89
|
# @param method_name [String]
|
28
90
|
# @param namespace [String]
|
29
91
|
# @param singleton [Boolean]
|
30
92
|
# @return [Rucoa::Definition::MethodDefinition, nil]
|
31
|
-
# @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
|
+
# )
|
32
106
|
# definition_store = Rucoa::DefinitionStore.new
|
33
|
-
# definition_store.
|
107
|
+
# definition_store.update_from(source)
|
34
108
|
# subject = definition_store.find_method_definition_by(
|
35
|
-
# method_name: '
|
36
|
-
# namespace: '
|
37
|
-
# singleton:
|
109
|
+
# method_name: 'foo',
|
110
|
+
# namespace: 'B',
|
111
|
+
# singleton: false
|
38
112
|
# )
|
39
|
-
# expect(subject.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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)
|
167
|
+
return unless definition
|
168
|
+
|
169
|
+
ancestors_of(definition).find do |ancestor|
|
170
|
+
method_marker = singleton ? '.' : '#'
|
171
|
+
qualified_method_name = [
|
172
|
+
ancestor.qualified_name,
|
173
|
+
method_marker,
|
174
|
+
method_name
|
175
|
+
].join
|
176
|
+
method_definition = find_definition_by_qualified_name(qualified_method_name)
|
177
|
+
break method_definition if method_definition
|
47
178
|
end
|
48
179
|
end
|
49
180
|
|
@@ -51,28 +182,25 @@ module Rucoa
|
|
51
182
|
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
52
183
|
# @example includes ancestors' methods
|
53
184
|
# definition_store = Rucoa::DefinitionStore.new
|
54
|
-
# definition_store.
|
185
|
+
# definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
|
55
186
|
# subject = definition_store.instance_method_definitions_of('File')
|
56
|
-
# expect(subject.map(&:
|
187
|
+
# expect(subject.map(&:qualified_name)).to include('IO#raw')
|
57
188
|
# @example responds to `singleton<File>`
|
58
189
|
# definition_store = Rucoa::DefinitionStore.new
|
59
|
-
# definition_store.
|
190
|
+
# definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
|
60
191
|
# subject = definition_store.instance_method_definitions_of('singleton<File>')
|
61
|
-
# expect(subject.map(&:
|
192
|
+
# expect(subject.map(&:qualified_name)).to include('IO.write')
|
62
193
|
def instance_method_definitions_of(type)
|
63
194
|
singleton_class_name = singleton_class_name_from(type)
|
64
195
|
return singleton_method_definitions_of(singleton_class_name) if singleton_class_name
|
65
196
|
|
66
|
-
class_or_module_definition =
|
197
|
+
class_or_module_definition = find_definition_by_qualified_name(type)
|
67
198
|
return [] unless class_or_module_definition
|
68
199
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
].map(&:full_qualified_name).flat_map do |full_qualified_type_name|
|
74
|
-
definitions.select do |definition|
|
75
|
-
definition.namespace == full_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
|
76
204
|
end
|
77
205
|
end
|
78
206
|
end
|
@@ -81,29 +209,21 @@ module Rucoa
|
|
81
209
|
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
82
210
|
# @example returns singleton method definitions of File
|
83
211
|
# definition_store = Rucoa::DefinitionStore.new
|
84
|
-
# definition_store.
|
212
|
+
# definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
|
85
213
|
# subject = definition_store.singleton_method_definitions_of('File')
|
86
|
-
# expect(subject.map(&:
|
214
|
+
# expect(subject.map(&:qualified_name)).to include('IO.write')
|
87
215
|
def singleton_method_definitions_of(type)
|
88
|
-
class_or_module_definition =
|
216
|
+
class_or_module_definition = find_definition_by_qualified_name(type)
|
89
217
|
return [] unless class_or_module_definition
|
90
218
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
].map(&:full_qualified_name).flat_map do |full_qualified_type_name|
|
96
|
-
definitions.select do |definition|
|
97
|
-
definition.namespace == full_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
|
98
223
|
end
|
99
224
|
end
|
100
225
|
end
|
101
226
|
|
102
|
-
# @return [Array<Rucoa::Definition::ConstantDefinition>]
|
103
|
-
def constant_definitions
|
104
|
-
@definitions.grep(Definitions::ConstantDefinition)
|
105
|
-
end
|
106
|
-
|
107
227
|
# @param namespace [String]
|
108
228
|
# @return [Array<Rucoa::Definitions::ConstantDefinition>] e.g. File::Separator, File::SEPARATOR, etc.
|
109
229
|
def constant_definitions_under(namespace)
|
@@ -112,41 +232,83 @@ module Rucoa
|
|
112
232
|
end
|
113
233
|
end
|
114
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
|
+
|
115
247
|
private
|
116
248
|
|
249
|
+
# @param source [Rucoa::Source]
|
250
|
+
# @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)
|
254
|
+
end
|
255
|
+
@qualified_names_by_uri.delete(source.uri)
|
256
|
+
end
|
257
|
+
|
117
258
|
# @param type [String]
|
118
259
|
# @return [String, nil]
|
119
260
|
def singleton_class_name_from(type)
|
120
261
|
type[/singleton<(\w+)>/, 1]
|
121
262
|
end
|
122
263
|
|
123
|
-
# @param
|
124
|
-
# @return [Array<Rucoa::Definitions::Class>]
|
125
|
-
def
|
126
|
-
|
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
|
127
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)
|
128
293
|
result = []
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
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
|
133
297
|
|
134
|
-
result <<
|
298
|
+
result << super_definition
|
299
|
+
definition = super_definition
|
135
300
|
end
|
136
301
|
result
|
137
302
|
end
|
138
303
|
|
139
|
-
# @
|
140
|
-
|
141
|
-
|
142
|
-
@definitions.find do |definition|
|
143
|
-
definition.full_qualified_name == type
|
144
|
-
end
|
304
|
+
# @return [Array<Rucoa::Definitions::Base>]
|
305
|
+
def definitions
|
306
|
+
@definition_by_qualified_name.values
|
145
307
|
end
|
146
308
|
|
147
309
|
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
148
310
|
def method_definitions
|
149
|
-
|
311
|
+
definitions.grep(Definitions::MethodDefinition)
|
150
312
|
end
|
151
313
|
|
152
314
|
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
@@ -159,11 +321,42 @@ module Rucoa
|
|
159
321
|
method_definitions.select(&:singleton_method?)
|
160
322
|
end
|
161
323
|
|
162
|
-
# @
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
324
|
+
# @return [Array<Rucoa::Definition::ConstantDefinition>]
|
325
|
+
def constant_definitions
|
326
|
+
definitions.grep(Definitions::ConstantDefinition)
|
327
|
+
end
|
328
|
+
|
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
|
341
|
+
|
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 = []
|
167
360
|
end
|
168
361
|
end
|
169
362
|
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
|
@@ -4,12 +4,28 @@ module Rucoa
|
|
4
4
|
module Definitions
|
5
5
|
class ClassDefinition < ModuleDefinition
|
6
6
|
# @return [String, nil]
|
7
|
-
|
7
|
+
attr_accessor :super_class_qualified_name
|
8
8
|
|
9
|
-
# @
|
10
|
-
|
9
|
+
# @return [Rucoa::UnqualifiedName, nil]
|
10
|
+
attr_accessor :super_class_unqualified_name
|
11
|
+
|
12
|
+
# @param super_class_qualified_name [String, nil]
|
13
|
+
# @param super_class_unqualified_name [Rucoa::UnqualifiedName, nil]
|
14
|
+
def initialize(
|
15
|
+
super_class_qualified_name: nil,
|
16
|
+
super_class_unqualified_name: nil,
|
17
|
+
**keyword_arguments
|
18
|
+
)
|
11
19
|
super(**keyword_arguments)
|
12
|
-
@
|
20
|
+
@super_class_qualified_name = super_class_qualified_name
|
21
|
+
@super_class_unqualified_name = super_class_unqualified_name
|
22
|
+
end
|
23
|
+
|
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
|
13
29
|
end
|
14
30
|
end
|
15
31
|
end
|
@@ -5,25 +5,30 @@ module Rucoa
|
|
5
5
|
# Represents class definition, module definition, or constant assignment.
|
6
6
|
class ConstantDefinition < Base
|
7
7
|
# @return [String]
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :qualified_name
|
9
9
|
|
10
|
-
# @
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@full_qualified_name = full_qualified_name
|
18
|
-
@source_path = source_path
|
10
|
+
# @param qualified_name [String]
|
11
|
+
def initialize(
|
12
|
+
qualified_name:,
|
13
|
+
**keyword_arguments
|
14
|
+
)
|
15
|
+
super(**keyword_arguments)
|
16
|
+
@qualified_name = qualified_name
|
19
17
|
end
|
20
18
|
|
21
19
|
# @return [String]
|
22
20
|
# @example returns non-full-qualified name
|
23
|
-
# definition = Rucoa::
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
21
|
+
# definition = Rucoa::Source.new(
|
22
|
+
# content: <<~RUBY,
|
23
|
+
# module Foo
|
24
|
+
# module Bar
|
25
|
+
# class Baz
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
# RUBY
|
30
|
+
# uri: 'file:///path/to/foo/bar/baz.rb',
|
31
|
+
# ).definitions[2]
|
27
32
|
# expect(definition.name).to eq('Baz')
|
28
33
|
def name
|
29
34
|
names.last
|
@@ -31,10 +36,17 @@ module Rucoa
|
|
31
36
|
|
32
37
|
# @return [String]
|
33
38
|
# @example returns namespace
|
34
|
-
# definition = Rucoa::
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
39
|
+
# definition = Rucoa::Source.new(
|
40
|
+
# content: <<~RUBY,
|
41
|
+
# module Foo
|
42
|
+
# module Bar
|
43
|
+
# class Baz
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
# RUBY
|
48
|
+
# uri: 'file:///path/to/foo/bar/baz.rb',
|
49
|
+
# ).definitions[2]
|
38
50
|
# expect(definition.namespace).to eq('Foo::Bar')
|
39
51
|
def namespace
|
40
52
|
names[..-2].join('::')
|
@@ -44,7 +56,7 @@ module Rucoa
|
|
44
56
|
|
45
57
|
# @return [Array<String>]
|
46
58
|
def names
|
47
|
-
@names ||=
|
59
|
+
@names ||= qualified_name.split('::')
|
48
60
|
end
|
49
61
|
end
|
50
62
|
end
|