rucoa 0.8.0 → 0.10.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 +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
|