ruby-lsp 0.3.8 → 0.4.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/README.md +39 -1
- data/VERSION +1 -1
- data/exe/ruby-lsp +2 -1
- data/lib/ruby_lsp/executor.rb +362 -0
- data/lib/ruby_lsp/internal.rb +6 -1
- data/lib/ruby_lsp/requests/base_request.rb +10 -3
- data/lib/ruby_lsp/requests/code_actions.rb +21 -7
- data/lib/ruby_lsp/requests/diagnostics.rb +7 -11
- data/lib/ruby_lsp/requests/formatting.rb +8 -5
- data/lib/ruby_lsp/requests/on_type_formatting.rb +33 -14
- data/lib/ruby_lsp/requests/path_completion.rb +88 -0
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +35 -11
- data/lib/ruby_lsp/requests/support/annotation.rb +46 -0
- data/lib/ruby_lsp/requests/support/highlight_target.rb +14 -3
- data/lib/ruby_lsp/requests/support/prefix_tree.rb +80 -0
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +29 -44
- data/lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb +1 -1
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +27 -1
- data/lib/ruby_lsp/requests/support/sorbet.rb +120 -0
- data/lib/ruby_lsp/requests.rb +5 -1
- data/lib/ruby_lsp/server.rb +128 -221
- data/lib/ruby_lsp/utils.rb +78 -0
- metadata +12 -9
- data/lib/ruby_lsp/handler.rb +0 -118
- data/lib/ruby_lsp/queue.rb +0 -182
- data/lib/ruby_lsp/requests/support/syntax_error_diagnostic.rb +0 -32
@@ -0,0 +1,88 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Requests
|
6
|
+
# 
|
7
|
+
#
|
8
|
+
# The [completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
|
9
|
+
# request looks up Ruby files in the $LOAD_PATH to suggest path completion inside `require` statements.
|
10
|
+
#
|
11
|
+
# # Example
|
12
|
+
#
|
13
|
+
# ```ruby
|
14
|
+
# require "ruby_lsp/requests" # --> completion: suggests `base_request`, `code_actions`, ...
|
15
|
+
# ```
|
16
|
+
class PathCompletion < BaseRequest
|
17
|
+
extend T::Sig
|
18
|
+
|
19
|
+
sig { params(document: Document, position: Document::PositionShape).void }
|
20
|
+
def initialize(document, position)
|
21
|
+
super(document)
|
22
|
+
|
23
|
+
@tree = T.let(Support::PrefixTree.new(collect_load_path_files), Support::PrefixTree)
|
24
|
+
|
25
|
+
char_position = document.create_scanner.find_char_position(position)
|
26
|
+
@target = T.let(find(char_position), T.nilable(SyntaxTree::TStringContent))
|
27
|
+
end
|
28
|
+
|
29
|
+
sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::CompletionItem], Object)) }
|
30
|
+
def run
|
31
|
+
# no @target means the we are not inside a `require` call
|
32
|
+
return [] unless @target
|
33
|
+
|
34
|
+
text = @target.value
|
35
|
+
@tree.search(text).sort.map! do |path|
|
36
|
+
build_completion(path, path.delete_prefix(text))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
sig { returns(T::Array[String]) }
|
43
|
+
def collect_load_path_files
|
44
|
+
$LOAD_PATH.flat_map do |p|
|
45
|
+
Dir.glob("**/*.rb", base: p)
|
46
|
+
end.map! do |result|
|
47
|
+
result.delete_suffix!(".rb")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
sig { params(position: Integer).returns(T.nilable(SyntaxTree::TStringContent)) }
|
52
|
+
def find(position)
|
53
|
+
matched, parent = locate(
|
54
|
+
T.must(@document.tree),
|
55
|
+
position,
|
56
|
+
node_types: [SyntaxTree::Command, SyntaxTree::CommandCall, SyntaxTree::CallNode],
|
57
|
+
)
|
58
|
+
|
59
|
+
return unless matched && parent
|
60
|
+
|
61
|
+
case matched
|
62
|
+
when SyntaxTree::Command, SyntaxTree::CallNode, SyntaxTree::CommandCall
|
63
|
+
return unless matched.message.value == "require"
|
64
|
+
|
65
|
+
args = matched.arguments
|
66
|
+
args = args.arguments if args.is_a?(SyntaxTree::ArgParen)
|
67
|
+
|
68
|
+
path_node = args.parts.first.parts.first
|
69
|
+
return unless path_node
|
70
|
+
return unless (path_node.location.start_char..path_node.location.end_char).cover?(position)
|
71
|
+
|
72
|
+
path_node
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
sig do
|
77
|
+
params(label: String, insert_text: String).returns(LanguageServer::Protocol::Interface::CompletionItem)
|
78
|
+
end
|
79
|
+
def build_completion(label, insert_text)
|
80
|
+
LanguageServer::Protocol::Interface::CompletionItem.new(
|
81
|
+
label: label,
|
82
|
+
insert_text: insert_text,
|
83
|
+
kind: LanguageServer::Protocol::Constant::CompletionItemKind::REFERENCE,
|
84
|
+
)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -20,7 +20,7 @@ module RubyLsp
|
|
20
20
|
# ```
|
21
21
|
class SemanticHighlighting < BaseRequest
|
22
22
|
extend T::Sig
|
23
|
-
include SyntaxTree::
|
23
|
+
include SyntaxTree::WithScope
|
24
24
|
|
25
25
|
TOKEN_TYPES = T.let(
|
26
26
|
{
|
@@ -78,11 +78,28 @@ module RubyLsp
|
|
78
78
|
T::Array[String],
|
79
79
|
)
|
80
80
|
|
81
|
-
class SemanticToken
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
81
|
+
class SemanticToken
|
82
|
+
extend T::Sig
|
83
|
+
|
84
|
+
sig { returns(SyntaxTree::Location) }
|
85
|
+
attr_reader :location
|
86
|
+
|
87
|
+
sig { returns(Integer) }
|
88
|
+
attr_reader :length
|
89
|
+
|
90
|
+
sig { returns(Integer) }
|
91
|
+
attr_reader :type
|
92
|
+
|
93
|
+
sig { returns(T::Array[Integer]) }
|
94
|
+
attr_reader :modifier
|
95
|
+
|
96
|
+
sig { params(location: SyntaxTree::Location, length: Integer, type: Integer, modifier: T::Array[Integer]).void }
|
97
|
+
def initialize(location:, length:, type:, modifier:)
|
98
|
+
@location = location
|
99
|
+
@length = length
|
100
|
+
@type = type
|
101
|
+
@modifier = modifier
|
102
|
+
end
|
86
103
|
end
|
87
104
|
|
88
105
|
sig do
|
@@ -126,8 +143,10 @@ module RubyLsp
|
|
126
143
|
visit(node.receiver)
|
127
144
|
|
128
145
|
message = node.message
|
129
|
-
|
130
|
-
|
146
|
+
if message != :call && !special_method?(message.value)
|
147
|
+
type = Support::Sorbet.annotation?(node) ? :type : :method
|
148
|
+
|
149
|
+
add_token(message.location, type)
|
131
150
|
end
|
132
151
|
|
133
152
|
visit(node.arguments)
|
@@ -137,7 +156,9 @@ module RubyLsp
|
|
137
156
|
def visit_command(node)
|
138
157
|
return super unless visible?(node, @range)
|
139
158
|
|
140
|
-
|
159
|
+
unless special_method?(node.message.value)
|
160
|
+
add_token(node.message.location, :method)
|
161
|
+
end
|
141
162
|
visit(node.arguments)
|
142
163
|
end
|
143
164
|
|
@@ -243,7 +264,10 @@ module RubyLsp
|
|
243
264
|
def visit_vcall(node)
|
244
265
|
return super unless visible?(node, @range)
|
245
266
|
|
246
|
-
|
267
|
+
return if special_method?(node.value.value)
|
268
|
+
|
269
|
+
type = Support::Sorbet.annotation?(node) ? :type : :method
|
270
|
+
add_token(node.value.location, type)
|
247
271
|
end
|
248
272
|
|
249
273
|
sig { override.params(node: SyntaxTree::ClassDeclaration).void }
|
@@ -305,7 +329,7 @@ module RubyLsp
|
|
305
329
|
|
306
330
|
sig { params(value: SyntaxTree::Ident).returns(Symbol) }
|
307
331
|
def type_for_local(value)
|
308
|
-
local =
|
332
|
+
local = current_scope.find_local(value.value)
|
309
333
|
|
310
334
|
if local.nil? || local.type == :variable
|
311
335
|
:variable
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Requests
|
6
|
+
module Support
|
7
|
+
class Annotation
|
8
|
+
extend T::Sig
|
9
|
+
sig do
|
10
|
+
params(
|
11
|
+
arity: T.any(Integer, T::Range[Integer]),
|
12
|
+
receiver: T::Boolean,
|
13
|
+
).void
|
14
|
+
end
|
15
|
+
def initialize(arity:, receiver: false)
|
16
|
+
@arity = arity
|
17
|
+
@receiver = receiver
|
18
|
+
end
|
19
|
+
|
20
|
+
sig { returns(T.any(Integer, T::Range[Integer])) }
|
21
|
+
attr_reader :arity
|
22
|
+
|
23
|
+
sig { returns(T::Boolean) }
|
24
|
+
attr_reader :receiver
|
25
|
+
|
26
|
+
sig { params(arity: T.any(T::Range[Integer], Integer)).returns(T::Boolean) }
|
27
|
+
def supports_arity?(arity)
|
28
|
+
if @arity.is_a?(Integer)
|
29
|
+
@arity == arity
|
30
|
+
elsif @arity.is_a?(Range)
|
31
|
+
@arity.cover?(arity)
|
32
|
+
else
|
33
|
+
T.absurd(@arity)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
sig { params(receiver: T.nilable(String)).returns(T::Boolean) }
|
38
|
+
def supports_receiver?(receiver)
|
39
|
+
return receiver.nil? || receiver.empty? if @receiver == false
|
40
|
+
|
41
|
+
receiver == "T"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -10,9 +10,20 @@ module RubyLsp
|
|
10
10
|
READ = LanguageServer::Protocol::Constant::DocumentHighlightKind::READ
|
11
11
|
WRITE = LanguageServer::Protocol::Constant::DocumentHighlightKind::WRITE
|
12
12
|
|
13
|
-
class HighlightMatch
|
14
|
-
|
15
|
-
|
13
|
+
class HighlightMatch
|
14
|
+
extend T::Sig
|
15
|
+
|
16
|
+
sig { returns(Integer) }
|
17
|
+
attr_reader :type
|
18
|
+
|
19
|
+
sig { returns(SyntaxTree::Node) }
|
20
|
+
attr_reader :node
|
21
|
+
|
22
|
+
sig { params(type: Integer, node: SyntaxTree::Node).void }
|
23
|
+
def initialize(type:, node:)
|
24
|
+
@type = type
|
25
|
+
@node = node
|
26
|
+
end
|
16
27
|
end
|
17
28
|
|
18
29
|
sig { params(node: SyntaxTree::Node).void }
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Requests
|
6
|
+
module Support
|
7
|
+
class PrefixTree
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { params(items: T::Array[String]).void }
|
11
|
+
def initialize(items)
|
12
|
+
@root = T.let(Node.new(""), Node)
|
13
|
+
|
14
|
+
items.each do |item|
|
15
|
+
insert(item)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
sig { params(prefix: String).returns(T::Array[String]) }
|
20
|
+
def search(prefix)
|
21
|
+
node = T.let(@root, Node)
|
22
|
+
|
23
|
+
prefix.each_char do |char|
|
24
|
+
snode = node.children[char]
|
25
|
+
return [] unless snode
|
26
|
+
|
27
|
+
node = snode
|
28
|
+
end
|
29
|
+
|
30
|
+
node.collect
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
sig { params(item: String).void }
|
36
|
+
def insert(item)
|
37
|
+
node = T.let(@root, Node)
|
38
|
+
|
39
|
+
item.each_char do |char|
|
40
|
+
node = node.children[char] ||= Node.new(node.value + char)
|
41
|
+
end
|
42
|
+
|
43
|
+
node.leaf = true
|
44
|
+
end
|
45
|
+
|
46
|
+
class Node
|
47
|
+
extend T::Sig
|
48
|
+
|
49
|
+
sig { returns(T::Hash[String, Node]) }
|
50
|
+
attr_reader :children
|
51
|
+
|
52
|
+
sig { returns(String) }
|
53
|
+
attr_reader :value
|
54
|
+
|
55
|
+
sig { returns(T::Boolean) }
|
56
|
+
attr_accessor :leaf
|
57
|
+
|
58
|
+
sig { params(value: String).void }
|
59
|
+
def initialize(value)
|
60
|
+
@children = T.let({}, T::Hash[String, Node])
|
61
|
+
@value = T.let(value, String)
|
62
|
+
@leaf = T.let(false, T::Boolean)
|
63
|
+
end
|
64
|
+
|
65
|
+
sig { returns(T::Array[String]) }
|
66
|
+
def collect
|
67
|
+
result = T.let([], T::Array[String])
|
68
|
+
result << value if leaf
|
69
|
+
|
70
|
+
children.each_value do |node|
|
71
|
+
result.concat(node.collect)
|
72
|
+
end
|
73
|
+
|
74
|
+
result
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -9,52 +9,35 @@ module RubyLsp
|
|
9
9
|
|
10
10
|
RUBOCOP_TO_LSP_SEVERITY = T.let(
|
11
11
|
{
|
12
|
-
convention:
|
13
|
-
info:
|
14
|
-
refactor:
|
15
|
-
warning:
|
16
|
-
error:
|
17
|
-
fatal:
|
12
|
+
convention: Constant::DiagnosticSeverity::INFORMATION,
|
13
|
+
info: Constant::DiagnosticSeverity::INFORMATION,
|
14
|
+
refactor: Constant::DiagnosticSeverity::INFORMATION,
|
15
|
+
warning: Constant::DiagnosticSeverity::WARNING,
|
16
|
+
error: Constant::DiagnosticSeverity::ERROR,
|
17
|
+
fatal: Constant::DiagnosticSeverity::ERROR,
|
18
18
|
}.freeze,
|
19
19
|
T::Hash[Symbol, Integer],
|
20
20
|
)
|
21
21
|
|
22
|
-
sig { returns(T::Array[LanguageServer::Protocol::Interface::TextEdit]) }
|
23
|
-
attr_reader :replacements
|
24
|
-
|
25
22
|
sig { params(offense: RuboCop::Cop::Offense, uri: String).void }
|
26
23
|
def initialize(offense, uri)
|
27
24
|
@offense = offense
|
28
25
|
@uri = uri
|
29
|
-
@replacements = T.let(
|
30
|
-
offense.correctable? ? offense_replacements : [],
|
31
|
-
T::Array[LanguageServer::Protocol::Interface::TextEdit],
|
32
|
-
)
|
33
|
-
end
|
34
|
-
|
35
|
-
sig { returns(T::Boolean) }
|
36
|
-
def correctable?
|
37
|
-
@offense.correctable?
|
38
26
|
end
|
39
27
|
|
40
|
-
sig {
|
41
|
-
def in_range?(range)
|
42
|
-
range.cover?(@offense.line - 1)
|
43
|
-
end
|
44
|
-
|
45
|
-
sig { returns(LanguageServer::Protocol::Interface::CodeAction) }
|
28
|
+
sig { returns(Interface::CodeAction) }
|
46
29
|
def to_lsp_code_action
|
47
|
-
|
30
|
+
Interface::CodeAction.new(
|
48
31
|
title: "Autocorrect #{@offense.cop_name}",
|
49
|
-
kind:
|
50
|
-
edit:
|
32
|
+
kind: Constant::CodeActionKind::QUICK_FIX,
|
33
|
+
edit: Interface::WorkspaceEdit.new(
|
51
34
|
document_changes: [
|
52
|
-
|
53
|
-
text_document:
|
35
|
+
Interface::TextDocumentEdit.new(
|
36
|
+
text_document: Interface::OptionalVersionedTextDocumentIdentifier.new(
|
54
37
|
uri: @uri,
|
55
38
|
version: nil,
|
56
39
|
),
|
57
|
-
edits: @
|
40
|
+
edits: @offense.correctable? ? offense_replacements : [],
|
58
41
|
),
|
59
42
|
],
|
60
43
|
),
|
@@ -62,45 +45,47 @@ module RubyLsp
|
|
62
45
|
)
|
63
46
|
end
|
64
47
|
|
65
|
-
sig { returns(
|
48
|
+
sig { returns(Interface::Diagnostic) }
|
66
49
|
def to_lsp_diagnostic
|
67
50
|
if @offense.correctable?
|
68
51
|
severity = RUBOCOP_TO_LSP_SEVERITY[@offense.severity.name]
|
69
52
|
message = @offense.message
|
70
53
|
else
|
71
|
-
severity =
|
54
|
+
severity = Constant::DiagnosticSeverity::WARNING
|
72
55
|
message = "#{@offense.message}\n\nThis offense is not auto-correctable.\n"
|
73
56
|
end
|
74
|
-
|
57
|
+
|
58
|
+
Interface::Diagnostic.new(
|
75
59
|
message: message,
|
76
60
|
source: "RuboCop",
|
77
61
|
code: @offense.cop_name,
|
78
62
|
severity: severity,
|
79
|
-
range:
|
80
|
-
start:
|
63
|
+
range: Interface::Range.new(
|
64
|
+
start: Interface::Position.new(
|
81
65
|
line: @offense.line - 1,
|
82
66
|
character: @offense.column,
|
83
67
|
),
|
84
|
-
end:
|
68
|
+
end: Interface::Position.new(
|
85
69
|
line: @offense.last_line - 1,
|
86
70
|
character: @offense.last_column,
|
87
71
|
),
|
88
72
|
),
|
73
|
+
data: {
|
74
|
+
correctable: @offense.correctable?,
|
75
|
+
code_action: to_lsp_code_action,
|
76
|
+
},
|
89
77
|
)
|
90
78
|
end
|
91
79
|
|
92
80
|
private
|
93
81
|
|
94
|
-
sig { returns(T::Array[
|
82
|
+
sig { returns(T::Array[Interface::TextEdit]) }
|
95
83
|
def offense_replacements
|
96
84
|
@offense.corrector.as_replacements.map do |range, replacement|
|
97
|
-
|
98
|
-
range:
|
99
|
-
start:
|
100
|
-
end:
|
101
|
-
line: range.last_line - 1,
|
102
|
-
character: range.last_column,
|
103
|
-
),
|
85
|
+
Interface::TextEdit.new(
|
86
|
+
range: Interface::Range.new(
|
87
|
+
start: Interface::Position.new(line: range.line - 1, character: range.column),
|
88
|
+
end: Interface::Position.new(line: range.last_line - 1, character: range.last_column),
|
104
89
|
),
|
105
90
|
new_text: replacement,
|
106
91
|
)
|
@@ -21,7 +21,7 @@ module RubyLsp
|
|
21
21
|
@runner = T.let(RuboCopRunner.new("-a"), RuboCopRunner)
|
22
22
|
end
|
23
23
|
|
24
|
-
sig { params(uri: String, document: Document).returns(
|
24
|
+
sig { params(uri: String, document: Document).returns(String) }
|
25
25
|
def run(uri, document)
|
26
26
|
filename = CGI.unescape(URI.parse(uri).path)
|
27
27
|
|
@@ -16,6 +16,22 @@ end
|
|
16
16
|
module RubyLsp
|
17
17
|
module Requests
|
18
18
|
module Support
|
19
|
+
class InternalRuboCopError < StandardError
|
20
|
+
extend T::Sig
|
21
|
+
|
22
|
+
MESSAGE = <<~EOS
|
23
|
+
An internal error occurred for the %s cop.
|
24
|
+
Updating to a newer version of RuboCop may solve this.
|
25
|
+
For more details, run RuboCop on the command line.
|
26
|
+
EOS
|
27
|
+
|
28
|
+
sig { params(rubocop_error: RuboCop::ErrorWithAnalyzedFileLocation).void }
|
29
|
+
def initialize(rubocop_error)
|
30
|
+
message = format(MESSAGE, rubocop_error.cop.name)
|
31
|
+
super(message)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
19
35
|
# :nodoc:
|
20
36
|
class RuboCopRunner < RuboCop::Runner
|
21
37
|
extend T::Sig
|
@@ -31,10 +47,18 @@ module RubyLsp
|
|
31
47
|
"--force-exclusion",
|
32
48
|
"--format",
|
33
49
|
"RuboCop::Formatter::BaseFormatter", # Suppress any output by using the base formatter
|
34
|
-
]
|
50
|
+
],
|
35
51
|
T::Array[String],
|
36
52
|
)
|
37
53
|
|
54
|
+
begin
|
55
|
+
RuboCop::Options.new.parse(["--raise-cop-error"])
|
56
|
+
DEFAULT_ARGS << "--raise-cop-error"
|
57
|
+
rescue OptionParser::InvalidOption
|
58
|
+
# older versions of RuboCop don't support this flag
|
59
|
+
end
|
60
|
+
DEFAULT_ARGS.freeze
|
61
|
+
|
38
62
|
sig { params(args: String).void }
|
39
63
|
def initialize(*args)
|
40
64
|
@options = T.let({}, T::Hash[Symbol, T.untyped])
|
@@ -63,6 +87,8 @@ module RubyLsp
|
|
63
87
|
raise Formatting::Error, error.message
|
64
88
|
rescue RuboCop::ValidationError => error
|
65
89
|
raise ConfigurationError, error.message
|
90
|
+
rescue RuboCop::ErrorWithAnalyzedFileLocation => error
|
91
|
+
raise InternalRuboCopError, error
|
66
92
|
end
|
67
93
|
|
68
94
|
sig { returns(String) }
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Requests
|
6
|
+
module Support
|
7
|
+
class Sorbet
|
8
|
+
class << self
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
ANNOTATIONS = T.let(
|
12
|
+
{
|
13
|
+
"abstract!" => Annotation.new(arity: 0),
|
14
|
+
"absurd" => Annotation.new(arity: 1, receiver: true),
|
15
|
+
"all" => Annotation.new(arity: (2..), receiver: true),
|
16
|
+
"any" => Annotation.new(arity: (2..), receiver: true),
|
17
|
+
"assert_type!" => Annotation.new(arity: 2, receiver: true),
|
18
|
+
"attached_class" => Annotation.new(arity: 0, receiver: true),
|
19
|
+
"bind" => Annotation.new(arity: 2, receiver: true),
|
20
|
+
"cast" => Annotation.new(arity: 2, receiver: true),
|
21
|
+
"class_of" => Annotation.new(arity: 1, receiver: true),
|
22
|
+
"enums" => Annotation.new(arity: 0),
|
23
|
+
"interface!" => Annotation.new(arity: 0),
|
24
|
+
"let" => Annotation.new(arity: 2, receiver: true),
|
25
|
+
"mixes_in_class_methods" => Annotation.new(arity: 1),
|
26
|
+
"must" => Annotation.new(arity: 1, receiver: true),
|
27
|
+
"must_because" => Annotation.new(arity: 1, receiver: true),
|
28
|
+
"nilable" => Annotation.new(arity: 1, receiver: true),
|
29
|
+
"noreturn" => Annotation.new(arity: 0, receiver: true),
|
30
|
+
"requires_ancestor" => Annotation.new(arity: 0),
|
31
|
+
"reveal_type" => Annotation.new(arity: 1, receiver: true),
|
32
|
+
"sealed!" => Annotation.new(arity: 0),
|
33
|
+
"self_type" => Annotation.new(arity: 0, receiver: true),
|
34
|
+
"sig" => Annotation.new(arity: 0),
|
35
|
+
"type_member" => Annotation.new(arity: (0..1)),
|
36
|
+
"type_template" => Annotation.new(arity: 0),
|
37
|
+
"unsafe" => Annotation.new(arity: 1),
|
38
|
+
"untyped" => Annotation.new(arity: 0, receiver: true),
|
39
|
+
},
|
40
|
+
T::Hash[String, Annotation],
|
41
|
+
)
|
42
|
+
|
43
|
+
sig do
|
44
|
+
params(
|
45
|
+
node: T.any(SyntaxTree::CallNode, SyntaxTree::VCall),
|
46
|
+
).returns(T::Boolean)
|
47
|
+
end
|
48
|
+
def annotation?(node)
|
49
|
+
annotation = annotation(node)
|
50
|
+
|
51
|
+
return false if annotation.nil?
|
52
|
+
|
53
|
+
return false unless annotation.supports_receiver?(receiver_name(node))
|
54
|
+
|
55
|
+
annotation.supports_arity?(node.arity)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
sig { params(node: T.any(SyntaxTree::CallNode, SyntaxTree::VCall)).returns(T.nilable(Annotation)) }
|
61
|
+
def annotation(node)
|
62
|
+
case node
|
63
|
+
when SyntaxTree::VCall
|
64
|
+
ANNOTATIONS[node.value.value]
|
65
|
+
when SyntaxTree::CallNode
|
66
|
+
ANNOTATIONS[node.message.value]
|
67
|
+
else
|
68
|
+
T.absurd(node)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
sig do
|
73
|
+
params(receiver: T.any(SyntaxTree::CallNode, SyntaxTree::VCall)).returns(T.nilable(String))
|
74
|
+
end
|
75
|
+
def receiver_name(receiver)
|
76
|
+
case receiver
|
77
|
+
when SyntaxTree::CallNode
|
78
|
+
node_name(receiver.receiver)
|
79
|
+
when SyntaxTree::VCall
|
80
|
+
nil
|
81
|
+
else
|
82
|
+
T.absurd(receiver)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
sig do
|
87
|
+
params(node: T.nilable(T.any(
|
88
|
+
SyntaxTree::VarRef,
|
89
|
+
SyntaxTree::CallNode,
|
90
|
+
SyntaxTree::VCall,
|
91
|
+
SyntaxTree::Ident,
|
92
|
+
SyntaxTree::Backtick,
|
93
|
+
SyntaxTree::Const,
|
94
|
+
SyntaxTree::Op,
|
95
|
+
Symbol,
|
96
|
+
))).returns(T.nilable(String))
|
97
|
+
end
|
98
|
+
def node_name(node)
|
99
|
+
case node
|
100
|
+
when NilClass
|
101
|
+
nil
|
102
|
+
when SyntaxTree::VarRef
|
103
|
+
node.value.value
|
104
|
+
when SyntaxTree::CallNode
|
105
|
+
node_name(node.receiver)
|
106
|
+
when SyntaxTree::VCall
|
107
|
+
node_name(node.value)
|
108
|
+
when SyntaxTree::Ident, SyntaxTree::Backtick, SyntaxTree::Const, SyntaxTree::Op
|
109
|
+
node.value
|
110
|
+
when Symbol
|
111
|
+
node.to_s
|
112
|
+
else
|
113
|
+
T.absurd(node)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/lib/ruby_lsp/requests.rb
CHANGED
@@ -16,6 +16,7 @@ module RubyLsp
|
|
16
16
|
# - {RubyLsp::Requests::CodeActions}
|
17
17
|
# - {RubyLsp::Requests::DocumentHighlight}
|
18
18
|
# - {RubyLsp::Requests::InlayHints}
|
19
|
+
# - {RubyLsp::Requests::PathCompletion}
|
19
20
|
|
20
21
|
module Requests
|
21
22
|
autoload :BaseRequest, "ruby_lsp/requests/base_request"
|
@@ -31,15 +32,18 @@ module RubyLsp
|
|
31
32
|
autoload :CodeActions, "ruby_lsp/requests/code_actions"
|
32
33
|
autoload :DocumentHighlight, "ruby_lsp/requests/document_highlight"
|
33
34
|
autoload :InlayHints, "ruby_lsp/requests/inlay_hints"
|
35
|
+
autoload :PathCompletion, "ruby_lsp/requests/path_completion"
|
34
36
|
|
35
37
|
# :nodoc:
|
36
38
|
module Support
|
37
39
|
autoload :RuboCopDiagnostic, "ruby_lsp/requests/support/rubocop_diagnostic"
|
38
40
|
autoload :SelectionRange, "ruby_lsp/requests/support/selection_range"
|
39
41
|
autoload :SemanticTokenEncoder, "ruby_lsp/requests/support/semantic_token_encoder"
|
40
|
-
autoload :
|
42
|
+
autoload :Annotation, "ruby_lsp/requests/support/annotation"
|
43
|
+
autoload :Sorbet, "ruby_lsp/requests/support/sorbet"
|
41
44
|
autoload :HighlightTarget, "ruby_lsp/requests/support/highlight_target"
|
42
45
|
autoload :RailsDocumentClient, "ruby_lsp/requests/support/rails_document_client"
|
46
|
+
autoload :PrefixTree, "ruby_lsp/requests/support/prefix_tree"
|
43
47
|
end
|
44
48
|
end
|
45
49
|
end
|