rucoa 0.5.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +12 -13
  4. data/data/definitions_ruby_3_1 +0 -0
  5. data/lib/rucoa/cli.rb +3 -2
  6. data/lib/rucoa/configuration.rb +69 -16
  7. data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +14 -2
  8. data/lib/rucoa/handlers/initialize_handler.rb +7 -0
  9. data/lib/rucoa/handlers/initialized_handler.rb +1 -1
  10. data/lib/rucoa/handlers/text_document_completion_handler.rb +223 -0
  11. data/lib/rucoa/handlers/text_document_did_close_handler.rb +20 -0
  12. data/lib/rucoa/handlers/text_document_formatting_handler.rb +2 -2
  13. data/lib/rucoa/handlers/text_document_hover_handler.rb +76 -0
  14. data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +2 -2
  15. data/lib/rucoa/handlers.rb +3 -0
  16. data/lib/rucoa/node_inspector.rb +13 -1
  17. data/lib/rucoa/position.rb +12 -1
  18. data/lib/rucoa/{definition_builders/rbs_constant_definition_builder.rb → rbs/constant_definition_mapper.rb} +4 -8
  19. data/lib/rucoa/{definition_builders/rbs_method_definition_builder.rb → rbs/method_definition_mapper.rb} +4 -7
  20. data/lib/rucoa/rbs/ruby_definitions_loader.rb +78 -0
  21. data/lib/rucoa/rbs.rb +9 -0
  22. data/lib/rucoa/rubocop/autocorrector.rb +40 -0
  23. data/lib/rucoa/rubocop/configuration_checker.rb +44 -0
  24. data/lib/rucoa/rubocop/investigator.rb +50 -0
  25. data/lib/rucoa/rubocop.rb +9 -0
  26. data/lib/rucoa/server.rb +45 -12
  27. data/lib/rucoa/source.rb +6 -1
  28. data/lib/rucoa/version.rb +1 -1
  29. data/lib/rucoa/{definition_builders/yard_method_definition_builder.rb → yard/definition_mapper.rb} +20 -21
  30. data/lib/rucoa/yard/definitions_loader.rb +62 -0
  31. data/lib/rucoa/yard.rb +8 -0
  32. data/lib/rucoa.rb +3 -7
  33. metadata +16 -12
  34. data/lib/rucoa/definition_builders.rb +0 -9
  35. data/lib/rucoa/rbs_document_loader.rb +0 -43
  36. data/lib/rucoa/rubocop_autocorrector.rb +0 -38
  37. data/lib/rucoa/rubocop_configuration_checker.rb +0 -42
  38. data/lib/rucoa/rubocop_investigator.rb +0 -48
  39. data/lib/rucoa/yard_glob_document_loader.rb +0 -47
  40. data/lib/rucoa/yard_string_document_loader.rb +0 -70
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ffd244eb4ed0935120e2d33a03798897a4880e06ff999c1779a920e4926215c
4
- data.tar.gz: fe7296dba2ff6d185a729e6649cd9630a5644961837d28306f3a5a193643d38e
3
+ metadata.gz: 48f65475f89a895b8fa3429ddcb5a10738c78e2181a0a0f41a8fe14ec8a2fd17
4
+ data.tar.gz: b94bffab0ae35cf83ee0ae5146f41b583abcea4b4192eabcdc8acbcedf3418b4
5
5
  SHA512:
6
- metadata.gz: 9f9965f568980d2f069a5670dcf5e008986399b8826a331410bdd0f31cacf10a01068bc8e37109241ccd2c1e79bf9f0bc639600b7608260fffd02b07251e310b
7
- data.tar.gz: 1143b279fbbf845f07f0654b37eadf20226d96b1dc930ceea5fd9fc3daf90b6bd786d3a55c08b9601019d85b0e79284de1268de5ed628136cb0097be3e6af846
6
+ metadata.gz: 1693536178207fc2740ede4806a8803f140477b312c143e7ad0284875c1685244a09fa33dcd6208e993f4d0acb87284391a605a27e09d8479c71f556cf951d7f
7
+ data.tar.gz: d4458ea8223b032e5df2680bfa4f8ed2f939f2971a19db327306a3c6fb6a9a6b3810ffd8ed56346b6e7defb36b916e9054bcb71d031f2494c30b0d6f216995eb
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rucoa (0.5.1)
4
+ rucoa (0.7.0)
5
5
  parser
6
6
  rbs
7
7
  rubocop
data/README.md CHANGED
@@ -15,15 +15,6 @@ To install rucoa gem, if your project is managed by bundler, add to your Gemfile
15
15
  gem 'rucoa'
16
16
  ```
17
17
 
18
- or in Rails application, we'll recommend you to do like this:
19
-
20
- ```ruby
21
- # Gemfile
22
- group :development do
23
- gem 'rucoa', require: false
24
- end
25
- ```
26
-
27
18
  If bundler is not being used to manage dependencies, simply install the gem:
28
19
 
29
20
  ```bash
@@ -65,14 +56,22 @@ This extension supports the folowiing types of symbols:
65
56
 
66
57
  ![demo](images/document-symbol.gif)
67
58
 
68
- ### Signature help (experimental)
59
+ ## Experimental features
60
+
61
+ ### Completion
62
+
63
+ Provides completion items for constant names and method names.
64
+
65
+ ### Hover
66
+
67
+ Shows documentation for the symbol under the cursor.
68
+
69
+ ### Signature help
69
70
 
70
71
  Shows method signature help when you start to type method arguments like `"100".to_i(`.
71
72
 
72
- ### Coming soon
73
+ ## Coming soon
73
74
 
74
- - Completion
75
- - Documentation
76
75
  - Go to Definition
77
76
  - Highlight
78
77
  - Semantic Tokens
Binary file
data/lib/rucoa/cli.rb CHANGED
@@ -16,8 +16,9 @@ module Rucoa
16
16
  # @return [void]
17
17
  def call
18
18
  Server.new(
19
- input: $stdin,
20
- output: $stdout
19
+ io_in: $stdin,
20
+ io_log: $stderr,
21
+ io_out: $stdout
21
22
  ).start
22
23
  end
23
24
  end
@@ -8,62 +8,108 @@ module Rucoa
8
8
 
9
9
  # @return [void]
10
10
  def disable_code_action
11
- disable('codeAction')
11
+ disable_feature('codeAction')
12
+ end
13
+
14
+ # @return [void]
15
+ def disable_completion
16
+ disable_feature('completion')
12
17
  end
13
18
 
14
19
  # @return [void]
15
20
  def disable_diagnostics
16
- disable('diagnostics')
21
+ disable_feature('diagnostics')
17
22
  end
18
23
 
19
24
  # @return [void]
20
25
  def disable_document_symbol
21
- disable('documentSymbol')
26
+ disable_feature('documentSymbol')
22
27
  end
23
28
 
24
29
  # @return [void]
25
30
  def disable_formatting
26
- disable('formatting')
31
+ disable_feature('formatting')
32
+ end
33
+
34
+ # @return [void]
35
+ def disable_hover
36
+ disable_feature('hover')
27
37
  end
28
38
 
29
39
  # @return [void]
30
40
  def disable_selection_range
31
- disable('selectionRange')
41
+ disable_feature('selectionRange')
32
42
  end
33
43
 
34
44
  # @return [void]
35
45
  def disable_signature_help
36
- disable('signatureHelp')
46
+ disable_feature('signatureHelp')
47
+ end
48
+
49
+ # @return [void]
50
+ def enable_debug
51
+ @settings ||= {}
52
+ @settings['base'] ||= {}
53
+ @settings['base']['debug'] = true
37
54
  end
38
55
 
39
56
  # @return [Boolean]
57
+ # @example returns false if the configuration is empty
58
+ # configuration = Rucoa::Configuration.new
59
+ # expect(configuration).not_to be_enables_debug
60
+ # @example returns true if the configuration enables debug
61
+ # configuration = Rucoa::Configuration.new
62
+ # configuration.update('base' => { 'debug' => true })
63
+ # expect(configuration).to be_enables_debug
64
+ def enables_debug?
65
+ fetch('base', 'debug', default: false)
66
+ end
67
+
68
+ # @return [Boolean]
69
+ # @example returns true if the configuration is empty
70
+ # configuration = Rucoa::Configuration.new
71
+ # expect(configuration).to be_enables_code_action
72
+ # @example returns false if the configuration disables code action
73
+ # configuration = Rucoa::Configuration.new
74
+ # configuration.disable_code_action
75
+ # expect(configuration).not_to be_enables_code_action
40
76
  def enables_code_action?
41
- enables?('codeAction')
77
+ enables_feature?('codeAction')
78
+ end
79
+
80
+ # @return [Boolean]
81
+ def enables_completion?
82
+ enables_feature?('completion')
42
83
  end
43
84
 
44
85
  # @return [Boolean]
45
86
  def enables_diagnostics?
46
- enables?('diagnostics')
87
+ enables_feature?('diagnostics')
47
88
  end
48
89
 
49
90
  # @return [Boolean]
50
91
  def enables_document_symbol?
51
- enables?('documentSymbol')
92
+ enables_feature?('documentSymbol')
52
93
  end
53
94
 
54
95
  # @return [Boolean]
55
96
  def enables_formatting?
56
- enables?('formatting')
97
+ enables_feature?('formatting')
98
+ end
99
+
100
+ # @return [Boolean]
101
+ def enables_hover?
102
+ enables_feature?('hover')
57
103
  end
58
104
 
59
105
  # @return [Boolean]
60
106
  def enables_selection_range?
61
- enables?('selectionRange')
107
+ enables_feature?('selectionRange')
62
108
  end
63
109
 
64
110
  # @return [Boolean]
65
111
  def enables_signature_help?
66
- enables?('signatureHelp')
112
+ enables_feature?('signatureHelp')
67
113
  end
68
114
 
69
115
  # @param settings [Hash]
@@ -76,7 +122,7 @@ module Rucoa
76
122
 
77
123
  # @param feature [String]
78
124
  # @return [void]
79
- def disable(feature)
125
+ def disable_feature(feature)
80
126
  @settings ||= {}
81
127
  @settings['feature'] ||= {}
82
128
  @settings['feature'][feature] ||= {}
@@ -85,10 +131,17 @@ module Rucoa
85
131
 
86
132
  # @param feature [String]
87
133
  # @return [Boolean]
88
- def enables?(feature)
89
- value = @settings.dig('feature', feature, 'enable')
134
+ def enables_feature?(feature)
135
+ fetch('feature', feature, 'enable', default: true)
136
+ end
137
+
138
+ # @param keys [Array<String>]
139
+ # @param default [Object]
140
+ # @return [Object]
141
+ def fetch(*keys, default:)
142
+ value = @settings.dig(*keys)
90
143
  if value.nil?
91
- true
144
+ default
92
145
  else
93
146
  value
94
147
  end
@@ -16,6 +16,18 @@ module Rucoa
16
16
  )
17
17
  end
18
18
 
19
+ # @param uri [String]
20
+ # @return [void]
21
+ def clear_diagnostics_on(uri)
22
+ write(
23
+ method: 'textDocument/publishDiagnostics',
24
+ params: {
25
+ diagnostics: [],
26
+ uri: uri
27
+ }
28
+ )
29
+ end
30
+
19
31
  # @param uri [String]
20
32
  # @return [void]
21
33
  def publish_diagnostics_on(uri)
@@ -48,7 +60,7 @@ module Rucoa
48
60
 
49
61
  # @return [Array<Hash>]
50
62
  def call
51
- return [] unless RubocopConfigurationChecker.call
63
+ return [] unless Rubocop::ConfigurationChecker.call
52
64
 
53
65
  offenses.map do |offense|
54
66
  OffenseToDiagnosticMapper.call(
@@ -63,7 +75,7 @@ module Rucoa
63
75
 
64
76
  # @return [Array<RuboCop::Cop::Offense>]
65
77
  def offenses
66
- RubocopInvestigator.call(source: @source)
78
+ Rubocop::Investigator.call(source: @source)
67
79
  end
68
80
 
69
81
  class OffenseToDiagnosticMapper
@@ -7,9 +7,16 @@ module Rucoa
7
7
  respond(
8
8
  capabilities: {
9
9
  codeActionProvider: true,
10
+ completionProvider: {
11
+ resolveProvider: true,
12
+ triggerCharacters: %w[
13
+ .
14
+ ]
15
+ },
10
16
  documentFormattingProvider: true,
11
17
  documentRangeFormattingProvider: true,
12
18
  documentSymbolProvider: true,
19
+ hoverProvider: true,
13
20
  selectionRangeProvider: true,
14
21
  signatureHelpProvider: {
15
22
  triggerCharacters: %w[
@@ -14,7 +14,7 @@ module Rucoa
14
14
 
15
15
  # @return [void]
16
16
  def load_definitions
17
- YardGlobDocumentLoader.call(
17
+ Yard::DefinitionsLoader.load_globs(
18
18
  globs: ::YARD::Parser::SourceParser::DEFAULT_PATH_GLOB
19
19
  )
20
20
  end
@@ -0,0 +1,223 @@
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(
212
+ case node
213
+ when Nodes::SendNode
214
+ node.location.selector
215
+ else
216
+ node.location.expression
217
+ end
218
+ )
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Handlers
5
+ class TextDocumentDidCloseHandler < Base
6
+ include HandlerConcerns::DiagnosticsPublishable
7
+
8
+ def call
9
+ clear_diagnostics_on(uri)
10
+ end
11
+
12
+ private
13
+
14
+ # @return [String]
15
+ def uri
16
+ request.dig('params', 'textDocument', 'uri')
17
+ end
18
+ end
19
+ end
20
+ end
@@ -13,7 +13,7 @@ module Rucoa
13
13
  def formattable?
14
14
  configuration.enables_formatting? &&
15
15
  source &&
16
- RubocopConfigurationChecker.call
16
+ Rubocop::ConfigurationChecker.call
17
17
  end
18
18
 
19
19
  # @return [Array<Hash>]
@@ -43,7 +43,7 @@ module Rucoa
43
43
 
44
44
  # @return [String]
45
45
  def new_text
46
- RubocopAutocorrector.call(source: source)
46
+ Rubocop::Autocorrector.call(source: source)
47
47
  end
48
48
 
49
49
  # @return [Hash]
@@ -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
@@ -25,7 +25,7 @@ module Rucoa
25
25
  def formattable?
26
26
  configuration.enables_formatting? &&
27
27
  source &&
28
- RubocopConfigurationChecker.call
28
+ Rubocop::ConfigurationChecker.call
29
29
  end
30
30
 
31
31
  # @return [Rucoa::Source]
@@ -59,7 +59,7 @@ module Rucoa
59
59
 
60
60
  # @return [Array<RuboCop::Cop::Offense>]
61
61
  def offenses
62
- RubocopInvestigator.call(source: source)
62
+ Rubocop::Investigator.call(source: source)
63
63
  end
64
64
 
65
65
  # @return [Array(Rucoa::Range, String)]
@@ -8,10 +8,13 @@ module Rucoa
8
8
  autoload :InitializedHandler, 'rucoa/handlers/initialized_handler'
9
9
  autoload :ShutdownHandler, 'rucoa/handlers/shutdown_handler'
10
10
  autoload :TextDocumentCodeActionHandler, 'rucoa/handlers/text_document_code_action_handler'
11
+ autoload :TextDocumentCompletionHandler, 'rucoa/handlers/text_document_completion_handler'
11
12
  autoload :TextDocumentDidChangeHandler, 'rucoa/handlers/text_document_did_change_handler'
13
+ autoload :TextDocumentDidCloseHandler, 'rucoa/handlers/text_document_did_close_handler'
12
14
  autoload :TextDocumentDidOpenHandler, 'rucoa/handlers/text_document_did_open_handler'
13
15
  autoload :TextDocumentDocumentSymbolHandler, 'rucoa/handlers/text_document_document_symbol_handler'
14
16
  autoload :TextDocumentFormattingHandler, 'rucoa/handlers/text_document_formatting_handler'
17
+ autoload :TextDocumentHoverHandler, 'rucoa/handlers/text_document_hover_handler'
15
18
  autoload :TextDocumentRangeFormattingHandler, 'rucoa/handlers/text_document_range_formatting_handler'
16
19
  autoload :TextDocumentSelectionRangeHandler, 'rucoa/handlers/text_document_selection_range_handler'
17
20
  autoload :TextDocumentSignatureHelpHandler, 'rucoa/handlers/text_document_signature_help_handler'
@@ -80,7 +80,19 @@ module Rucoa
80
80
  [
81
81
  type,
82
82
  @node.name
83
- ].join('#')
83
+ ].join(method_kind_symbol)
84
+ end
85
+ end
86
+
87
+ # @return [String, nil]
88
+ def method_kind_symbol
89
+ return unless @node.is_a?(Nodes::SendNode)
90
+
91
+ case @node.receiver
92
+ when Nodes::ConstNode
93
+ '.'
94
+ else
95
+ '#'
84
96
  end
85
97
  end
86
98