rucoa 0.7.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +4 -1
- data/data/definitions_ruby_3_1 +0 -0
- data/lib/rucoa/configuration.rb +10 -0
- data/lib/rucoa/definition_store.rb +194 -27
- data/lib/rucoa/definitions/class_definition.rb +82 -0
- data/lib/rucoa/definitions/constant_definition.rb +7 -7
- data/lib/rucoa/definitions/method_definition.rb +18 -6
- data/lib/rucoa/definitions/module_definition.rb +8 -0
- data/lib/rucoa/definitions.rb +2 -0
- data/lib/rucoa/handlers/initialize_handler.rb +1 -0
- data/lib/rucoa/handlers/initialized_handler.rb +33 -5
- data/lib/rucoa/handlers/text_document_completion_handler.rb +2 -2
- data/lib/rucoa/handlers/text_document_definition_handler.rb +155 -0
- data/lib/rucoa/handlers/text_document_did_open_handler.rb +1 -4
- data/lib/rucoa/handlers/text_document_hover_handler.rb +3 -4
- data/lib/rucoa/handlers.rb +1 -0
- data/lib/rucoa/node_concerns/{name_full_qualifiable.rb → name_fully_qualifiable.rb} +2 -2
- data/lib/rucoa/node_concerns.rb +1 -1
- data/lib/rucoa/node_inspector.rb +56 -34
- data/lib/rucoa/nodes/base.rb +32 -7
- 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 +62 -1
- data/lib/rucoa/nodes/const_node.rb +72 -0
- 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 +1 -1
- data/lib/rucoa/nodes/send_node.rb +14 -10
- data/lib/rucoa/nodes.rb +1 -0
- data/lib/rucoa/parse_result.rb +29 -0
- data/lib/rucoa/parser.rb +40 -8
- data/lib/rucoa/parser_builder.rb +1 -0
- data/lib/rucoa/position.rb +1 -1
- data/lib/rucoa/rbs/class_definition_mapper.rb +46 -0
- data/lib/rucoa/rbs/constant_definition_mapper.rb +2 -2
- data/lib/rucoa/rbs/module_definition_mapper.rb +40 -0
- data/lib/rucoa/rbs/ruby_definitions_loader.rb +11 -7
- data/lib/rucoa/rbs.rb +2 -0
- data/lib/rucoa/rubocop/autocorrector.rb +12 -1
- data/lib/rucoa/rubocop/investigator.rb +10 -1
- data/lib/rucoa/server.rb +2 -1
- data/lib/rucoa/source.rb +47 -24
- data/lib/rucoa/source_store.rb +0 -13
- data/lib/rucoa/version.rb +1 -1
- data/lib/rucoa/yard/definitions_loader.rb +320 -48
- data/lib/rucoa/yard/type.rb +46 -0
- data/lib/rucoa/yard.rb +1 -1
- data/lib/rucoa.rb +1 -0
- metadata +11 -4
- data/lib/rucoa/yard/definition_mapper.rb +0 -217
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 237fa68185426d66437c43fc2a3f34f7f85ee7309eb4ed6bb6ce4e31b5dfbb6e
|
4
|
+
data.tar.gz: e9f96daf65c7ccef564b2e06756497fd4d98bd946911487ca2fdd32740436e4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3698e9db246d46ce64314df9b4a7418278a6e9f65cc2e80dfece624b547c5ab238af42b456370d1096e872f6e30aefdb132b5b2bd435ec03d1e6cccdac0a908a
|
7
|
+
data.tar.gz: 5088d4dcc1fa5ad6e053a155246da87602071fa8283b4f42e1b4e9040b222be5f82622343ad2467b5cdf8003b02293e70ea8d391dc99f478ee36a1389311a9d4
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -62,6 +62,10 @@ This extension supports the folowiing types of symbols:
|
|
62
62
|
|
63
63
|
Provides completion items for constant names and method names.
|
64
64
|
|
65
|
+
### Definition
|
66
|
+
|
67
|
+
Provides "Go to Definition" command to jump to the definition.
|
68
|
+
|
65
69
|
### Hover
|
66
70
|
|
67
71
|
Shows documentation for the symbol under the cursor.
|
@@ -72,6 +76,5 @@ Shows method signature help when you start to type method arguments like `"100".
|
|
72
76
|
|
73
77
|
## Coming soon
|
74
78
|
|
75
|
-
- Go to Definition
|
76
79
|
- Highlight
|
77
80
|
- Semantic Tokens
|
data/data/definitions_ruby_3_1
CHANGED
Binary file
|
data/lib/rucoa/configuration.rb
CHANGED
@@ -16,6 +16,11 @@ module Rucoa
|
|
16
16
|
disable_feature('completion')
|
17
17
|
end
|
18
18
|
|
19
|
+
# @return [void]
|
20
|
+
def disable_definition
|
21
|
+
disable_feature('definition')
|
22
|
+
end
|
23
|
+
|
19
24
|
# @return [void]
|
20
25
|
def disable_diagnostics
|
21
26
|
disable_feature('diagnostics')
|
@@ -82,6 +87,11 @@ module Rucoa
|
|
82
87
|
enables_feature?('completion')
|
83
88
|
end
|
84
89
|
|
90
|
+
# @return [Boolean]
|
91
|
+
def enables_definition?
|
92
|
+
enables_feature?('definition')
|
93
|
+
end
|
94
|
+
|
85
95
|
# @return [Boolean]
|
86
96
|
def enables_diagnostics?
|
87
97
|
enables_feature?('diagnostics')
|
@@ -2,33 +2,152 @@
|
|
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_full_qualified_name = {}
|
7
|
+
@fully_qualified_names_by_uri = ::Hash.new { |hash, key| hash[key] = [] }
|
10
8
|
end
|
11
9
|
|
12
|
-
# @param
|
13
|
-
# @return [
|
14
|
-
def
|
15
|
-
|
16
|
-
|
10
|
+
# @param definitions [Array<Rucoa::Definition::Base>]
|
11
|
+
# @return [void]
|
12
|
+
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
|
16
|
+
end
|
17
17
|
end
|
18
18
|
|
19
|
-
# @param
|
20
|
-
# @return [
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
# @param source [Rucoa::Source]
|
20
|
+
# @return [void]
|
21
|
+
# @example resolves super class name correctly by using existent definitions
|
22
|
+
# definition_store = Rucoa::DefinitionStore.new
|
23
|
+
# foo = Rucoa::Source.new(
|
24
|
+
# content: <<~RUBY,
|
25
|
+
# module A
|
26
|
+
# class Foo
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
# RUBY
|
30
|
+
# uri: 'file:///path/to/a/foo.rb',
|
31
|
+
# )
|
32
|
+
# definition_store.update_from(foo)
|
33
|
+
# bar = Rucoa::Source.new(
|
34
|
+
# content: <<~RUBY,
|
35
|
+
# module A
|
36
|
+
# class Bar < Foo
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
# RUBY
|
40
|
+
# uri: 'file:///path/to/a/bar.rb',
|
41
|
+
# )
|
42
|
+
# 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')
|
45
|
+
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)
|
24
61
|
end
|
25
62
|
end
|
26
63
|
|
64
|
+
# @param fully_qualified_name [String]
|
65
|
+
# @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]
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param method_name [String]
|
27
71
|
# @param namespace [String]
|
72
|
+
# @param singleton [Boolean]
|
73
|
+
# @return [Rucoa::Definition::MethodDefinition, nil]
|
74
|
+
# @example has the ability to find `IO.write` from `File.write`
|
75
|
+
# definition_store = Rucoa::DefinitionStore.new
|
76
|
+
# definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
|
77
|
+
# subject = definition_store.find_method_definition_by(
|
78
|
+
# method_name: 'write',
|
79
|
+
# namespace: 'File',
|
80
|
+
# singleton: true
|
81
|
+
# )
|
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)
|
85
|
+
return unless definition
|
86
|
+
|
87
|
+
[
|
88
|
+
namespace,
|
89
|
+
*ancestor_definitions_of(definition).map(&:fully_qualified_name)
|
90
|
+
].find do |fully_qualified_name|
|
91
|
+
method_marker = singleton ? '.' : '#'
|
92
|
+
fully_qualified_method_name = [
|
93
|
+
fully_qualified_name,
|
94
|
+
method_marker,
|
95
|
+
method_name
|
96
|
+
].join
|
97
|
+
definition = find_definition_by_fully_qualified_name(fully_qualified_method_name)
|
98
|
+
break definition if definition
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# @param type [String]
|
28
103
|
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
29
|
-
|
30
|
-
|
31
|
-
|
104
|
+
# @example includes ancestors' methods
|
105
|
+
# definition_store = Rucoa::DefinitionStore.new
|
106
|
+
# definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
|
107
|
+
# subject = definition_store.instance_method_definitions_of('File')
|
108
|
+
# expect(subject.map(&:fully_qualified_name)).to include('IO#raw')
|
109
|
+
# @example responds to `singleton<File>`
|
110
|
+
# definition_store = Rucoa::DefinitionStore.new
|
111
|
+
# definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
|
112
|
+
# subject = definition_store.instance_method_definitions_of('singleton<File>')
|
113
|
+
# expect(subject.map(&:fully_qualified_name)).to include('IO.write')
|
114
|
+
def instance_method_definitions_of(type)
|
115
|
+
singleton_class_name = singleton_class_name_from(type)
|
116
|
+
return singleton_method_definitions_of(singleton_class_name) if singleton_class_name
|
117
|
+
|
118
|
+
class_or_module_definition = find_definition_by_fully_qualified_name(type)
|
119
|
+
return [] unless class_or_module_definition
|
120
|
+
|
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
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param type [String]
|
133
|
+
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
134
|
+
# @example returns singleton method definitions of File
|
135
|
+
# definition_store = Rucoa::DefinitionStore.new
|
136
|
+
# definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
|
137
|
+
# subject = definition_store.singleton_method_definitions_of('File')
|
138
|
+
# expect(subject.map(&:fully_qualified_name)).to include('IO.write')
|
139
|
+
def singleton_method_definitions_of(type)
|
140
|
+
class_or_module_definition = find_definition_by_fully_qualified_name(type)
|
141
|
+
return [] unless class_or_module_definition
|
142
|
+
|
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
|
150
|
+
end
|
32
151
|
end
|
33
152
|
end
|
34
153
|
|
@@ -42,22 +161,70 @@ module Rucoa
|
|
42
161
|
|
43
162
|
private
|
44
163
|
|
45
|
-
# @
|
46
|
-
|
47
|
-
|
164
|
+
# @param source [Rucoa::Source]
|
165
|
+
# @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)
|
169
|
+
end
|
170
|
+
@fully_qualified_names_by_uri.delete(source.uri)
|
171
|
+
end
|
172
|
+
|
173
|
+
# @param type [String]
|
174
|
+
# @return [String, nil]
|
175
|
+
def singleton_class_name_from(type)
|
176
|
+
type[/singleton<(\w+)>/, 1]
|
177
|
+
end
|
178
|
+
|
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)
|
183
|
+
|
184
|
+
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
|
189
|
+
|
190
|
+
result << class_definition
|
191
|
+
end
|
192
|
+
result
|
193
|
+
end
|
194
|
+
|
195
|
+
# @return [Array<Rucoa::Definitions::Base>]
|
196
|
+
def definitions
|
197
|
+
@definition_by_full_qualified_name.values
|
48
198
|
end
|
49
199
|
|
50
200
|
# @return [Array<Rucoa::Definition::MethodDefinition>]
|
51
201
|
def method_definitions
|
52
|
-
|
202
|
+
definitions.grep(Definitions::MethodDefinition)
|
53
203
|
end
|
54
204
|
|
55
|
-
# @
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
+
# @return [Array<Rucoa::Definition::ConstantDefinition>]
|
216
|
+
def constant_definitions
|
217
|
+
definitions.grep(Definitions::ConstantDefinition)
|
218
|
+
end
|
219
|
+
|
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
|
224
|
+
|
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
|
61
228
|
end
|
62
229
|
end
|
63
230
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Definitions
|
5
|
+
class ClassDefinition < ModuleDefinition
|
6
|
+
# @return [Arra<String>, nil]
|
7
|
+
attr_reader :module_nesting
|
8
|
+
|
9
|
+
# @return [String, nil]
|
10
|
+
attr_reader :super_class_chained_name
|
11
|
+
|
12
|
+
# @return [String, nil]
|
13
|
+
attr_accessor :super_class_fully_qualified_name
|
14
|
+
|
15
|
+
# @param module_nesting [Array<String>, nil]
|
16
|
+
# @param super_class_chained_name [String, nil]
|
17
|
+
# @param super_class_fully_qualified_name [String, nil]
|
18
|
+
def initialize(
|
19
|
+
module_nesting: nil,
|
20
|
+
super_class_chained_name: nil,
|
21
|
+
super_class_fully_qualified_name: nil,
|
22
|
+
**keyword_arguments
|
23
|
+
)
|
24
|
+
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
|
28
|
+
end
|
29
|
+
|
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]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -5,23 +5,23 @@ 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 :fully_qualified_name
|
9
9
|
|
10
10
|
# @return [String]
|
11
11
|
attr_reader :source_path
|
12
12
|
|
13
|
-
# @param
|
13
|
+
# @param fully_qualified_name [String]
|
14
14
|
# @param source_path [String]
|
15
|
-
def initialize(
|
15
|
+
def initialize(fully_qualified_name:, source_path:)
|
16
16
|
super()
|
17
|
-
@
|
17
|
+
@fully_qualified_name = fully_qualified_name
|
18
18
|
@source_path = source_path
|
19
19
|
end
|
20
20
|
|
21
21
|
# @return [String]
|
22
22
|
# @example returns non-full-qualified name
|
23
23
|
# definition = Rucoa::Definitions::ConstantDefinition.new(
|
24
|
-
#
|
24
|
+
# fully_qualified_name: 'Foo::Bar::Baz',
|
25
25
|
# source_path: '/path/to/foo/bar/baz.rb'
|
26
26
|
# )
|
27
27
|
# expect(definition.name).to eq('Baz')
|
@@ -32,7 +32,7 @@ module Rucoa
|
|
32
32
|
# @return [String]
|
33
33
|
# @example returns namespace
|
34
34
|
# definition = Rucoa::Definitions::ConstantDefinition.new(
|
35
|
-
#
|
35
|
+
# fully_qualified_name: 'Foo::Bar::Baz',
|
36
36
|
# source_path: '/path/to/foo/bar/baz.rb'
|
37
37
|
# )
|
38
38
|
# expect(definition.namespace).to eq('Foo::Bar')
|
@@ -44,7 +44,7 @@ module Rucoa
|
|
44
44
|
|
45
45
|
# @return [Array<String>]
|
46
46
|
def names
|
47
|
-
@names ||=
|
47
|
+
@names ||= fully_qualified_name.split('::')
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -6,6 +6,9 @@ module Rucoa
|
|
6
6
|
# @return [String, nil]
|
7
7
|
attr_reader :description
|
8
8
|
|
9
|
+
# @return [Symbol]
|
10
|
+
attr_reader :kind
|
11
|
+
|
9
12
|
# @return [String]
|
10
13
|
attr_reader :method_name
|
11
14
|
|
@@ -48,8 +51,8 @@ module Rucoa
|
|
48
51
|
# source_path: '/path/to/foo/bar.rb',
|
49
52
|
# types: []
|
50
53
|
# )
|
51
|
-
# expect(method_definition.
|
52
|
-
def
|
54
|
+
# expect(method_definition.fully_qualified_name).to eq('Foo::Bar#foo')
|
55
|
+
def fully_qualified_name
|
53
56
|
[
|
54
57
|
@namespace,
|
55
58
|
method_kind_symbol,
|
@@ -102,20 +105,29 @@ module Rucoa
|
|
102
105
|
def signatures
|
103
106
|
@types.map do |type|
|
104
107
|
format(
|
105
|
-
'%<
|
106
|
-
|
108
|
+
'%<fully_qualified_name>s(%<parameters>s) -> %<return_types>s',
|
109
|
+
fully_qualified_name: fully_qualified_name,
|
107
110
|
parameters: type.parameters_string,
|
108
111
|
return_types: type.return_type
|
109
112
|
)
|
110
113
|
end
|
111
114
|
end
|
112
115
|
|
116
|
+
# @return [Boolean]
|
117
|
+
def instance_method?
|
118
|
+
@kind == :instance
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [Boolean]
|
122
|
+
def singleton_method?
|
123
|
+
!instance_method?
|
124
|
+
end
|
125
|
+
|
113
126
|
private
|
114
127
|
|
115
128
|
# @return [String]
|
116
129
|
def method_kind_symbol
|
117
|
-
|
118
|
-
when :instance
|
130
|
+
if instance_method?
|
119
131
|
'#'
|
120
132
|
else
|
121
133
|
'.'
|
data/lib/rucoa/definitions.rb
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
module Rucoa
|
4
4
|
module Definitions
|
5
5
|
autoload :Base, 'rucoa/definitions/base'
|
6
|
+
autoload :ClassDefinition, 'rucoa/definitions/class_definition'
|
6
7
|
autoload :ConstantDefinition, 'rucoa/definitions/constant_definition'
|
7
8
|
autoload :MethodDefinition, 'rucoa/definitions/method_definition'
|
9
|
+
autoload :ModuleDefinition, 'rucoa/definitions/module_definition'
|
8
10
|
end
|
9
11
|
end
|
@@ -7,16 +7,44 @@ module Rucoa
|
|
7
7
|
|
8
8
|
def call
|
9
9
|
request_workspace_configuration
|
10
|
-
|
10
|
+
update_source_store
|
11
|
+
update_definition_store
|
11
12
|
end
|
12
13
|
|
13
14
|
private
|
14
15
|
|
15
16
|
# @return [void]
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def update_definition_store
|
18
|
+
sources.each do |source|
|
19
|
+
definition_store.update_from(source)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [void]
|
24
|
+
def update_source_store
|
25
|
+
sources.each do |source|
|
26
|
+
source_store.update(source)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Array<Rucoa::Source>]
|
31
|
+
def sources
|
32
|
+
@sources ||= pathnames.map do |pathname|
|
33
|
+
Source.new(
|
34
|
+
content: pathname.read,
|
35
|
+
uri: "file://#{pathname}"
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Array<Pathname>]
|
41
|
+
def pathnames
|
42
|
+
::Pathname.glob(glob)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [String]
|
46
|
+
def glob
|
47
|
+
::File.expand_path('{app,lib}/**/*.rb')
|
20
48
|
end
|
21
49
|
end
|
22
50
|
end
|
@@ -148,7 +148,7 @@ module Rucoa
|
|
148
148
|
# @return [Array<String>]
|
149
149
|
def callable_method_definitions
|
150
150
|
receiver_types.flat_map do |type|
|
151
|
-
definition_store.
|
151
|
+
definition_store.instance_method_definitions_of(type)
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
@@ -163,7 +163,7 @@ module Rucoa
|
|
163
163
|
# @return [Rucoa::Node, nil]
|
164
164
|
def node
|
165
165
|
@node ||=
|
166
|
-
if source.
|
166
|
+
if source.failed_to_parse?
|
167
167
|
repair
|
168
168
|
repaired_node
|
169
169
|
else
|