solargraph 0.58.2 → 0.58.3

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +3 -2
  3. data/CHANGELOG.md +3 -0
  4. data/lib/solargraph/bench.rb +45 -45
  5. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  6. data/lib/solargraph/convention/gemfile.rb +15 -15
  7. data/lib/solargraph/convention/gemspec.rb +23 -23
  8. data/lib/solargraph/convention/rakefile.rb +17 -17
  9. data/lib/solargraph/convention.rb +78 -78
  10. data/lib/solargraph/converters/dd.rb +17 -17
  11. data/lib/solargraph/converters/dl.rb +15 -15
  12. data/lib/solargraph/converters/dt.rb +15 -15
  13. data/lib/solargraph/converters/misc.rb +1 -1
  14. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  15. data/lib/solargraph/language_server/error_codes.rb +20 -20
  16. data/lib/solargraph/language_server/message/base.rb +97 -97
  17. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  18. data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -60
  19. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  20. data/lib/solargraph/language_server/message/extended/download_core.rb +19 -19
  21. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  22. data/lib/solargraph/language_server/message/initialize.rb +191 -191
  23. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  24. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  25. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  26. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  27. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -35
  28. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -40
  29. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +26 -26
  30. data/lib/solargraph/language_server/message.rb +94 -94
  31. data/lib/solargraph/language_server/request.rb +27 -27
  32. data/lib/solargraph/language_server/transport/data_reader.rb +74 -74
  33. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  34. data/lib/solargraph/page.rb +92 -92
  35. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  36. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +37 -37
  37. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  38. data/lib/solargraph/parser/parser_gem.rb +12 -12
  39. data/lib/solargraph/parser.rb +23 -23
  40. data/lib/solargraph/pin/constant.rb +45 -45
  41. data/lib/solargraph/rbs_map/core_fills.rb +84 -84
  42. data/lib/solargraph/server_methods.rb +16 -16
  43. data/lib/solargraph/shell.rb +14 -3
  44. data/lib/solargraph/source/chain/array.rb +37 -37
  45. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  46. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  47. data/lib/solargraph/source/chain/link.rb +109 -109
  48. data/lib/solargraph/source/chain/q_call.rb +11 -11
  49. data/lib/solargraph/source/chain/variable.rb +13 -13
  50. data/lib/solargraph/source/chain/z_super.rb +30 -30
  51. data/lib/solargraph/version.rb +1 -1
  52. data/lib/solargraph/yard_tags.rb +20 -20
  53. metadata +2 -2
@@ -1,191 +1,191 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module LanguageServer
5
- module Message
6
- class Initialize < Base
7
- def process
8
- host.configure params['initializationOptions']
9
- host.client_capabilities = params['capabilities']
10
- if support_workspace_folders?
11
- host.prepare_folders params['workspaceFolders']
12
- elsif params['rootUri']
13
- host.prepare UriHelpers.uri_to_file(params['rootUri'])
14
- else
15
- host.prepare params['rootPath']
16
- end
17
- result = {
18
- capabilities: {
19
- textDocumentSync: 2, # @todo What should this be?
20
- workspace: {
21
- workspaceFolders: {
22
- supported: true,
23
- changeNotifications: true
24
- }
25
- }
26
- }
27
- }
28
- # FIXME: lsp default is utf-16, may have different position
29
- result[:capabilities][:positionEncoding] = "utf-32" if params.dig("capabilities", "general", "positionEncodings")&.include?("utf-32")
30
- result[:capabilities].merge! static_completion unless dynamic_registration_for?('textDocument', 'completion')
31
- result[:capabilities].merge! static_signature_help unless dynamic_registration_for?('textDocument', 'signatureHelp')
32
- # result[:capabilities].merge! static_on_type_formatting unless dynamic_registration_for?('textDocument', 'onTypeFormatting')
33
- result[:capabilities].merge! static_hover unless dynamic_registration_for?('textDocument', 'hover')
34
- result[:capabilities].merge! static_document_formatting unless dynamic_registration_for?('textDocument', 'formatting')
35
- result[:capabilities].merge! static_document_symbols unless dynamic_registration_for?('textDocument', 'documentSymbol')
36
- result[:capabilities].merge! static_definitions unless dynamic_registration_for?('textDocument', 'definition')
37
- result[:capabilities].merge! static_type_definitions unless dynamic_registration_for?('textDocument', 'typeDefinition')
38
- result[:capabilities].merge! static_rename unless dynamic_registration_for?('textDocument', 'rename')
39
- result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
40
- result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
41
- result[:capabilities].merge! static_folding_range unless dynamic_registration_for?('textDocument', 'foldingRange')
42
- result[:capabilities].merge! static_highlights unless dynamic_registration_for?('textDocument', 'documentHighlight')
43
- # @todo Temporarily disabled
44
- # result[:capabilities].merge! static_code_action unless dynamic_registration_for?('textDocument', 'codeAction')
45
- set_result result
46
- end
47
-
48
- private
49
-
50
- # @todo '?' methods should type like RBS 'boolish' rather than a strict true or false
51
- # @sg-ignore
52
- def support_workspace_folders?
53
- params['capabilities'] &&
54
- params['capabilities']['workspace'] &&
55
- params['capabilities']['workspace']['workspaceFolders'] &&
56
- params['workspaceFolders']
57
- end
58
-
59
- # @return [Hash{Symbol => undefined}]
60
- def static_completion
61
- return {} unless host.options['completion']
62
- {
63
- completionProvider: {
64
- resolveProvider: true,
65
- triggerCharacters: ['.', ':', '@']
66
- }
67
- }
68
- end
69
-
70
- # @return [Hash{Symbol => BasicObject}]
71
- def static_code_action
72
- {
73
- codeActionProvider: true,
74
- codeActionKinds: ["quickfix"]
75
- }
76
- end
77
-
78
- # @return [Hash{Symbol => BasicObject}]
79
- def static_signature_help
80
- {
81
- signatureHelpProvider: {
82
- triggerCharacters: ['(', ',']
83
- }
84
- }
85
- end
86
-
87
- # @return [Hash{Symbol => Hash{Symbol => String, Array<String>}}]
88
- def static_on_type_formatting
89
- {
90
- documentOnTypeFormattingProvider: {
91
- firstTriggerCharacter: '{',
92
- moreTriggerCharacter: ['(']
93
- }
94
- }
95
- end
96
-
97
- # @return [Hash{Symbol => Boolean}]
98
- def static_hover
99
- return {} unless host.options['hover']
100
- {
101
- hoverProvider: true
102
- }
103
- end
104
-
105
- # @return [Hash{Symbol => Boolean}]
106
- def static_document_formatting
107
- return {} unless host.options['formatting']
108
- {
109
- documentFormattingProvider: true
110
- }
111
- end
112
-
113
- # @return [Hash{Symbol => Boolean}]
114
- def static_document_symbols
115
- return {} unless host.options['symbols']
116
- {
117
- documentSymbolProvider: true
118
- }
119
- end
120
-
121
- # @return [Hash{Symbol => Boolean}]
122
- def static_workspace_symbols
123
- {
124
- workspaceSymbolProvider: true
125
- }
126
- end
127
-
128
- # @return [Hash{Symbol => Boolean}]
129
- def static_definitions
130
- return {} unless host.options['definitions']
131
- {
132
- definitionProvider: true
133
- }
134
- end
135
-
136
- # @return [Hash{Symbol => Boolean}]
137
- def static_type_definitions
138
- return {} unless host.options['typeDefinitions']
139
- {
140
- typeDefinitionProvider: true
141
- }
142
- end
143
-
144
- # @return [Hash{Symbol => Hash{Symbol => Boolean}}]
145
- def static_rename
146
- {
147
- renameProvider: {prepareProvider: true}
148
- }
149
- end
150
-
151
-
152
- # @return [Hash{Symbol => Boolean}]
153
- def static_references
154
- return {} unless host.options['references']
155
- {
156
- referencesProvider: true
157
- }
158
- end
159
-
160
- # @return [Hash{Symbol => Boolean}]
161
- def static_folding_range
162
- return {} unless host.options['folding']
163
- {
164
- foldingRangeProvider: true
165
- }
166
- end
167
-
168
- # @return [Hash{Symbol => Boolean}]
169
- def static_highlights
170
- {
171
- documentHighlightProvider: true
172
- }
173
- end
174
-
175
- # @param section [String]
176
- # @param capability [String]
177
- # @todo Need support for RBS' boolish "type", which doesn't
178
- # enforce strict true/false-ness
179
- # @sg-ignore
180
- def dynamic_registration_for? section, capability
181
- result = (params['capabilities'] &&
182
- params['capabilities'][section] &&
183
- params['capabilities'][section][capability] &&
184
- params['capabilities'][section][capability]['dynamicRegistration'])
185
- host.allow_registration("#{section}/#{capability}") if result
186
- result
187
- end
188
- end
189
- end
190
- end
191
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module LanguageServer
5
+ module Message
6
+ class Initialize < Base
7
+ def process
8
+ host.configure params['initializationOptions']
9
+ host.client_capabilities = params['capabilities']
10
+ if support_workspace_folders?
11
+ host.prepare_folders params['workspaceFolders']
12
+ elsif params['rootUri']
13
+ host.prepare UriHelpers.uri_to_file(params['rootUri'])
14
+ else
15
+ host.prepare params['rootPath']
16
+ end
17
+ result = {
18
+ capabilities: {
19
+ textDocumentSync: 2, # @todo What should this be?
20
+ workspace: {
21
+ workspaceFolders: {
22
+ supported: true,
23
+ changeNotifications: true
24
+ }
25
+ }
26
+ }
27
+ }
28
+ # FIXME: lsp default is utf-16, may have different position
29
+ result[:capabilities][:positionEncoding] = "utf-32" if params.dig("capabilities", "general", "positionEncodings")&.include?("utf-32")
30
+ result[:capabilities].merge! static_completion unless dynamic_registration_for?('textDocument', 'completion')
31
+ result[:capabilities].merge! static_signature_help unless dynamic_registration_for?('textDocument', 'signatureHelp')
32
+ # result[:capabilities].merge! static_on_type_formatting unless dynamic_registration_for?('textDocument', 'onTypeFormatting')
33
+ result[:capabilities].merge! static_hover unless dynamic_registration_for?('textDocument', 'hover')
34
+ result[:capabilities].merge! static_document_formatting unless dynamic_registration_for?('textDocument', 'formatting')
35
+ result[:capabilities].merge! static_document_symbols unless dynamic_registration_for?('textDocument', 'documentSymbol')
36
+ result[:capabilities].merge! static_definitions unless dynamic_registration_for?('textDocument', 'definition')
37
+ result[:capabilities].merge! static_type_definitions unless dynamic_registration_for?('textDocument', 'typeDefinition')
38
+ result[:capabilities].merge! static_rename unless dynamic_registration_for?('textDocument', 'rename')
39
+ result[:capabilities].merge! static_references unless dynamic_registration_for?('textDocument', 'references')
40
+ result[:capabilities].merge! static_workspace_symbols unless dynamic_registration_for?('workspace', 'symbol')
41
+ result[:capabilities].merge! static_folding_range unless dynamic_registration_for?('textDocument', 'foldingRange')
42
+ result[:capabilities].merge! static_highlights unless dynamic_registration_for?('textDocument', 'documentHighlight')
43
+ # @todo Temporarily disabled
44
+ # result[:capabilities].merge! static_code_action unless dynamic_registration_for?('textDocument', 'codeAction')
45
+ set_result result
46
+ end
47
+
48
+ private
49
+
50
+ # @todo '?' methods should type like RBS 'boolish' rather than a strict true or false
51
+ # @sg-ignore
52
+ def support_workspace_folders?
53
+ params['capabilities'] &&
54
+ params['capabilities']['workspace'] &&
55
+ params['capabilities']['workspace']['workspaceFolders'] &&
56
+ params['workspaceFolders']
57
+ end
58
+
59
+ # @return [Hash{Symbol => undefined}]
60
+ def static_completion
61
+ return {} unless host.options['completion']
62
+ {
63
+ completionProvider: {
64
+ resolveProvider: true,
65
+ triggerCharacters: ['.', ':', '@']
66
+ }
67
+ }
68
+ end
69
+
70
+ # @return [Hash{Symbol => BasicObject}]
71
+ def static_code_action
72
+ {
73
+ codeActionProvider: true,
74
+ codeActionKinds: ["quickfix"]
75
+ }
76
+ end
77
+
78
+ # @return [Hash{Symbol => BasicObject}]
79
+ def static_signature_help
80
+ {
81
+ signatureHelpProvider: {
82
+ triggerCharacters: ['(', ',']
83
+ }
84
+ }
85
+ end
86
+
87
+ # @return [Hash{Symbol => Hash{Symbol => String, Array<String>}}]
88
+ def static_on_type_formatting
89
+ {
90
+ documentOnTypeFormattingProvider: {
91
+ firstTriggerCharacter: '{',
92
+ moreTriggerCharacter: ['(']
93
+ }
94
+ }
95
+ end
96
+
97
+ # @return [Hash{Symbol => Boolean}]
98
+ def static_hover
99
+ return {} unless host.options['hover']
100
+ {
101
+ hoverProvider: true
102
+ }
103
+ end
104
+
105
+ # @return [Hash{Symbol => Boolean}]
106
+ def static_document_formatting
107
+ return {} unless host.options['formatting']
108
+ {
109
+ documentFormattingProvider: true
110
+ }
111
+ end
112
+
113
+ # @return [Hash{Symbol => Boolean}]
114
+ def static_document_symbols
115
+ return {} unless host.options['symbols']
116
+ {
117
+ documentSymbolProvider: true
118
+ }
119
+ end
120
+
121
+ # @return [Hash{Symbol => Boolean}]
122
+ def static_workspace_symbols
123
+ {
124
+ workspaceSymbolProvider: true
125
+ }
126
+ end
127
+
128
+ # @return [Hash{Symbol => Boolean}]
129
+ def static_definitions
130
+ return {} unless host.options['definitions']
131
+ {
132
+ definitionProvider: true
133
+ }
134
+ end
135
+
136
+ # @return [Hash{Symbol => Boolean}]
137
+ def static_type_definitions
138
+ return {} unless host.options['typeDefinitions']
139
+ {
140
+ typeDefinitionProvider: true
141
+ }
142
+ end
143
+
144
+ # @return [Hash{Symbol => Hash{Symbol => Boolean}}]
145
+ def static_rename
146
+ {
147
+ renameProvider: {prepareProvider: true}
148
+ }
149
+ end
150
+
151
+
152
+ # @return [Hash{Symbol => Boolean}]
153
+ def static_references
154
+ return {} unless host.options['references']
155
+ {
156
+ referencesProvider: true
157
+ }
158
+ end
159
+
160
+ # @return [Hash{Symbol => Boolean}]
161
+ def static_folding_range
162
+ return {} unless host.options['folding']
163
+ {
164
+ foldingRangeProvider: true
165
+ }
166
+ end
167
+
168
+ # @return [Hash{Symbol => Boolean}]
169
+ def static_highlights
170
+ {
171
+ documentHighlightProvider: true
172
+ }
173
+ end
174
+
175
+ # @param section [String]
176
+ # @param capability [String]
177
+ # @todo Need support for RBS' boolish "type", which doesn't
178
+ # enforce strict true/false-ness
179
+ # @sg-ignore
180
+ def dynamic_registration_for? section, capability
181
+ result = (params['capabilities'] &&
182
+ params['capabilities'][section] &&
183
+ params['capabilities'][section][capability] &&
184
+ params['capabilities'][section][capability]['dynamicRegistration'])
185
+ host.allow_registration("#{section}/#{capability}") if result
186
+ result
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -1,16 +1,16 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph::LanguageServer::Message::TextDocument
4
- class DocumentHighlight < Base
5
- def process
6
- locs = host.references_from(params['textDocument']['uri'], params['position']['line'], params['position']['character'], strip: true, only: true)
7
- result = locs.map do |loc|
8
- {
9
- range: loc.range.to_hash,
10
- kind: 1
11
- }
12
- end
13
- set_result result
14
- end
15
- end
16
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph::LanguageServer::Message::TextDocument
4
+ class DocumentHighlight < Base
5
+ def process
6
+ locs = host.references_from(params['textDocument']['uri'], params['position']['line'], params['position']['character'], strip: true, only: true)
7
+ result = locs.map do |loc|
8
+ {
9
+ range: loc.range.to_hash,
10
+ kind: 1
11
+ }
12
+ end
13
+ set_result result
14
+ end
15
+ end
16
+ end
@@ -1,11 +1,11 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph::LanguageServer::Message::TextDocument
4
- class PrepareRename < Base
5
- def process
6
- line = params['position']['line']
7
- col = params['position']['character']
8
- set_result host.sources.find(params['textDocument']['uri']).cursor_at(Solargraph::Position.new(line, col)).range.to_hash
9
- end
10
- end
11
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph::LanguageServer::Message::TextDocument
4
+ class PrepareRename < Base
5
+ def process
6
+ line = params['position']['line']
7
+ col = params['position']['character']
8
+ set_result host.sources.find(params['textDocument']['uri']).cursor_at(Solargraph::Position.new(line, col)).range.to_hash
9
+ end
10
+ end
11
+ end
@@ -1,16 +1,16 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph::LanguageServer::Message::TextDocument
4
- class References < Base
5
- def process
6
- locs = host.references_from(params['textDocument']['uri'], params['position']['line'], params['position']['character'])
7
- result = locs.map do |loc|
8
- {
9
- uri: file_to_uri(loc.filename),
10
- range: loc.range.to_hash
11
- }
12
- end
13
- set_result result
14
- end
15
- end
16
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph::LanguageServer::Message::TextDocument
4
+ class References < Base
5
+ def process
6
+ locs = host.references_from(params['textDocument']['uri'], params['position']['line'], params['position']['character'])
7
+ result = locs.map do |loc|
8
+ {
9
+ uri: file_to_uri(loc.filename),
10
+ range: loc.range.to_hash
11
+ }
12
+ end
13
+ set_result result
14
+ end
15
+ end
16
+ end
@@ -1,19 +1,19 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph::LanguageServer::Message::TextDocument
4
- class Rename < Base
5
- def process
6
- locs = host.references_from(params['textDocument']['uri'], params['position']['line'], params['position']['character'], strip: true)
7
- changes = {}
8
- locs.each do |loc|
9
- uri = file_to_uri(loc.filename)
10
- changes[uri] ||= []
11
- changes[uri].push({
12
- range: loc.range.to_hash,
13
- newText: params['newName']
14
- })
15
- end
16
- set_result changes: changes
17
- end
18
- end
19
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph::LanguageServer::Message::TextDocument
4
+ class Rename < Base
5
+ def process
6
+ locs = host.references_from(params['textDocument']['uri'], params['position']['line'], params['position']['character'], strip: true)
7
+ changes = {}
8
+ locs.each do |loc|
9
+ uri = file_to_uri(loc.filename)
10
+ changes[uri] ||= []
11
+ changes[uri].push({
12
+ range: loc.range.to_hash,
13
+ newText: params['newName']
14
+ })
15
+ end
16
+ set_result changes: changes
17
+ end
18
+ end
19
+ end
@@ -1,35 +1,35 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph::LanguageServer::Message::Workspace
4
- class DidChangeConfiguration < Solargraph::LanguageServer::Message::Base
5
- def process
6
- return unless params['settings']
7
- update = params['settings']['solargraph']
8
- host.configure update
9
- register_from_options
10
- end
11
-
12
- private
13
-
14
- # @return [void]
15
- def register_from_options
16
- Solargraph.logger.debug "Registering capabilities from options: #{host.options.inspect}"
17
- # @type [Array<String>]
18
- y = []
19
- # @type [Array<String>]
20
- n = []
21
- (host.options['completion'] ? y : n).push('textDocument/completion')
22
- (host.options['hover'] ? y : n).push('textDocument/hover', 'textDocument/signatureHelp')
23
- (host.options['autoformat'] ? y : n).push('textDocument/onTypeFormatting')
24
- (host.options['formatting'] ? y : n).push('textDocument/formatting')
25
- (host.options['symbols'] ? y : n).push('textDocument/documentSymbol', 'workspace/symbol')
26
- (host.options['definitions'] ? y : n).push('textDocument/definition')
27
- (host.options['typeDefinitions'] ? y : n).push('textDocument/typeDefinition')
28
- (host.options['references'] ? y : n).push('textDocument/references')
29
- (host.options['folding'] ? y : n).push('textDocument/folding')
30
- (host.options['highlights'] ? y : n).push('textDocument/documentHighlight')
31
- host.register_capabilities y
32
- host.unregister_capabilities n
33
- end
34
- end
35
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph::LanguageServer::Message::Workspace
4
+ class DidChangeConfiguration < Solargraph::LanguageServer::Message::Base
5
+ def process
6
+ return unless params['settings']
7
+ update = params['settings']['solargraph']
8
+ host.configure update
9
+ register_from_options
10
+ end
11
+
12
+ private
13
+
14
+ # @return [void]
15
+ def register_from_options
16
+ Solargraph.logger.debug "Registering capabilities from options: #{host.options.inspect}"
17
+ # @type [Array<String>]
18
+ y = []
19
+ # @type [Array<String>]
20
+ n = []
21
+ (host.options['completion'] ? y : n).push('textDocument/completion')
22
+ (host.options['hover'] ? y : n).push('textDocument/hover', 'textDocument/signatureHelp')
23
+ (host.options['autoformat'] ? y : n).push('textDocument/onTypeFormatting')
24
+ (host.options['formatting'] ? y : n).push('textDocument/formatting')
25
+ (host.options['symbols'] ? y : n).push('textDocument/documentSymbol', 'workspace/symbol')
26
+ (host.options['definitions'] ? y : n).push('textDocument/definition')
27
+ (host.options['typeDefinitions'] ? y : n).push('textDocument/typeDefinition')
28
+ (host.options['references'] ? y : n).push('textDocument/references')
29
+ (host.options['folding'] ? y : n).push('textDocument/folding')
30
+ (host.options['highlights'] ? y : n).push('textDocument/documentHighlight')
31
+ host.register_capabilities y
32
+ host.unregister_capabilities n
33
+ end
34
+ end
35
+ end