ruby-lsp 0.9.3 → 0.10.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/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +27 -15
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +68 -15
- data/lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb +29 -0
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +153 -0
- data/lib/ruby_indexer/ruby_indexer.rb +2 -0
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +1 -1
- data/lib/ruby_indexer/test/configuration_test.rb +30 -24
- data/lib/ruby_indexer/test/index_test.rb +42 -9
- data/lib/ruby_indexer/test/prefix_tree_test.rb +150 -0
- data/lib/ruby_indexer/test/test_case.rb +1 -1
- data/lib/ruby_lsp/check_docs.rb +2 -1
- data/lib/ruby_lsp/event_emitter.rb +2 -0
- data/lib/ruby_lsp/executor.rb +33 -16
- data/lib/ruby_lsp/extension.rb +13 -1
- data/lib/ruby_lsp/listener.rb +43 -4
- data/lib/ruby_lsp/requests/code_lens.rb +15 -13
- data/lib/ruby_lsp/requests/completion.rb +168 -0
- data/lib/ruby_lsp/requests/definition.rb +43 -32
- data/lib/ruby_lsp/requests/document_highlight.rb +3 -3
- data/lib/ruby_lsp/requests/document_link.rb +3 -3
- data/lib/ruby_lsp/requests/document_symbol.rb +10 -9
- data/lib/ruby_lsp/requests/hover.rb +16 -33
- data/lib/ruby_lsp/requests/inlay_hints.rb +3 -3
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +4 -4
- data/lib/ruby_lsp/requests/support/common.rb +33 -0
- data/lib/ruby_lsp/requests.rb +2 -3
- metadata +9 -7
- data/lib/ruby_lsp/requests/path_completion.rb +0 -65
- data/lib/ruby_lsp/requests/support/prefix_tree.rb +0 -80
@@ -17,14 +17,14 @@ module RubyLsp
|
|
17
17
|
# require "some_gem/file" # <- Request go to definition on this string will take you to the file
|
18
18
|
# Product.new # <- Request go to definition on this class name will take you to its declaration.
|
19
19
|
# ```
|
20
|
-
class Definition <
|
20
|
+
class Definition < ExtensibleListener
|
21
21
|
extend T::Sig
|
22
22
|
extend T::Generic
|
23
23
|
|
24
24
|
ResponseType = type_member { { fixed: T.nilable(T.any(T::Array[Interface::Location], Interface::Location)) } }
|
25
25
|
|
26
26
|
sig { override.returns(ResponseType) }
|
27
|
-
attr_reader :
|
27
|
+
attr_reader :_response
|
28
28
|
|
29
29
|
sig do
|
30
30
|
params(
|
@@ -36,15 +36,37 @@ module RubyLsp
|
|
36
36
|
).void
|
37
37
|
end
|
38
38
|
def initialize(uri, nesting, index, emitter, message_queue)
|
39
|
-
super(emitter, message_queue)
|
40
|
-
|
41
39
|
@uri = uri
|
42
40
|
@nesting = nesting
|
43
41
|
@index = index
|
44
|
-
@
|
42
|
+
@_response = T.let(nil, ResponseType)
|
43
|
+
|
44
|
+
super(emitter, message_queue)
|
45
|
+
|
45
46
|
emitter.register(self, :on_command, :on_const, :on_const_path_ref)
|
46
47
|
end
|
47
48
|
|
49
|
+
sig { override.params(ext: Extension).returns(T.nilable(RubyLsp::Listener[ResponseType])) }
|
50
|
+
def initialize_external_listener(ext)
|
51
|
+
ext.create_definition_listener(@uri, @nesting, @index, @emitter, @message_queue)
|
52
|
+
end
|
53
|
+
|
54
|
+
sig { override.params(other: Listener[ResponseType]).returns(T.self_type) }
|
55
|
+
def merge_response!(other)
|
56
|
+
other_response = other._response
|
57
|
+
|
58
|
+
case @_response
|
59
|
+
when Interface::Location
|
60
|
+
@_response = [@_response, *other_response]
|
61
|
+
when Array
|
62
|
+
@_response.concat(Array(other_response))
|
63
|
+
when nil
|
64
|
+
@_response = other_response
|
65
|
+
end
|
66
|
+
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
48
70
|
sig { params(node: SyntaxTree::ConstPathRef).void }
|
49
71
|
def on_const_path_ref(node)
|
50
72
|
name = full_constant_name(node)
|
@@ -67,14 +89,16 @@ module RubyLsp
|
|
67
89
|
string = argument.parts.first
|
68
90
|
return unless string.is_a?(SyntaxTree::TStringContent)
|
69
91
|
|
70
|
-
required_file = "#{string.value}.rb"
|
71
|
-
|
72
92
|
case message
|
73
93
|
when "require"
|
74
|
-
|
94
|
+
entry = @index.search_require_paths(string.value).find do |indexable_path|
|
95
|
+
indexable_path.require_path == string.value
|
96
|
+
end
|
97
|
+
|
98
|
+
if entry
|
99
|
+
candidate = entry.full_path
|
75
100
|
|
76
|
-
|
77
|
-
@response = Interface::Location.new(
|
101
|
+
@_response = Interface::Location.new(
|
78
102
|
uri: URI::Generic.from_path(path: candidate).to_s,
|
79
103
|
range: Interface::Range.new(
|
80
104
|
start: Interface::Position.new(line: 0, character: 0),
|
@@ -83,19 +107,18 @@ module RubyLsp
|
|
83
107
|
)
|
84
108
|
end
|
85
109
|
when "require_relative"
|
110
|
+
required_file = "#{string.value}.rb"
|
86
111
|
path = @uri.to_standardized_path
|
87
112
|
current_folder = path ? Pathname.new(CGI.unescape(path)).dirname : Dir.pwd
|
88
113
|
candidate = File.expand_path(File.join(current_folder, required_file))
|
89
114
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
)
|
98
|
-
end
|
115
|
+
@_response = Interface::Location.new(
|
116
|
+
uri: URI::Generic.from_path(path: candidate).to_s,
|
117
|
+
range: Interface::Range.new(
|
118
|
+
start: Interface::Position.new(line: 0, character: 0),
|
119
|
+
end: Interface::Position.new(line: 0, character: 0),
|
120
|
+
),
|
121
|
+
)
|
99
122
|
end
|
100
123
|
end
|
101
124
|
|
@@ -112,7 +135,7 @@ module RubyLsp
|
|
112
135
|
nil
|
113
136
|
end
|
114
137
|
|
115
|
-
@
|
138
|
+
@_response = entries.filter_map do |entry|
|
116
139
|
location = entry.location
|
117
140
|
# If the project has Sorbet, then we only want to handle go to definition for constants defined in gems, as an
|
118
141
|
# additional behavior on top of jumping to RBIs. Sorbet can already handle go to definition for all constants
|
@@ -133,18 +156,6 @@ module RubyLsp
|
|
133
156
|
)
|
134
157
|
end
|
135
158
|
end
|
136
|
-
|
137
|
-
sig { params(file: String).returns(T.nilable(String)) }
|
138
|
-
def find_file_in_load_path(file)
|
139
|
-
return unless file.include?("/")
|
140
|
-
|
141
|
-
$LOAD_PATH.each do |p|
|
142
|
-
found = Dir.glob("**/#{file}", base: p).first
|
143
|
-
return "#{p}/#{found}" if found
|
144
|
-
end
|
145
|
-
|
146
|
-
nil
|
147
|
-
end
|
148
159
|
end
|
149
160
|
end
|
150
161
|
end
|
@@ -28,7 +28,7 @@ module RubyLsp
|
|
28
28
|
ResponseType = type_member { { fixed: T::Array[Interface::DocumentHighlight] } }
|
29
29
|
|
30
30
|
sig { override.returns(ResponseType) }
|
31
|
-
attr_reader :
|
31
|
+
attr_reader :_response
|
32
32
|
|
33
33
|
sig do
|
34
34
|
params(
|
@@ -41,7 +41,7 @@ module RubyLsp
|
|
41
41
|
def initialize(target, parent, emitter, message_queue)
|
42
42
|
super(emitter, message_queue)
|
43
43
|
|
44
|
-
@
|
44
|
+
@_response = T.let([], T::Array[Interface::DocumentHighlight])
|
45
45
|
|
46
46
|
return unless target && parent
|
47
47
|
|
@@ -83,7 +83,7 @@ module RubyLsp
|
|
83
83
|
sig { params(match: Support::HighlightTarget::HighlightMatch).void }
|
84
84
|
def add_highlight(match)
|
85
85
|
range = range_from_syntax_tree_node(match.node)
|
86
|
-
@
|
86
|
+
@_response << Interface::DocumentHighlight.new(range: range, kind: match.type)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -73,7 +73,7 @@ module RubyLsp
|
|
73
73
|
end
|
74
74
|
|
75
75
|
sig { override.returns(ResponseType) }
|
76
|
-
attr_reader :
|
76
|
+
attr_reader :_response
|
77
77
|
|
78
78
|
sig { params(uri: URI::Generic, emitter: EventEmitter, message_queue: Thread::Queue).void }
|
79
79
|
def initialize(uri, emitter, message_queue)
|
@@ -84,7 +84,7 @@ module RubyLsp
|
|
84
84
|
path = uri.to_standardized_path
|
85
85
|
version_match = path ? /(?<=%40)[\d.]+(?=\.rbi$)/.match(path) : nil
|
86
86
|
@gem_version = T.let(version_match && version_match[0], T.nilable(String))
|
87
|
-
@
|
87
|
+
@_response = T.let([], T::Array[Interface::DocumentLink])
|
88
88
|
|
89
89
|
emitter.register(self, :on_comment)
|
90
90
|
end
|
@@ -99,7 +99,7 @@ module RubyLsp
|
|
99
99
|
file_path = self.class.gem_paths.dig(uri.gem_name, gem_version, CGI.unescape(uri.path))
|
100
100
|
return if file_path.nil?
|
101
101
|
|
102
|
-
@
|
102
|
+
@_response << Interface::DocumentLink.new(
|
103
103
|
range: range_from_syntax_tree_node(node),
|
104
104
|
target: "file://#{file_path}##{uri.line_number}",
|
105
105
|
tooltip: "Jump to #{file_path}##{uri.line_number}",
|
@@ -26,7 +26,7 @@ module RubyLsp
|
|
26
26
|
# end
|
27
27
|
# end
|
28
28
|
# ```
|
29
|
-
class DocumentSymbol <
|
29
|
+
class DocumentSymbol < ExtensibleListener
|
30
30
|
extend T::Sig
|
31
31
|
extend T::Generic
|
32
32
|
|
@@ -47,22 +47,18 @@ module RubyLsp
|
|
47
47
|
end
|
48
48
|
|
49
49
|
sig { override.returns(T::Array[Interface::DocumentSymbol]) }
|
50
|
-
attr_reader :
|
50
|
+
attr_reader :_response
|
51
51
|
|
52
52
|
sig { params(emitter: EventEmitter, message_queue: Thread::Queue).void }
|
53
53
|
def initialize(emitter, message_queue)
|
54
|
-
super
|
55
|
-
|
56
54
|
@root = T.let(SymbolHierarchyRoot.new, SymbolHierarchyRoot)
|
57
|
-
@
|
55
|
+
@_response = T.let(@root.children, T::Array[Interface::DocumentSymbol])
|
58
56
|
@stack = T.let(
|
59
57
|
[@root],
|
60
58
|
T::Array[T.any(SymbolHierarchyRoot, Interface::DocumentSymbol)],
|
61
59
|
)
|
62
60
|
|
63
|
-
|
64
|
-
Extension.extensions.filter_map { |ext| ext.create_document_symbol_listener(emitter, message_queue) },
|
65
|
-
)
|
61
|
+
super
|
66
62
|
|
67
63
|
emitter.register(
|
68
64
|
self,
|
@@ -79,10 +75,15 @@ module RubyLsp
|
|
79
75
|
)
|
80
76
|
end
|
81
77
|
|
78
|
+
sig { override.params(extension: RubyLsp::Extension).returns(T.nilable(Listener[ResponseType])) }
|
79
|
+
def initialize_external_listener(extension)
|
80
|
+
extension.create_document_symbol_listener(@emitter, @message_queue)
|
81
|
+
end
|
82
|
+
|
82
83
|
# Merges responses from other listeners
|
83
84
|
sig { override.params(other: Listener[ResponseType]).returns(T.self_type) }
|
84
85
|
def merge_response!(other)
|
85
|
-
@
|
86
|
+
@_response.concat(other.response)
|
86
87
|
self
|
87
88
|
end
|
88
89
|
|
@@ -13,7 +13,7 @@ module RubyLsp
|
|
13
13
|
# ```ruby
|
14
14
|
# String # -> Hovering over the class reference will show all declaration locations and the documentation
|
15
15
|
# ```
|
16
|
-
class Hover <
|
16
|
+
class Hover < ExtensibleListener
|
17
17
|
extend T::Sig
|
18
18
|
extend T::Generic
|
19
19
|
|
@@ -30,7 +30,7 @@ module RubyLsp
|
|
30
30
|
)
|
31
31
|
|
32
32
|
sig { override.returns(ResponseType) }
|
33
|
-
attr_reader :
|
33
|
+
attr_reader :_response
|
34
34
|
|
35
35
|
sig do
|
36
36
|
params(
|
@@ -41,27 +41,29 @@ module RubyLsp
|
|
41
41
|
).void
|
42
42
|
end
|
43
43
|
def initialize(index, nesting, emitter, message_queue)
|
44
|
-
super(emitter, message_queue)
|
45
|
-
|
46
44
|
@nesting = nesting
|
47
45
|
@index = index
|
48
|
-
@
|
49
|
-
|
50
|
-
)
|
51
|
-
@response = T.let(nil, ResponseType)
|
46
|
+
@_response = T.let(nil, ResponseType)
|
47
|
+
|
48
|
+
super(emitter, message_queue)
|
52
49
|
emitter.register(self, :on_const_path_ref, :on_const)
|
53
50
|
end
|
54
51
|
|
52
|
+
sig { override.params(extension: RubyLsp::Extension).returns(T.nilable(Listener[ResponseType])) }
|
53
|
+
def initialize_external_listener(extension)
|
54
|
+
extension.create_hover_listener(@emitter, @message_queue)
|
55
|
+
end
|
56
|
+
|
55
57
|
# Merges responses from other hover listeners
|
56
58
|
sig { override.params(other: Listener[ResponseType]).returns(T.self_type) }
|
57
59
|
def merge_response!(other)
|
58
60
|
other_response = other.response
|
59
61
|
return self unless other_response
|
60
62
|
|
61
|
-
if @
|
62
|
-
@
|
63
|
+
if @_response.nil?
|
64
|
+
@_response = other.response
|
63
65
|
else
|
64
|
-
@
|
66
|
+
@_response.contents.value << "\n\n" << other_response.contents.value
|
65
67
|
end
|
66
68
|
|
67
69
|
self
|
@@ -89,29 +91,10 @@ module RubyLsp
|
|
89
91
|
entries = @index.resolve(name, @nesting)
|
90
92
|
return unless entries
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
entries.each do |entry|
|
96
|
-
loc = entry.location
|
97
|
-
|
98
|
-
# We always handle locations as zero based. However, for file links in Markdown we need them to be one based,
|
99
|
-
# which is why instead of the usual subtraction of 1 to line numbers, we are actually adding 1 to columns. The
|
100
|
-
# format for VS Code file URIs is `file:///path/to/file.rb#Lstart_line,start_column-end_line,end_column`
|
101
|
-
uri = URI::Generic.from_path(
|
102
|
-
path: entry.file_path,
|
103
|
-
fragment: "L#{loc.start_line},#{loc.start_column + 1}-#{loc.end_line},#{loc.end_column + 1}",
|
104
|
-
)
|
105
|
-
|
106
|
-
definitions << "[#{entry.file_name}](#{uri})"
|
107
|
-
content << "\n\n#{entry.comments.join("\n")}" unless entry.comments.empty?
|
108
|
-
end
|
109
|
-
|
110
|
-
contents = Interface::MarkupContent.new(
|
111
|
-
kind: "markdown",
|
112
|
-
value: "#{title}\n\n**Definitions**: #{definitions.join(" | ")}\n\n#{content}",
|
94
|
+
@_response = Interface::Hover.new(
|
95
|
+
range: range_from_syntax_tree_node(node),
|
96
|
+
contents: markdown_from_index_entries(name, entries),
|
113
97
|
)
|
114
|
-
@response = Interface::Hover.new(range: range_from_syntax_tree_node(node), contents: contents)
|
115
98
|
end
|
116
99
|
end
|
117
100
|
end
|
@@ -27,13 +27,13 @@ module RubyLsp
|
|
27
27
|
RESCUE_STRING_LENGTH = T.let("rescue".length, Integer)
|
28
28
|
|
29
29
|
sig { override.returns(ResponseType) }
|
30
|
-
attr_reader :
|
30
|
+
attr_reader :_response
|
31
31
|
|
32
32
|
sig { params(range: T::Range[Integer], emitter: EventEmitter, message_queue: Thread::Queue).void }
|
33
33
|
def initialize(range, emitter, message_queue)
|
34
34
|
super(emitter, message_queue)
|
35
35
|
|
36
|
-
@
|
36
|
+
@_response = T.let([], ResponseType)
|
37
37
|
@range = range
|
38
38
|
|
39
39
|
emitter.register(self, :on_rescue)
|
@@ -47,7 +47,7 @@ module RubyLsp
|
|
47
47
|
loc = node.location
|
48
48
|
return unless visible?(node, @range)
|
49
49
|
|
50
|
-
@
|
50
|
+
@_response << Interface::InlayHint.new(
|
51
51
|
position: { line: loc.start_line - 1, character: loc.start_column + RESCUE_STRING_LENGTH },
|
52
52
|
label: "StandardError",
|
53
53
|
padding_left: true,
|
@@ -105,7 +105,7 @@ module RubyLsp
|
|
105
105
|
end
|
106
106
|
|
107
107
|
sig { override.returns(ResponseType) }
|
108
|
-
attr_reader :
|
108
|
+
attr_reader :_response
|
109
109
|
|
110
110
|
sig do
|
111
111
|
params(
|
@@ -117,7 +117,7 @@ module RubyLsp
|
|
117
117
|
def initialize(emitter, message_queue, range: nil)
|
118
118
|
super(emitter, message_queue)
|
119
119
|
|
120
|
-
@
|
120
|
+
@_response = T.let([], ResponseType)
|
121
121
|
@range = range
|
122
122
|
@special_methods = T.let(nil, T.nilable(T::Array[String]))
|
123
123
|
|
@@ -174,7 +174,7 @@ module RubyLsp
|
|
174
174
|
# When finding a module or class definition, we will have already pushed a token related to this constant. We
|
175
175
|
# need to look at the previous two tokens and if they match this locatione exactly, avoid pushing another token
|
176
176
|
# on top of the previous one
|
177
|
-
return if @
|
177
|
+
return if @_response.last(2).any? { |token| token.location == node.location }
|
178
178
|
|
179
179
|
add_token(node.location, :namespace)
|
180
180
|
end
|
@@ -327,7 +327,7 @@ module RubyLsp
|
|
327
327
|
def add_token(location, type, modifiers = [])
|
328
328
|
length = location.end_char - location.start_char
|
329
329
|
modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
|
330
|
-
@
|
330
|
+
@_response.push(
|
331
331
|
SemanticToken.new(
|
332
332
|
location: location,
|
333
333
|
length: length,
|
@@ -74,6 +74,39 @@ module RubyLsp
|
|
74
74
|
data: data,
|
75
75
|
)
|
76
76
|
end
|
77
|
+
|
78
|
+
sig { params(title: String, entries: T::Array[RubyIndexer::Index::Entry]).returns(Interface::MarkupContent) }
|
79
|
+
def markdown_from_index_entries(title, entries)
|
80
|
+
markdown_title = "```ruby\n#{title}\n```"
|
81
|
+
definitions = []
|
82
|
+
content = +""
|
83
|
+
entries.each do |entry|
|
84
|
+
loc = entry.location
|
85
|
+
|
86
|
+
# We always handle locations as zero based. However, for file links in Markdown we need them to be one
|
87
|
+
# based, which is why instead of the usual subtraction of 1 to line numbers, we are actually adding 1 to
|
88
|
+
# columns. The format for VS Code file URIs is
|
89
|
+
# `file:///path/to/file.rb#Lstart_line,start_column-end_line,end_column`
|
90
|
+
uri = URI::Generic.from_path(
|
91
|
+
path: entry.file_path,
|
92
|
+
fragment: "L#{loc.start_line},#{loc.start_column + 1}-#{loc.end_line},#{loc.end_column + 1}",
|
93
|
+
)
|
94
|
+
|
95
|
+
definitions << "[#{entry.file_name}](#{uri})"
|
96
|
+
content << "\n\n#{entry.comments.join("\n")}" unless entry.comments.empty?
|
97
|
+
end
|
98
|
+
|
99
|
+
Interface::MarkupContent.new(
|
100
|
+
kind: "markdown",
|
101
|
+
value: <<~MARKDOWN.chomp,
|
102
|
+
#{markdown_title}
|
103
|
+
|
104
|
+
**Definitions**: #{definitions.join(" | ")}
|
105
|
+
|
106
|
+
#{content}
|
107
|
+
MARKDOWN
|
108
|
+
)
|
109
|
+
end
|
77
110
|
end
|
78
111
|
end
|
79
112
|
end
|
data/lib/ruby_lsp/requests.rb
CHANGED
@@ -17,7 +17,7 @@ module RubyLsp
|
|
17
17
|
# - [CodeActionResolve](rdoc-ref:RubyLsp::Requests::CodeActionResolve)
|
18
18
|
# - [DocumentHighlight](rdoc-ref:RubyLsp::Requests::DocumentHighlight)
|
19
19
|
# - [InlayHint](rdoc-ref:RubyLsp::Requests::InlayHints)
|
20
|
-
# - [
|
20
|
+
# - [Completion](rdoc-ref:RubyLsp::Requests::Completion)
|
21
21
|
# - [CodeLens](rdoc-ref:RubyLsp::Requests::CodeLens)
|
22
22
|
# - [Definition](rdoc-ref:RubyLsp::Requests::Definition)
|
23
23
|
# - [ShowSyntaxTree](rdoc-ref:RubyLsp::Requests::ShowSyntaxTree)
|
@@ -38,7 +38,7 @@ module RubyLsp
|
|
38
38
|
autoload :CodeActionResolve, "ruby_lsp/requests/code_action_resolve"
|
39
39
|
autoload :DocumentHighlight, "ruby_lsp/requests/document_highlight"
|
40
40
|
autoload :InlayHints, "ruby_lsp/requests/inlay_hints"
|
41
|
-
autoload :
|
41
|
+
autoload :Completion, "ruby_lsp/requests/completion"
|
42
42
|
autoload :CodeLens, "ruby_lsp/requests/code_lens"
|
43
43
|
autoload :Definition, "ruby_lsp/requests/definition"
|
44
44
|
autoload :ShowSyntaxTree, "ruby_lsp/requests/show_syntax_tree"
|
@@ -53,7 +53,6 @@ module RubyLsp
|
|
53
53
|
autoload :Sorbet, "ruby_lsp/requests/support/sorbet"
|
54
54
|
autoload :HighlightTarget, "ruby_lsp/requests/support/highlight_target"
|
55
55
|
autoload :RailsDocumentClient, "ruby_lsp/requests/support/rails_document_client"
|
56
|
-
autoload :PrefixTree, "ruby_lsp/requests/support/prefix_tree"
|
57
56
|
autoload :Common, "ruby_lsp/requests/support/common"
|
58
57
|
autoload :FormatterRunner, "ruby_lsp/requests/support/formatter_runner"
|
59
58
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
version: '0.9'
|
68
68
|
- - "<"
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version: '0.
|
70
|
+
version: '0.11'
|
71
71
|
type: :runtime
|
72
72
|
prerelease: false
|
73
73
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -77,7 +77,7 @@ dependencies:
|
|
77
77
|
version: '0.9'
|
78
78
|
- - "<"
|
79
79
|
- !ruby/object:Gem::Version
|
80
|
-
version: '0.
|
80
|
+
version: '0.11'
|
81
81
|
description: An opinionated language server for Ruby
|
82
82
|
email:
|
83
83
|
- ruby@shopify.com
|
@@ -97,12 +97,15 @@ files:
|
|
97
97
|
- lib/ruby-lsp.rb
|
98
98
|
- lib/ruby_indexer/lib/ruby_indexer/configuration.rb
|
99
99
|
- lib/ruby_indexer/lib/ruby_indexer/index.rb
|
100
|
+
- lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb
|
101
|
+
- lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb
|
100
102
|
- lib/ruby_indexer/lib/ruby_indexer/visitor.rb
|
101
103
|
- lib/ruby_indexer/ruby_indexer.rb
|
102
104
|
- lib/ruby_indexer/test/classes_and_modules_test.rb
|
103
105
|
- lib/ruby_indexer/test/configuration_test.rb
|
104
106
|
- lib/ruby_indexer/test/constant_test.rb
|
105
107
|
- lib/ruby_indexer/test/index_test.rb
|
108
|
+
- lib/ruby_indexer/test/prefix_tree_test.rb
|
106
109
|
- lib/ruby_indexer/test/test_case.rb
|
107
110
|
- lib/ruby_lsp/check_docs.rb
|
108
111
|
- lib/ruby_lsp/document.rb
|
@@ -116,6 +119,7 @@ files:
|
|
116
119
|
- lib/ruby_lsp/requests/code_action_resolve.rb
|
117
120
|
- lib/ruby_lsp/requests/code_actions.rb
|
118
121
|
- lib/ruby_lsp/requests/code_lens.rb
|
122
|
+
- lib/ruby_lsp/requests/completion.rb
|
119
123
|
- lib/ruby_lsp/requests/definition.rb
|
120
124
|
- lib/ruby_lsp/requests/diagnostics.rb
|
121
125
|
- lib/ruby_lsp/requests/document_highlight.rb
|
@@ -126,7 +130,6 @@ files:
|
|
126
130
|
- lib/ruby_lsp/requests/hover.rb
|
127
131
|
- lib/ruby_lsp/requests/inlay_hints.rb
|
128
132
|
- lib/ruby_lsp/requests/on_type_formatting.rb
|
129
|
-
- lib/ruby_lsp/requests/path_completion.rb
|
130
133
|
- lib/ruby_lsp/requests/selection_ranges.rb
|
131
134
|
- lib/ruby_lsp/requests/semantic_highlighting.rb
|
132
135
|
- lib/ruby_lsp/requests/show_syntax_tree.rb
|
@@ -135,7 +138,6 @@ files:
|
|
135
138
|
- lib/ruby_lsp/requests/support/dependency_detector.rb
|
136
139
|
- lib/ruby_lsp/requests/support/formatter_runner.rb
|
137
140
|
- lib/ruby_lsp/requests/support/highlight_target.rb
|
138
|
-
- lib/ruby_lsp/requests/support/prefix_tree.rb
|
139
141
|
- lib/ruby_lsp/requests/support/rubocop_diagnostic.rb
|
140
142
|
- lib/ruby_lsp/requests/support/rubocop_diagnostics_runner.rb
|
141
143
|
- lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb
|
@@ -170,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
172
|
- !ruby/object:Gem::Version
|
171
173
|
version: '0'
|
172
174
|
requirements: []
|
173
|
-
rubygems_version: 3.4.
|
175
|
+
rubygems_version: 3.4.19
|
174
176
|
signing_key:
|
175
177
|
specification_version: 4
|
176
178
|
summary: An opinionated language server for Ruby
|
@@ -1,65 +0,0 @@
|
|
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 < Listener
|
17
|
-
extend T::Sig
|
18
|
-
extend T::Generic
|
19
|
-
|
20
|
-
ResponseType = type_member { { fixed: T::Array[Interface::CompletionItem] } }
|
21
|
-
|
22
|
-
sig { override.returns(ResponseType) }
|
23
|
-
attr_reader :response
|
24
|
-
|
25
|
-
sig { params(emitter: EventEmitter, message_queue: Thread::Queue).void }
|
26
|
-
def initialize(emitter, message_queue)
|
27
|
-
super
|
28
|
-
@response = T.let([], ResponseType)
|
29
|
-
@tree = T.let(Support::PrefixTree.new(collect_load_path_files), Support::PrefixTree)
|
30
|
-
|
31
|
-
emitter.register(self, :on_tstring_content)
|
32
|
-
end
|
33
|
-
|
34
|
-
sig { params(node: SyntaxTree::TStringContent).void }
|
35
|
-
def on_tstring_content(node)
|
36
|
-
@tree.search(node.value).sort.each do |path|
|
37
|
-
@response << build_completion(path, node)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
sig { returns(T::Array[String]) }
|
44
|
-
def collect_load_path_files
|
45
|
-
$LOAD_PATH.flat_map do |p|
|
46
|
-
Dir.glob("**/*.rb", base: p)
|
47
|
-
end.map! do |result|
|
48
|
-
result.delete_suffix!(".rb")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
sig { params(label: String, node: SyntaxTree::TStringContent).returns(Interface::CompletionItem) }
|
53
|
-
def build_completion(label, node)
|
54
|
-
Interface::CompletionItem.new(
|
55
|
-
label: label,
|
56
|
-
text_edit: Interface::TextEdit.new(
|
57
|
-
range: range_from_syntax_tree_node(node),
|
58
|
-
new_text: label,
|
59
|
-
),
|
60
|
-
kind: Constant::CompletionItemKind::REFERENCE,
|
61
|
-
)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,80 +0,0 @@
|
|
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
|