rucoa 0.3.0 → 0.5.1
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 +37 -6
- 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/configuration.rb +62 -28
- 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/handler_concerns/diagnostics_publishable.rb +140 -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 +7 -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_code_action_handler.rb +78 -3
- 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 +242 -0
- data/lib/rucoa/handlers/text_document_formatting_handler.rb +36 -5
- data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +65 -13
- data/lib/rucoa/handlers/text_document_selection_range_handler.rb +124 -8
- data/lib/rucoa/handlers/text_document_signature_help_handler.rb +68 -0
- data/lib/rucoa/handlers.rb +4 -0
- data/lib/rucoa/node_concerns/name_full_qualifiable.rb +20 -0
- data/lib/rucoa/node_concerns.rb +7 -0
- data/lib/rucoa/node_inspector.rb +111 -0
- data/lib/rucoa/nodes/base.rb +43 -0
- data/lib/rucoa/nodes/casgn_node.rb +14 -0
- data/lib/rucoa/nodes/class_node.rb +8 -0
- data/lib/rucoa/nodes/const_node.rb +12 -0
- data/lib/rucoa/nodes/def_node.rb +71 -0
- data/lib/rucoa/nodes/defs_node.rb +12 -0
- data/lib/rucoa/nodes/lvar_node.rb +25 -0
- data/lib/rucoa/nodes/module_node.rb +21 -0
- data/lib/rucoa/nodes/sclass_node.rb +8 -0
- data/lib/rucoa/nodes/send_node.rb +60 -0
- data/lib/rucoa/nodes/str_node.rb +4 -0
- data/lib/rucoa/nodes/sym_node.rb +12 -0
- data/lib/rucoa/nodes.rb +10 -0
- data/lib/rucoa/parser_builder.rb +20 -10
- data/lib/rucoa/position.rb +2 -2
- 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 +20 -1
- data/lib/rucoa/source.rb +56 -6
- 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 +10 -5
- data/rucoa.gemspec +2 -0
- metadata +68 -7
- data/lib/rucoa/code_action_provider.rb +0 -102
- data/lib/rucoa/diagnostic_provider.rb +0 -143
- data/lib/rucoa/formatting_provider.rb +0 -54
- data/lib/rucoa/range_formatting_provider.rb +0 -67
- data/lib/rucoa/selection_range_provider.rb +0 -99
@@ -0,0 +1,242 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Rucoa
|
6
|
+
module Handlers
|
7
|
+
class TextDocumentDocumentSymbolHandler < Base
|
8
|
+
DOCUMENT_SYMBOL_KIND_FOR_FILE = 1
|
9
|
+
DOCUMENT_SYMBOL_KIND_FOR_MODULE = 2
|
10
|
+
DOCUMENT_SYMBOL_KIND_FOR_NAMESPACE = 3
|
11
|
+
DOCUMENT_SYMBOL_KIND_FOR_PACKAGE = 4
|
12
|
+
DOCUMENT_SYMBOL_KIND_FOR_CLASS = 5
|
13
|
+
DOCUMENT_SYMBOL_KIND_FOR_METHOD = 6
|
14
|
+
DOCUMENT_SYMBOL_KIND_FOR_PROPERTY = 7
|
15
|
+
DOCUMENT_SYMBOL_KIND_FOR_FIELD = 8
|
16
|
+
DOCUMENT_SYMBOL_KIND_FOR_CONSTRUCTOR = 9
|
17
|
+
DOCUMENT_SYMBOL_KIND_FOR_ENUM = 10
|
18
|
+
DOCUMENT_SYMBOL_KIND_FOR_INTERFACE = 11
|
19
|
+
DOCUMENT_SYMBOL_KIND_FOR_FUNCTION = 12
|
20
|
+
DOCUMENT_SYMBOL_KIND_FOR_VARIABLE = 13
|
21
|
+
DOCUMENT_SYMBOL_KIND_FOR_CONSTANT = 14
|
22
|
+
DOCUMENT_SYMBOL_KIND_FOR_STRING = 15
|
23
|
+
DOCUMENT_SYMBOL_KIND_FOR_NUMBER = 16
|
24
|
+
DOCUMENT_SYMBOL_KIND_FOR_BOOLEAN = 17
|
25
|
+
DOCUMENT_SYMBOL_KIND_FOR_ARRAY = 18
|
26
|
+
DOCUMENT_SYMBOL_KIND_FOR_OBJECT = 19
|
27
|
+
DOCUMENT_SYMBOL_KIND_FOR_KEY = 20
|
28
|
+
DOCUMENT_SYMBOL_KIND_FOR_NULL = 21
|
29
|
+
DOCUMENT_SYMBOL_KIND_FOR_ENUMMEMBER = 22
|
30
|
+
DOCUMENT_SYMBOL_KIND_FOR_STRUCT = 23
|
31
|
+
DOCUMENT_SYMBOL_KIND_FOR_EVENT = 24
|
32
|
+
DOCUMENT_SYMBOL_KIND_FOR_OPERATOR = 25
|
33
|
+
DOCUMENT_SYMBOL_KIND_FOR_TYPEPARAMETER = 26
|
34
|
+
|
35
|
+
# @return [Set<String>]
|
36
|
+
ATTRIBUTE_METHOD_NAMES = ::Set[
|
37
|
+
'attr_accessor',
|
38
|
+
'attr_reader',
|
39
|
+
'attr_writer',
|
40
|
+
]
|
41
|
+
|
42
|
+
def call
|
43
|
+
return unless responsible?
|
44
|
+
|
45
|
+
respond(document_symbols)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# @return [Array<Hash>]
|
51
|
+
def document_symbols
|
52
|
+
visit(source.root_node)
|
53
|
+
document_symbol_stack.first[:children]
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param node [Rucoa::Nodes::Base]
|
57
|
+
# @return [void]
|
58
|
+
def visit(node)
|
59
|
+
document_symbols = create_document_symbols_for(node)
|
60
|
+
document_symbol_stack.last[:children].push(*document_symbols)
|
61
|
+
with_document_symbol_stack(document_symbols.first) do
|
62
|
+
with_singleton_class_stack(node) do
|
63
|
+
node.each_child_node do |child_node|
|
64
|
+
visit(child_node)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param document_symbol [Hash, nil]
|
71
|
+
# @return [void]
|
72
|
+
def with_document_symbol_stack(document_symbol)
|
73
|
+
unless document_symbol
|
74
|
+
yield
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
78
|
+
document_symbol_stack.push(document_symbol)
|
79
|
+
yield
|
80
|
+
document_symbol_stack.pop
|
81
|
+
end
|
82
|
+
|
83
|
+
# @param node [Rucoa::Nodes::Base]
|
84
|
+
def with_singleton_class_stack(node)
|
85
|
+
unless node.is_a?(Rucoa::Nodes::SclassNode)
|
86
|
+
yield
|
87
|
+
return
|
88
|
+
end
|
89
|
+
|
90
|
+
singleton_class_stack.push(node)
|
91
|
+
yield
|
92
|
+
singleton_class_stack.pop
|
93
|
+
end
|
94
|
+
|
95
|
+
# @param node [Rucoa::Nodes::Base]
|
96
|
+
# @return [Array<Hash>]
|
97
|
+
def create_document_symbols_for(node)
|
98
|
+
case node
|
99
|
+
when Nodes::CasgnNode
|
100
|
+
create_document_symbols_for_casgn(node)
|
101
|
+
when Nodes::ClassNode
|
102
|
+
create_document_symbols_for_class(node)
|
103
|
+
when Nodes::DefNode
|
104
|
+
create_document_symbols_for_def(node)
|
105
|
+
when Nodes::DefsNode
|
106
|
+
create_document_symbols_for_defs(node)
|
107
|
+
when Nodes::ModuleNode
|
108
|
+
create_document_symbols_for_module(node)
|
109
|
+
when Nodes::SendNode
|
110
|
+
create_document_symbols_for_send(node)
|
111
|
+
else
|
112
|
+
[]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# @param node [Rucoa::Nodes::CasgnNode]
|
117
|
+
# @return [Array<Hash>]
|
118
|
+
def create_document_symbols_for_casgn(node)
|
119
|
+
[
|
120
|
+
{
|
121
|
+
children: [],
|
122
|
+
kind: DOCUMENT_SYMBOL_KIND_FOR_CONSTANT,
|
123
|
+
name: node.name,
|
124
|
+
range: Range.from_parser_range(node.location.expression).to_vscode_range,
|
125
|
+
selectionRange: Range.from_parser_range(node.location.name).to_vscode_range
|
126
|
+
}
|
127
|
+
]
|
128
|
+
end
|
129
|
+
|
130
|
+
# @param node [Rucoa::Nodes::ClassNode]
|
131
|
+
# @return [Array<Hash>]
|
132
|
+
def create_document_symbols_for_class(node)
|
133
|
+
[
|
134
|
+
{
|
135
|
+
children: [],
|
136
|
+
kind: DOCUMENT_SYMBOL_KIND_FOR_CLASS,
|
137
|
+
name: node.name,
|
138
|
+
range: Range.from_parser_range(node.location.expression).to_vscode_range,
|
139
|
+
selectionRange: Range.from_parser_range(node.location.name).to_vscode_range
|
140
|
+
}
|
141
|
+
]
|
142
|
+
end
|
143
|
+
|
144
|
+
# @param node [Rucoa::Nodes::ModuleNode]
|
145
|
+
# @return [Array<Hash>]
|
146
|
+
def create_document_symbols_for_module(node)
|
147
|
+
[
|
148
|
+
{
|
149
|
+
children: [],
|
150
|
+
kind: DOCUMENT_SYMBOL_KIND_FOR_MODULE,
|
151
|
+
name: node.name,
|
152
|
+
range: Range.from_parser_range(node.location.expression).to_vscode_range,
|
153
|
+
selectionRange: Range.from_parser_range(node.location.name).to_vscode_range
|
154
|
+
}
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
# @param node [Rucoa::Nodes::DefNode]
|
159
|
+
# @return [Array<Hash>]
|
160
|
+
def create_document_symbols_for_def(node)
|
161
|
+
[
|
162
|
+
{
|
163
|
+
children: [],
|
164
|
+
kind: DOCUMENT_SYMBOL_KIND_FOR_METHOD,
|
165
|
+
name: singleton_class_stack.empty? ? "##{node.name}" : ".#{node.name}",
|
166
|
+
range: Range.from_parser_range(node.location.expression).to_vscode_range,
|
167
|
+
selectionRange: Range.from_parser_range(node.location.name).to_vscode_range
|
168
|
+
}
|
169
|
+
]
|
170
|
+
end
|
171
|
+
|
172
|
+
# @param node [Rucoa::Nodes::DefNode]
|
173
|
+
# @return [Array<Hash>]
|
174
|
+
def create_document_symbols_for_defs(node)
|
175
|
+
[
|
176
|
+
{
|
177
|
+
children: [],
|
178
|
+
kind: DOCUMENT_SYMBOL_KIND_FOR_METHOD,
|
179
|
+
name: ".#{node.name}",
|
180
|
+
range: Range.from_parser_range(node.location.expression).to_vscode_range,
|
181
|
+
selectionRange: Range.from_parser_range(node.location.name).to_vscode_range
|
182
|
+
}
|
183
|
+
]
|
184
|
+
end
|
185
|
+
|
186
|
+
# @param node [Rucoa::Nodes::SendNode]
|
187
|
+
# @return [Array<Hash>]
|
188
|
+
def create_document_symbols_for_send(node)
|
189
|
+
return [] unless ATTRIBUTE_METHOD_NAMES.include?(node.name)
|
190
|
+
|
191
|
+
simple_types = ::Set[
|
192
|
+
:str,
|
193
|
+
:sym
|
194
|
+
]
|
195
|
+
node.arguments.select do |argument|
|
196
|
+
simple_types.include?(argument.type)
|
197
|
+
end.map do |argument|
|
198
|
+
{
|
199
|
+
children: [],
|
200
|
+
kind: DOCUMENT_SYMBOL_KIND_FOR_FIELD,
|
201
|
+
name: argument.value.to_s,
|
202
|
+
range: Range.from_parser_range(argument.location.expression).to_vscode_range,
|
203
|
+
selectionRange: Range.from_parser_range(argument.location.expression).to_vscode_range
|
204
|
+
}
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# @return [Boolean]
|
209
|
+
def responsible?
|
210
|
+
configuration.enables_document_symbol? &&
|
211
|
+
!source.nil?
|
212
|
+
end
|
213
|
+
|
214
|
+
# @return [Rucoa::Source]
|
215
|
+
def source
|
216
|
+
@source ||= source_store.get(uri)
|
217
|
+
end
|
218
|
+
|
219
|
+
# @return [String]
|
220
|
+
def uri
|
221
|
+
request.dig('params', 'textDocument', 'uri')
|
222
|
+
end
|
223
|
+
|
224
|
+
# @return [Arrah<Hash>]
|
225
|
+
def document_symbol_stack
|
226
|
+
@document_symbol_stack ||= [dummy_document_symbol]
|
227
|
+
end
|
228
|
+
|
229
|
+
# @return [Hash]
|
230
|
+
def dummy_document_symbol
|
231
|
+
{
|
232
|
+
children: []
|
233
|
+
}
|
234
|
+
end
|
235
|
+
|
236
|
+
# @return [Array<Rucoa::Nodes::SclassNode>]
|
237
|
+
def singleton_class_stack
|
238
|
+
@singleton_class_stack ||= []
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
@@ -9,14 +9,18 @@ module Rucoa
|
|
9
9
|
|
10
10
|
private
|
11
11
|
|
12
|
+
# @return [Boolean]
|
13
|
+
def formattable?
|
14
|
+
configuration.enables_formatting? &&
|
15
|
+
source &&
|
16
|
+
RubocopConfigurationChecker.call
|
17
|
+
end
|
18
|
+
|
12
19
|
# @return [Array<Hash>]
|
13
20
|
def edits
|
14
|
-
return unless
|
15
|
-
return unless source
|
21
|
+
return [] unless formattable?
|
16
22
|
|
17
|
-
|
18
|
-
source: source
|
19
|
-
)
|
23
|
+
[text_edit]
|
20
24
|
end
|
21
25
|
|
22
26
|
# @return [Rucoa::Source, nil]
|
@@ -28,6 +32,33 @@ module Rucoa
|
|
28
32
|
def uri
|
29
33
|
request.dig('params', 'textDocument', 'uri')
|
30
34
|
end
|
35
|
+
|
36
|
+
# @return [Hash]
|
37
|
+
def text_edit
|
38
|
+
{
|
39
|
+
newText: new_text,
|
40
|
+
range: range
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [String]
|
45
|
+
def new_text
|
46
|
+
RubocopAutocorrector.call(source: source)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Hash]
|
50
|
+
def range
|
51
|
+
Range.new(
|
52
|
+
Position.new(
|
53
|
+
column: 0,
|
54
|
+
line: 1
|
55
|
+
),
|
56
|
+
Position.new(
|
57
|
+
column: @source.content.lines.last.length,
|
58
|
+
line: @source.content.lines.count + 1
|
59
|
+
)
|
60
|
+
).to_vscode_range
|
61
|
+
end
|
31
62
|
end
|
32
63
|
end
|
33
64
|
end
|
@@ -4,21 +4,73 @@ module Rucoa
|
|
4
4
|
module Handlers
|
5
5
|
class TextDocumentRangeFormattingHandler < Base
|
6
6
|
def call
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
7
|
+
respond(edits)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# @return [Array<Hash>]
|
13
|
+
def edits
|
14
|
+
return [] unless formattable?
|
15
|
+
|
16
|
+
correctable_replacements.map do |replacement_range, replacement|
|
17
|
+
{
|
18
|
+
newText: replacement,
|
19
|
+
range: replacement_range.to_vscode_range
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Boolean]
|
25
|
+
def formattable?
|
26
|
+
configuration.enables_formatting? &&
|
27
|
+
source &&
|
28
|
+
RubocopConfigurationChecker.call
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Rucoa::Source]
|
32
|
+
def source
|
33
|
+
@source ||= source_store.get(uri)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String]
|
37
|
+
def uri
|
38
|
+
request.dig('params', 'textDocument', 'uri')
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Rucoa::Range]
|
42
|
+
def range
|
43
|
+
@range ||= Range.from_vscode_range(
|
44
|
+
request.dig('params', 'range')
|
20
45
|
)
|
21
46
|
end
|
47
|
+
|
48
|
+
# @return [Array<RuboCop::Cop::Corrector>]
|
49
|
+
def correctable_offenses
|
50
|
+
offenses.select(&:corrector)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [Array(Rucoa::Range, String)]
|
54
|
+
def correctable_replacements
|
55
|
+
replacements.select do |replacement_range, _|
|
56
|
+
range.contain?(replacement_range)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Array<RuboCop::Cop::Offense>]
|
61
|
+
def offenses
|
62
|
+
RubocopInvestigator.call(source: source)
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [Array(Rucoa::Range, String)]
|
66
|
+
def replacements
|
67
|
+
correctable_offenses.map(&:corrector).flat_map(&:as_replacements).map do |replacement_range, replacement|
|
68
|
+
[
|
69
|
+
Range.from_parser_range(replacement_range),
|
70
|
+
replacement
|
71
|
+
]
|
72
|
+
end
|
73
|
+
end
|
22
74
|
end
|
23
75
|
end
|
24
76
|
end
|
@@ -4,22 +4,138 @@ module Rucoa
|
|
4
4
|
module Handlers
|
5
5
|
class TextDocumentSelectionRangeHandler < Base
|
6
6
|
def call
|
7
|
-
return unless
|
8
|
-
|
9
|
-
source = source_store.get(
|
10
|
-
request.dig('params', 'textDocument', 'uri')
|
11
|
-
)
|
12
|
-
return unless source
|
7
|
+
return unless responsible?
|
13
8
|
|
14
9
|
respond(
|
15
|
-
|
10
|
+
positions.filter_map do |position|
|
16
11
|
SelectionRangeProvider.call(
|
17
|
-
position:
|
12
|
+
position: position,
|
18
13
|
source: source
|
19
14
|
)
|
20
15
|
end
|
21
16
|
)
|
22
17
|
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# @return [Boolean]
|
22
|
+
def responsible?
|
23
|
+
configuration.enables_selection_range? &&
|
24
|
+
!source.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Rucoa::Source]
|
28
|
+
def source
|
29
|
+
@source ||= source_store.get(uri)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Array<Rucoa::Position>]
|
33
|
+
def positions
|
34
|
+
request.dig('params', 'positions').map do |position|
|
35
|
+
Position.from_vscode_position(position)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [String]
|
40
|
+
def uri
|
41
|
+
request.dig('params', 'textDocument', 'uri')
|
42
|
+
end
|
43
|
+
|
44
|
+
class SelectionRangeProvider
|
45
|
+
class << self
|
46
|
+
# @param source [Rucoa::Source]
|
47
|
+
# @param position [Rucoa::Position]
|
48
|
+
# @return [Hash, nil]
|
49
|
+
def call(position:, source:)
|
50
|
+
new(
|
51
|
+
position: position,
|
52
|
+
source: source
|
53
|
+
).call
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param position [Rucoa::Position]
|
58
|
+
# @param source [Rucoa::Source]
|
59
|
+
def initialize(position:, source:)
|
60
|
+
@position = position
|
61
|
+
@source = source
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Hash, nil]
|
65
|
+
def call
|
66
|
+
ranges.reverse.reduce(nil) do |result, range|
|
67
|
+
{
|
68
|
+
parent: result,
|
69
|
+
range: range.to_vscode_range
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# @return [Rucoa::Nodes::Base, nil]
|
77
|
+
def node_at_position
|
78
|
+
if instance_variable_defined?(:@node_at_position)
|
79
|
+
@node_at_position
|
80
|
+
else
|
81
|
+
@node_at_position = @source.node_at(@position)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [Array<Rucoa::Range>]
|
86
|
+
def ranges
|
87
|
+
return [] unless node_at_position
|
88
|
+
|
89
|
+
[node_at_position, *node_at_position.ancestors].flat_map do |node|
|
90
|
+
NodeToRangesMapper.call(node)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class NodeToRangesMapper
|
95
|
+
class << self
|
96
|
+
# @param node [Rucoa::Nodes::Base]
|
97
|
+
# @return [Array<Rucoa::Range>]
|
98
|
+
def call(node)
|
99
|
+
new(node).call
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# @param node [Rucoa::Nodes::Base]
|
104
|
+
def initialize(node)
|
105
|
+
@node = node
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [Array<Rucoa::Range>]
|
109
|
+
def call
|
110
|
+
case @node
|
111
|
+
when Nodes::StrNode
|
112
|
+
[
|
113
|
+
inner_range,
|
114
|
+
expression_range
|
115
|
+
]
|
116
|
+
else
|
117
|
+
[
|
118
|
+
expression_range
|
119
|
+
]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# @return [Rucoa::Range]
|
126
|
+
def inner_range
|
127
|
+
Range.new(
|
128
|
+
Position.from_parser_range_ending(@node.location.begin),
|
129
|
+
Position.from_parser_range_beginning(@node.location.end)
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
# @return [Rucoa::Range]
|
134
|
+
def expression_range
|
135
|
+
Range.from_parser_range(@node.location.expression)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
23
139
|
end
|
24
140
|
end
|
25
141
|
end
|
@@ -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,14 +3,18 @@
|
|
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'
|
9
11
|
autoload :TextDocumentDidChangeHandler, 'rucoa/handlers/text_document_did_change_handler'
|
10
12
|
autoload :TextDocumentDidOpenHandler, 'rucoa/handlers/text_document_did_open_handler'
|
13
|
+
autoload :TextDocumentDocumentSymbolHandler, 'rucoa/handlers/text_document_document_symbol_handler'
|
11
14
|
autoload :TextDocumentFormattingHandler, 'rucoa/handlers/text_document_formatting_handler'
|
12
15
|
autoload :TextDocumentRangeFormattingHandler, 'rucoa/handlers/text_document_range_formatting_handler'
|
13
16
|
autoload :TextDocumentSelectionRangeHandler, 'rucoa/handlers/text_document_selection_range_handler'
|
17
|
+
autoload :TextDocumentSignatureHelpHandler, 'rucoa/handlers/text_document_signature_help_handler'
|
14
18
|
autoload :WorkspaceDidChangeConfigurationHandler, 'rucoa/handlers/workspace_did_change_configuration_handler'
|
15
19
|
end
|
16
20
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rucoa
|
4
|
+
module NodeConcerns
|
5
|
+
module NameFullQualifiable
|
6
|
+
# @return [String]
|
7
|
+
def full_qualified_name
|
8
|
+
[
|
9
|
+
name,
|
10
|
+
*each_ancestor(:class, :constant, :module).map(&:name)
|
11
|
+
].reverse.join('::')
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String]
|
15
|
+
def name
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|