rucoa 0.4.0 → 0.6.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 +3 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +12 -2
- data/README.md +47 -17
- data/data/definitions_ruby_3_1 +0 -0
- data/images/diagnostics.gif +0 -0
- data/images/document-formatting.gif +0 -0
- data/images/document-symbol.gif +0 -0
- data/images/selection-ranges.gif +0 -0
- data/lib/rucoa/cli.rb +3 -2
- data/lib/rucoa/configuration.rb +111 -32
- data/lib/rucoa/definition_archiver.rb +29 -0
- data/lib/rucoa/definition_builders/rbs_constant_definition_builder.rb +44 -0
- data/lib/rucoa/definition_builders/rbs_method_definition_builder.rb +106 -0
- data/lib/rucoa/definition_builders/yard_method_definition_builder.rb +218 -0
- data/lib/rucoa/definition_builders.rb +9 -0
- data/lib/rucoa/definition_store.rb +63 -0
- data/lib/rucoa/definitions/base.rb +12 -0
- data/lib/rucoa/definitions/constant_definition.rb +51 -0
- data/lib/rucoa/definitions/method_definition.rb +126 -0
- data/lib/rucoa/definitions/method_parameter_definition.rb +30 -0
- data/lib/rucoa/definitions.rb +9 -0
- data/lib/rucoa/handlers/base.rb +8 -0
- data/lib/rucoa/handlers/exit_handler.rb +11 -0
- data/lib/rucoa/handlers/initialize_handler.rb +13 -0
- data/lib/rucoa/handlers/initialized_handler.rb +10 -0
- data/lib/rucoa/handlers/shutdown_handler.rb +12 -0
- data/lib/rucoa/handlers/text_document_completion_handler.rb +216 -0
- data/lib/rucoa/handlers/text_document_did_change_handler.rb +1 -20
- data/lib/rucoa/handlers/text_document_did_open_handler.rb +11 -4
- data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +5 -4
- data/lib/rucoa/handlers/text_document_hover_handler.rb +76 -0
- data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +1 -1
- data/lib/rucoa/handlers/text_document_selection_range_handler.rb +3 -3
- data/lib/rucoa/handlers/text_document_signature_help_handler.rb +68 -0
- data/lib/rucoa/handlers.rb +5 -0
- data/lib/rucoa/node_inspector.rb +111 -0
- data/lib/rucoa/nodes/base.rb +30 -0
- data/lib/rucoa/nodes/def_node.rb +59 -0
- data/lib/rucoa/nodes/lvar_node.rb +25 -0
- data/lib/rucoa/nodes/send_node.rb +43 -0
- data/lib/rucoa/nodes.rb +1 -0
- data/lib/rucoa/parser_builder.rb +1 -0
- data/lib/rucoa/position.rb +14 -3
- data/lib/rucoa/range.rb +64 -14
- data/lib/rucoa/rbs_document_loader.rb +43 -0
- data/lib/rucoa/rubocop_autocorrector.rb +1 -1
- data/lib/rucoa/rubocop_investigator.rb +1 -1
- data/lib/rucoa/server.rb +63 -13
- data/lib/rucoa/source.rb +59 -4
- data/lib/rucoa/source_store.rb +6 -10
- data/lib/rucoa/types/method_type.rb +23 -0
- data/lib/rucoa/types.rb +7 -0
- data/lib/rucoa/version.rb +1 -1
- data/lib/rucoa/yard_glob_document_loader.rb +47 -0
- data/lib/rucoa/yard_string_document_loader.rb +70 -0
- data/lib/rucoa.rb +9 -0
- data/rucoa.gemspec +2 -0
- metadata +58 -2
@@ -0,0 +1,216 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Handlers
|
5
|
+
class TextDocumentCompletionHandler < Base
|
6
|
+
COMPLETION_ITEM_KIND_FOR_TEXT = 1
|
7
|
+
COMPLETION_ITEM_KIND_FOR_METHOD = 2
|
8
|
+
COMPLETION_ITEM_KIND_FOR_FUNCTION = 3
|
9
|
+
COMPLETION_ITEM_KIND_FOR_CONSTRUCTOR = 4
|
10
|
+
COMPLETION_ITEM_KIND_FOR_FIELD = 5
|
11
|
+
COMPLETION_ITEM_KIND_FOR_VARIABLE = 6
|
12
|
+
COMPLETION_ITEM_KIND_FOR_CLASS = 7
|
13
|
+
COMPLETION_ITEM_KIND_FOR_INTERFACE = 8
|
14
|
+
COMPLETION_ITEM_KIND_FOR_MODULE = 9
|
15
|
+
COMPLETION_ITEM_KIND_FOR_PROPERTY = 10
|
16
|
+
COMPLETION_ITEM_KIND_FOR_UNIT = 11
|
17
|
+
COMPLETION_ITEM_KIND_FOR_VALUE = 12
|
18
|
+
COMPLETION_ITEM_KIND_FOR_ENUM = 13
|
19
|
+
COMPLETION_ITEM_KIND_FOR_KEYWORD = 14
|
20
|
+
COMPLETION_ITEM_KIND_FOR_SNIPPET = 15
|
21
|
+
COMPLETION_ITEM_KIND_FOR_COLOR = 16
|
22
|
+
COMPLETION_ITEM_KIND_FOR_FILE = 17
|
23
|
+
COMPLETION_ITEM_KIND_FOR_REFERENCE = 18
|
24
|
+
COMPLETION_ITEM_KIND_FOR_FOLDER = 19
|
25
|
+
COMPLETION_ITEM_KIND_FOR_ENUM_MEMBER = 20
|
26
|
+
COMPLETION_ITEM_KIND_FOR_CONSTANT = 21
|
27
|
+
COMPLETION_ITEM_KIND_FOR_STRUCT = 22
|
28
|
+
COMPLETION_ITEM_KIND_FOR_EVENT = 23
|
29
|
+
COMPLETION_ITEM_KIND_FOR_OPERATOR = 24
|
30
|
+
COMPLETION_ITEM_KIND_FOR_TYPE_PARAMETER = 25
|
31
|
+
|
32
|
+
EXAMPLE_IDENTIFIER = 'a'
|
33
|
+
private_constant :EXAMPLE_IDENTIFIER
|
34
|
+
|
35
|
+
def call
|
36
|
+
respond(completion_items)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# @return [Array<Hash>, nil]
|
42
|
+
def completion_items
|
43
|
+
return unless responsible?
|
44
|
+
|
45
|
+
case node
|
46
|
+
when Nodes::ConstNode
|
47
|
+
completion_items_for_constant
|
48
|
+
when Nodes::SendNode
|
49
|
+
if node.location.dot&.is?('::')
|
50
|
+
completion_items_for_constant
|
51
|
+
else
|
52
|
+
completion_items_for_method
|
53
|
+
end
|
54
|
+
else
|
55
|
+
[]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Boolean]
|
60
|
+
def responsible?
|
61
|
+
configuration.enables_completion? &&
|
62
|
+
!source.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [Rucoa::Source, nil]
|
66
|
+
def source
|
67
|
+
@source ||= source_store.get(uri)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Rucoa::Position]
|
71
|
+
def position
|
72
|
+
@position ||= Position.from_vscode_position(
|
73
|
+
request.dig('params', 'position')
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String]
|
78
|
+
def uri
|
79
|
+
request.dig('params', 'textDocument', 'uri')
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Array<Hash>]
|
83
|
+
def completion_items_for_method
|
84
|
+
completable_method_names.map do |method_name|
|
85
|
+
{
|
86
|
+
kind: COMPLETION_ITEM_KIND_FOR_METHOD,
|
87
|
+
label: method_name,
|
88
|
+
textEdit: {
|
89
|
+
newText: method_name,
|
90
|
+
range: range.to_vscode_range
|
91
|
+
}
|
92
|
+
}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return [Array<Hash>]
|
97
|
+
def completion_items_for_constant
|
98
|
+
completable_constant_names.map do |constant_name|
|
99
|
+
{
|
100
|
+
kind: COMPLETION_ITEM_KIND_FOR_CONSTANT,
|
101
|
+
label: constant_name,
|
102
|
+
textEdit: {
|
103
|
+
newText: constant_name,
|
104
|
+
range: range.to_vscode_range
|
105
|
+
}
|
106
|
+
}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [Array<String>]
|
111
|
+
def completable_constant_names
|
112
|
+
referrable_constant_names.select do |constant_name|
|
113
|
+
constant_name.start_with?(completion_head)
|
114
|
+
end.sort
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return [String] e.g. "SE" to `File::SE|`, "ba" to `foo.ba|`
|
118
|
+
def completion_head
|
119
|
+
@completion_head ||=
|
120
|
+
if @repaired
|
121
|
+
''
|
122
|
+
else
|
123
|
+
node.name
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def referrable_constant_names
|
128
|
+
definition_store.constant_definitions_under(constant_namespace).map(&:name).uniq
|
129
|
+
end
|
130
|
+
|
131
|
+
# @return [String] e.g. "Foo::Bar" to `Foo::Bar.baz|`.
|
132
|
+
def constant_namespace
|
133
|
+
node.each_child_node(:const).map(&:name).reverse.join('::')
|
134
|
+
end
|
135
|
+
|
136
|
+
# @return [Array<String>]
|
137
|
+
def completable_method_names
|
138
|
+
callable_method_names.select do |method_name|
|
139
|
+
method_name.start_with?(completion_head)
|
140
|
+
end.sort
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [Array<String>]
|
144
|
+
def callable_method_names
|
145
|
+
callable_method_definitions.map(&:method_name).uniq
|
146
|
+
end
|
147
|
+
|
148
|
+
# @return [Array<String>]
|
149
|
+
def callable_method_definitions
|
150
|
+
receiver_types.flat_map do |type|
|
151
|
+
definition_store.method_definitions_of(type)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# @return [Array<String>]
|
156
|
+
def receiver_types
|
157
|
+
NodeInspector.new(
|
158
|
+
definition_store: definition_store,
|
159
|
+
node: node
|
160
|
+
).method_receiver_types
|
161
|
+
end
|
162
|
+
|
163
|
+
# @return [Rucoa::Node, nil]
|
164
|
+
def node
|
165
|
+
@node ||=
|
166
|
+
if source.syntax_error?
|
167
|
+
repair
|
168
|
+
repaired_node
|
169
|
+
else
|
170
|
+
normal_node
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# @return [Rucoa::Node, nil]
|
175
|
+
def normal_node
|
176
|
+
source.node_at(position)
|
177
|
+
end
|
178
|
+
|
179
|
+
# @return [Rucoa::Node, nil]
|
180
|
+
def repaired_node
|
181
|
+
repaired_source.node_at(position)
|
182
|
+
end
|
183
|
+
|
184
|
+
# @return [void]
|
185
|
+
def repair
|
186
|
+
@repaired = true
|
187
|
+
end
|
188
|
+
|
189
|
+
# @return [String]
|
190
|
+
def repaired_content
|
191
|
+
source.content.dup.insert(
|
192
|
+
position.to_index_of(source.content),
|
193
|
+
EXAMPLE_IDENTIFIER
|
194
|
+
)
|
195
|
+
end
|
196
|
+
|
197
|
+
# @return [Rucoa::Source]
|
198
|
+
def repaired_source
|
199
|
+
Source.new(
|
200
|
+
content: repaired_content,
|
201
|
+
uri: source.uri
|
202
|
+
)
|
203
|
+
end
|
204
|
+
|
205
|
+
# @return [Rucoa::Range]
|
206
|
+
def range
|
207
|
+
@range ||=
|
208
|
+
if @repaired
|
209
|
+
position.to_range
|
210
|
+
else
|
211
|
+
Range.from_parser_range(node.location.expression)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -2,30 +2,11 @@
|
|
2
2
|
|
3
3
|
module Rucoa
|
4
4
|
module Handlers
|
5
|
-
class TextDocumentDidChangeHandler <
|
6
|
-
include HandlerConcerns::DiagnosticsPublishable
|
7
|
-
|
8
|
-
def call
|
9
|
-
update_source
|
10
|
-
publish_diagnostics_on(uri)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
# @return [void]
|
16
|
-
def update_source
|
17
|
-
source_store.set(uri, text)
|
18
|
-
end
|
19
|
-
|
5
|
+
class TextDocumentDidChangeHandler < TextDocumentDidOpenHandler
|
20
6
|
# @return [String]
|
21
7
|
def text
|
22
8
|
request.dig('params', 'contentChanges')[0]['text']
|
23
9
|
end
|
24
|
-
|
25
|
-
# @return [String]
|
26
|
-
def uri
|
27
|
-
@uri ||= request.dig('params', 'textDocument', 'uri')
|
28
|
-
end
|
29
10
|
end
|
30
11
|
end
|
31
12
|
end
|
@@ -6,15 +6,22 @@ module Rucoa
|
|
6
6
|
include HandlerConcerns::DiagnosticsPublishable
|
7
7
|
|
8
8
|
def call
|
9
|
-
|
9
|
+
source_store.update(source)
|
10
|
+
definition_store.update_definitions_defined_in(
|
11
|
+
source.path,
|
12
|
+
definitions: source.definitions
|
13
|
+
)
|
10
14
|
publish_diagnostics_on(uri)
|
11
15
|
end
|
12
16
|
|
13
17
|
private
|
14
18
|
|
15
|
-
# @return [
|
16
|
-
def
|
17
|
-
|
19
|
+
# @return [Rucoa::Source]
|
20
|
+
def source
|
21
|
+
@source ||= Source.new(
|
22
|
+
content: text,
|
23
|
+
uri: uri
|
24
|
+
)
|
18
25
|
end
|
19
26
|
|
20
27
|
# @return [String]
|
@@ -40,7 +40,7 @@ module Rucoa
|
|
40
40
|
]
|
41
41
|
|
42
42
|
def call
|
43
|
-
return unless
|
43
|
+
return unless responsible?
|
44
44
|
|
45
45
|
respond(document_symbols)
|
46
46
|
end
|
@@ -206,13 +206,14 @@ module Rucoa
|
|
206
206
|
end
|
207
207
|
|
208
208
|
# @return [Boolean]
|
209
|
-
def
|
210
|
-
configuration.enables_document_symbol? &&
|
209
|
+
def responsible?
|
210
|
+
configuration.enables_document_symbol? &&
|
211
|
+
!source.nil?
|
211
212
|
end
|
212
213
|
|
213
214
|
# @return [Rucoa::Source]
|
214
215
|
def source
|
215
|
-
@source ||=
|
216
|
+
@source ||= source_store.get(uri)
|
216
217
|
end
|
217
218
|
|
218
219
|
# @return [String]
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Handlers
|
5
|
+
class TextDocumentHoverHandler < Base
|
6
|
+
def call
|
7
|
+
respond(hover)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# @return [Hash, nil]
|
13
|
+
def hover
|
14
|
+
return unless responsible?
|
15
|
+
|
16
|
+
{
|
17
|
+
contents: contents,
|
18
|
+
range: range.to_vscode_range
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Boolean]
|
23
|
+
def responsible?
|
24
|
+
configuration.enables_hover? &&
|
25
|
+
!source.nil? &&
|
26
|
+
!node.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [String, nil]
|
30
|
+
def contents
|
31
|
+
method_definition = method_definitions.first
|
32
|
+
return unless method_definition
|
33
|
+
|
34
|
+
[
|
35
|
+
method_definition.signatures.join("\n"),
|
36
|
+
method_definition.description
|
37
|
+
].join("\n\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Rucoa::Range]
|
41
|
+
def range
|
42
|
+
Range.from_parser_range(node.location.expression)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Rucoa::Nodes::Base, nil]
|
46
|
+
def node
|
47
|
+
@node ||= source.node_at(position)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Rucoa::Source, nil]
|
51
|
+
def source
|
52
|
+
@source ||= source_store.get(uri)
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [String]
|
56
|
+
def uri
|
57
|
+
request.dig('params', 'textDocument', 'uri')
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Rucoa::Position]
|
61
|
+
def position
|
62
|
+
Position.from_vscode_position(
|
63
|
+
request.dig('params', 'position')
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
68
|
+
def method_definitions
|
69
|
+
NodeInspector.new(
|
70
|
+
definition_store: definition_store,
|
71
|
+
node: node
|
72
|
+
).method_definitions
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -4,7 +4,7 @@ module Rucoa
|
|
4
4
|
module Handlers
|
5
5
|
class TextDocumentSelectionRangeHandler < Base
|
6
6
|
def call
|
7
|
-
return unless
|
7
|
+
return unless responsible?
|
8
8
|
|
9
9
|
respond(
|
10
10
|
positions.filter_map do |position|
|
@@ -19,9 +19,9 @@ module Rucoa
|
|
19
19
|
private
|
20
20
|
|
21
21
|
# @return [Boolean]
|
22
|
-
def
|
22
|
+
def responsible?
|
23
23
|
configuration.enables_selection_range? &&
|
24
|
-
source
|
24
|
+
!source.nil?
|
25
25
|
end
|
26
26
|
|
27
27
|
# @return [Rucoa::Source]
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module Handlers
|
5
|
+
class TextDocumentSignatureHelpHandler < Base
|
6
|
+
def call
|
7
|
+
respond(signature_help)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# @return [Hash]
|
13
|
+
def signature_help
|
14
|
+
return unless responsible?
|
15
|
+
|
16
|
+
{
|
17
|
+
signatures: signature_informations
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Boolean]
|
22
|
+
def responsible?
|
23
|
+
configuration.enables_signature_help? &&
|
24
|
+
node.is_a?(Nodes::SendNode)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array<Hash>]
|
28
|
+
def signature_informations
|
29
|
+
method_definitions.map do |method_definition|
|
30
|
+
{
|
31
|
+
documentation: method_definition.description,
|
32
|
+
label: method_definition.signatures.join("\n")
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Array<Rucoa::Definitions::MethodDefinition>]
|
38
|
+
def method_definitions
|
39
|
+
NodeInspector.new(
|
40
|
+
definition_store: definition_store,
|
41
|
+
node: node
|
42
|
+
).method_definitions
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Rucoa::Nodes::Base, nil]
|
46
|
+
def node
|
47
|
+
@node ||= source.node_at(position)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Rucoa::Position]
|
51
|
+
def position
|
52
|
+
Position.from_vscode_position(
|
53
|
+
request.dig('params', 'position')
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Rucoa::Source]
|
58
|
+
def source
|
59
|
+
source_store.get(uri)
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [String]
|
63
|
+
def uri
|
64
|
+
request.dig('params', 'textDocument', 'uri')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/rucoa/handlers.rb
CHANGED
@@ -3,15 +3,20 @@
|
|
3
3
|
module Rucoa
|
4
4
|
module Handlers
|
5
5
|
autoload :Base, 'rucoa/handlers/base'
|
6
|
+
autoload :ExitHandler, 'rucoa/handlers/exit_handler'
|
6
7
|
autoload :InitializeHandler, 'rucoa/handlers/initialize_handler'
|
7
8
|
autoload :InitializedHandler, 'rucoa/handlers/initialized_handler'
|
9
|
+
autoload :ShutdownHandler, 'rucoa/handlers/shutdown_handler'
|
8
10
|
autoload :TextDocumentCodeActionHandler, 'rucoa/handlers/text_document_code_action_handler'
|
11
|
+
autoload :TextDocumentCompletionHandler, 'rucoa/handlers/text_document_completion_handler'
|
9
12
|
autoload :TextDocumentDidChangeHandler, 'rucoa/handlers/text_document_did_change_handler'
|
10
13
|
autoload :TextDocumentDidOpenHandler, 'rucoa/handlers/text_document_did_open_handler'
|
11
14
|
autoload :TextDocumentDocumentSymbolHandler, 'rucoa/handlers/text_document_document_symbol_handler'
|
12
15
|
autoload :TextDocumentFormattingHandler, 'rucoa/handlers/text_document_formatting_handler'
|
16
|
+
autoload :TextDocumentHoverHandler, 'rucoa/handlers/text_document_hover_handler'
|
13
17
|
autoload :TextDocumentRangeFormattingHandler, 'rucoa/handlers/text_document_range_formatting_handler'
|
14
18
|
autoload :TextDocumentSelectionRangeHandler, 'rucoa/handlers/text_document_selection_range_handler'
|
19
|
+
autoload :TextDocumentSignatureHelpHandler, 'rucoa/handlers/text_document_signature_help_handler'
|
15
20
|
autoload :WorkspaceDidChangeConfigurationHandler, 'rucoa/handlers/workspace_did_change_configuration_handler'
|
16
21
|
end
|
17
22
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Rucoa
|
6
|
+
class NodeInspector
|
7
|
+
# @param definition_store [Rucoa::DefinitionStore]
|
8
|
+
# @param node [Rucoa::Node]
|
9
|
+
def initialize(definition_store:, node:)
|
10
|
+
@definition_store = definition_store
|
11
|
+
@node = node
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Array<String>]
|
15
|
+
def method_definitions
|
16
|
+
method_full_qualified_names.flat_map do |full_qualified_name|
|
17
|
+
@definition_store.select_by_full_qualified_name(full_qualified_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Array<String>]
|
22
|
+
def method_receiver_types
|
23
|
+
return [] unless @node.is_a?(Nodes::SendNode)
|
24
|
+
|
25
|
+
if @node.receiver
|
26
|
+
self.class.new(
|
27
|
+
definition_store: @definition_store,
|
28
|
+
node: @node.receiver
|
29
|
+
).return_types
|
30
|
+
else
|
31
|
+
[@node.namespace]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Array<String>]
|
36
|
+
def return_types
|
37
|
+
case @node.type
|
38
|
+
when :const
|
39
|
+
[@node.name]
|
40
|
+
when :lvar
|
41
|
+
return_types_for_lvar
|
42
|
+
when :send
|
43
|
+
return_types_for_send
|
44
|
+
when :array
|
45
|
+
%w[Array]
|
46
|
+
when :class, :module, :nil
|
47
|
+
%w[NilClass]
|
48
|
+
when :complex
|
49
|
+
%w[Complex]
|
50
|
+
when :def, :sym
|
51
|
+
%w[Symbol]
|
52
|
+
when :dstr, :str, :xstr
|
53
|
+
%w[String]
|
54
|
+
when :erange, :irange
|
55
|
+
%w[Range]
|
56
|
+
when false
|
57
|
+
%w[FalseClass]
|
58
|
+
when :float
|
59
|
+
%w[Float]
|
60
|
+
when :hash, :pair
|
61
|
+
%w[Hash]
|
62
|
+
when :int
|
63
|
+
%w[Integer]
|
64
|
+
when :rational
|
65
|
+
%w[Rational]
|
66
|
+
when :regexp, :regopt
|
67
|
+
%w[Regexp]
|
68
|
+
when true
|
69
|
+
%w[TrueClass]
|
70
|
+
else
|
71
|
+
[]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# @return [Array<String>]
|
78
|
+
def method_full_qualified_names
|
79
|
+
method_receiver_types.map do |type|
|
80
|
+
[
|
81
|
+
type,
|
82
|
+
@node.name
|
83
|
+
].join('#')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# @return [String, nil]
|
88
|
+
def nearest_def_full_qualified_name
|
89
|
+
@node.each_ancestor(:def).first&.full_qualified_name
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [Array<String>]
|
93
|
+
def return_types_for_lvar
|
94
|
+
full_qualified_name = nearest_def_full_qualified_name
|
95
|
+
return [] unless full_qualified_name
|
96
|
+
|
97
|
+
@definition_store.select_by_full_qualified_name(full_qualified_name).flat_map do |definition|
|
98
|
+
definition.parameters.select do |parameter|
|
99
|
+
parameter.name == @node.name
|
100
|
+
end.flat_map(&:types)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return [Array<String>]
|
105
|
+
def return_types_for_send
|
106
|
+
method_full_qualified_names.flat_map do |full_qualified_name|
|
107
|
+
@definition_store.select_by_full_qualified_name(full_qualified_name).flat_map(&:return_types)
|
108
|
+
end.uniq
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/rucoa/nodes/base.rb
CHANGED
@@ -85,6 +85,36 @@ module Rucoa
|
|
85
85
|
Range.from_parser_range(location.expression).include?(position)
|
86
86
|
end
|
87
87
|
|
88
|
+
# @note namespace is a String representation of `Module.nesting`.
|
89
|
+
# @return [String]
|
90
|
+
# @example returns namespace
|
91
|
+
# node = Rucoa::Source.new(
|
92
|
+
# content: <<~RUBY
|
93
|
+
# module Foo
|
94
|
+
# class Bar
|
95
|
+
# def baz
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
# end
|
99
|
+
# RUBY
|
100
|
+
# ).node_at(
|
101
|
+
# Rucoa::Position.new(
|
102
|
+
# column: 4,
|
103
|
+
# line: 3
|
104
|
+
# )
|
105
|
+
# )
|
106
|
+
# expect(node.namespace).to eq('Foo::Bar')
|
107
|
+
# @example returns "Object" when the node is not in a namespace
|
108
|
+
# node = Rucoa::Parser.call(
|
109
|
+
# <<~RUBY
|
110
|
+
# foo
|
111
|
+
# RUBY
|
112
|
+
# )
|
113
|
+
# expect(node.namespace).to eq('Object')
|
114
|
+
def namespace
|
115
|
+
each_ancestor(:module, :class).first&.full_qualified_name || 'Object'
|
116
|
+
end
|
117
|
+
|
88
118
|
protected
|
89
119
|
|
90
120
|
# Visit all descendants.
|