ruby-lsp 0.17.4 → 0.17.13
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 +11 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp +26 -1
- data/exe/ruby-lsp-check +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +74 -43
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +26 -0
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +147 -29
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +383 -79
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +195 -61
- data/lib/ruby_indexer/ruby_indexer.rb +1 -8
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +71 -3
- data/lib/ruby_indexer/test/configuration_test.rb +1 -1
- data/lib/ruby_indexer/test/constant_test.rb +17 -17
- data/lib/ruby_indexer/test/enhancements_test.rb +197 -0
- data/lib/ruby_indexer/test/index_test.rb +367 -17
- data/lib/ruby_indexer/test/method_test.rb +58 -25
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +297 -0
- data/lib/ruby_indexer/test/test_case.rb +1 -5
- data/lib/ruby_lsp/addon.rb +22 -5
- data/lib/ruby_lsp/base_server.rb +8 -3
- data/lib/ruby_lsp/document.rb +27 -46
- data/lib/ruby_lsp/erb_document.rb +125 -0
- data/lib/ruby_lsp/global_state.rb +47 -19
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/completion.rb +161 -57
- data/lib/ruby_lsp/listeners/definition.rb +91 -27
- data/lib/ruby_lsp/listeners/document_highlight.rb +5 -1
- data/lib/ruby_lsp/listeners/hover.rb +61 -19
- data/lib/ruby_lsp/listeners/signature_help.rb +13 -6
- data/lib/ruby_lsp/node_context.rb +65 -5
- data/lib/ruby_lsp/requests/code_action_resolve.rb +107 -9
- data/lib/ruby_lsp/requests/code_actions.rb +11 -2
- data/lib/ruby_lsp/requests/completion.rb +4 -4
- data/lib/ruby_lsp/requests/completion_resolve.rb +14 -9
- data/lib/ruby_lsp/requests/definition.rb +18 -8
- data/lib/ruby_lsp/requests/diagnostics.rb +6 -5
- data/lib/ruby_lsp/requests/document_symbol.rb +2 -7
- data/lib/ruby_lsp/requests/folding_ranges.rb +6 -2
- data/lib/ruby_lsp/requests/formatting.rb +15 -0
- data/lib/ruby_lsp/requests/hover.rb +5 -5
- data/lib/ruby_lsp/requests/on_type_formatting.rb +6 -4
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +3 -2
- data/lib/ruby_lsp/requests/signature_help.rb +3 -3
- data/lib/ruby_lsp/requests/support/common.rb +11 -2
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +2 -6
- data/lib/ruby_lsp/ruby_document.rb +74 -0
- data/lib/ruby_lsp/server.rb +129 -54
- data/lib/ruby_lsp/store.rb +33 -9
- data/lib/ruby_lsp/test_helper.rb +3 -1
- data/lib/ruby_lsp/type_inferrer.rb +61 -25
- data/lib/ruby_lsp/utils.rb +13 -0
- metadata +9 -8
- data/exe/ruby-lsp-doctor +0 -23
@@ -34,14 +34,9 @@ module RubyLsp
|
|
34
34
|
class << self
|
35
35
|
extend T::Sig
|
36
36
|
|
37
|
-
sig { returns(Interface::
|
37
|
+
sig { returns(Interface::DocumentSymbolOptions) }
|
38
38
|
def provider
|
39
|
-
Interface::
|
40
|
-
hierarchical_document_symbol_support: true,
|
41
|
-
symbol_kind: {
|
42
|
-
value_set: (Constant::SymbolKind::FILE..Constant::SymbolKind::TYPE_PARAMETER).to_a,
|
43
|
-
},
|
44
|
-
)
|
39
|
+
Interface::DocumentSymbolOptions.new
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
@@ -23,9 +23,13 @@ module RubyLsp
|
|
23
23
|
class << self
|
24
24
|
extend T::Sig
|
25
25
|
|
26
|
-
sig { returns(Interface::
|
26
|
+
sig { returns(Interface::FoldingRangeRegistrationOptions) }
|
27
27
|
def provider
|
28
|
-
Interface::
|
28
|
+
Interface::FoldingRangeRegistrationOptions.new(
|
29
|
+
document_selector: [
|
30
|
+
Interface::DocumentFilter.new(language: "ruby"),
|
31
|
+
],
|
32
|
+
)
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
@@ -27,6 +27,19 @@ module RubyLsp
|
|
27
27
|
|
28
28
|
class Error < StandardError; end
|
29
29
|
|
30
|
+
class << self
|
31
|
+
extend T::Sig
|
32
|
+
|
33
|
+
sig { returns(Interface::DocumentFormattingRegistrationOptions) }
|
34
|
+
def provider
|
35
|
+
Interface::DocumentFormattingRegistrationOptions.new(
|
36
|
+
document_selector: [
|
37
|
+
Interface::DocumentFilter.new(language: "ruby"),
|
38
|
+
],
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
30
43
|
sig { params(global_state: GlobalState, document: Document).void }
|
31
44
|
def initialize(global_state, document)
|
32
45
|
super()
|
@@ -40,6 +53,8 @@ module RubyLsp
|
|
40
53
|
return unless @active_formatter
|
41
54
|
return if @document.syntax_error?
|
42
55
|
|
56
|
+
# We don't format erb documents yet
|
57
|
+
|
43
58
|
formatted_text = @active_formatter.run_formatting(@uri, @document)
|
44
59
|
return unless formatted_text
|
45
60
|
|
@@ -22,9 +22,9 @@ module RubyLsp
|
|
22
22
|
class << self
|
23
23
|
extend T::Sig
|
24
24
|
|
25
|
-
sig { returns(Interface::
|
25
|
+
sig { returns(Interface::HoverOptions) }
|
26
26
|
def provider
|
27
|
-
Interface::
|
27
|
+
Interface::HoverOptions.new
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -36,10 +36,10 @@ module RubyLsp
|
|
36
36
|
global_state: GlobalState,
|
37
37
|
position: T::Hash[Symbol, T.untyped],
|
38
38
|
dispatcher: Prism::Dispatcher,
|
39
|
-
|
39
|
+
sorbet_level: RubyDocument::SorbetLevel,
|
40
40
|
).void
|
41
41
|
end
|
42
|
-
def initialize(document, global_state, position, dispatcher,
|
42
|
+
def initialize(document, global_state, position, dispatcher, sorbet_level)
|
43
43
|
super()
|
44
44
|
node_context = document.locate_node(position, node_types: Listeners::Hover::ALLOWED_TARGETS)
|
45
45
|
target = node_context.node
|
@@ -65,7 +65,7 @@ module RubyLsp
|
|
65
65
|
@target = T.let(target, T.nilable(Prism::Node))
|
66
66
|
uri = document.uri
|
67
67
|
@response_builder = T.let(ResponseBuilders::Hover.new, ResponseBuilders::Hover)
|
68
|
-
Listeners::Hover.new(@response_builder, global_state, uri, node_context, dispatcher,
|
68
|
+
Listeners::Hover.new(@response_builder, global_state, uri, node_context, dispatcher, sorbet_level)
|
69
69
|
Addon.addons.each do |addon|
|
70
70
|
addon.create_hover_listener(@response_builder, node_context, dispatcher)
|
71
71
|
end
|
@@ -21,9 +21,10 @@ module RubyLsp
|
|
21
21
|
class << self
|
22
22
|
extend T::Sig
|
23
23
|
|
24
|
-
sig { returns(Interface::
|
24
|
+
sig { returns(Interface::DocumentOnTypeFormattingRegistrationOptions) }
|
25
25
|
def provider
|
26
|
-
Interface::
|
26
|
+
Interface::DocumentOnTypeFormattingRegistrationOptions.new(
|
27
|
+
document_selector: [Interface::DocumentFilter.new(language: "ruby")],
|
27
28
|
first_trigger_character: "{",
|
28
29
|
more_trigger_character: ["\n", "|", "d"],
|
29
30
|
)
|
@@ -32,8 +33,9 @@ module RubyLsp
|
|
32
33
|
|
33
34
|
END_REGEXES = T.let(
|
34
35
|
[
|
35
|
-
/\b(if|unless|for|while|
|
36
|
-
|
36
|
+
/\b(if|unless|for|while|until)\b($|\s|\()/,
|
37
|
+
/\b(class|module|def|case)\b($|\s)/,
|
38
|
+
/.*\s\bdo\b($|\s)/,
|
37
39
|
],
|
38
40
|
T::Array[Regexp],
|
39
41
|
)
|
@@ -34,7 +34,7 @@ module RubyLsp
|
|
34
34
|
sig { override.returns(T.all(T::Array[Support::SelectionRange], Object)) }
|
35
35
|
def perform
|
36
36
|
# [node, parent]
|
37
|
-
queue = [[@document.
|
37
|
+
queue = [[@document.parse_result.value, nil]]
|
38
38
|
|
39
39
|
until queue.empty?
|
40
40
|
node, parent = queue.shift
|
@@ -25,6 +25,7 @@ module RubyLsp
|
|
25
25
|
super()
|
26
26
|
@document = document
|
27
27
|
@range = range
|
28
|
+
@tree = T.let(document.parse_result.value, Prism::ProgramNode)
|
28
29
|
end
|
29
30
|
|
30
31
|
sig { override.returns(String) }
|
@@ -32,7 +33,7 @@ module RubyLsp
|
|
32
33
|
return ast_for_range if @range
|
33
34
|
|
34
35
|
output_string = +""
|
35
|
-
PP.pp(@
|
36
|
+
PP.pp(@tree, output_string)
|
36
37
|
output_string
|
37
38
|
end
|
38
39
|
|
@@ -46,7 +47,7 @@ module RubyLsp
|
|
46
47
|
start_char = scanner.find_char_position(range[:start])
|
47
48
|
end_char = scanner.find_char_position(range[:end])
|
48
49
|
|
49
|
-
queue = @
|
50
|
+
queue = @tree.statements.body.dup
|
50
51
|
found_nodes = []
|
51
52
|
|
52
53
|
until queue.empty?
|
@@ -46,10 +46,10 @@ module RubyLsp
|
|
46
46
|
position: T::Hash[Symbol, T.untyped],
|
47
47
|
context: T.nilable(T::Hash[Symbol, T.untyped]),
|
48
48
|
dispatcher: Prism::Dispatcher,
|
49
|
-
|
49
|
+
sorbet_level: RubyDocument::SorbetLevel,
|
50
50
|
).void
|
51
51
|
end
|
52
|
-
def initialize(document, global_state, position, context, dispatcher,
|
52
|
+
def initialize(document, global_state, position, context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
|
53
53
|
super()
|
54
54
|
node_context = document.locate_node(
|
55
55
|
{ line: position[:line], character: position[:character] },
|
@@ -61,7 +61,7 @@ module RubyLsp
|
|
61
61
|
@target = T.let(target, T.nilable(Prism::Node))
|
62
62
|
@dispatcher = dispatcher
|
63
63
|
@response_builder = T.let(ResponseBuilders::SignatureHelp.new, ResponseBuilders::SignatureHelp)
|
64
|
-
Listeners::SignatureHelp.new(@response_builder, global_state, node_context, dispatcher,
|
64
|
+
Listeners::SignatureHelp.new(@response_builder, global_state, node_context, dispatcher, sorbet_level)
|
65
65
|
end
|
66
66
|
|
67
67
|
sig { override.returns(T.nilable(Interface::SignatureHelp)) }
|
@@ -130,13 +130,17 @@ module RubyLsp
|
|
130
130
|
title: String,
|
131
131
|
entries: T.any(T::Array[RubyIndexer::Entry], RubyIndexer::Entry),
|
132
132
|
max_entries: T.nilable(Integer),
|
133
|
+
extra_links: T.nilable(String),
|
133
134
|
).returns(String)
|
134
135
|
end
|
135
|
-
def markdown_from_index_entries(title, entries, max_entries = nil)
|
136
|
+
def markdown_from_index_entries(title, entries, max_entries = nil, extra_links: nil)
|
136
137
|
categorized_markdown = categorized_markdown_from_index_entries(title, entries, max_entries)
|
137
138
|
|
139
|
+
markdown = +(categorized_markdown[:title] || "")
|
140
|
+
markdown << "\n\n#{extra_links}" if extra_links
|
141
|
+
|
138
142
|
<<~MARKDOWN.chomp
|
139
|
-
#{
|
143
|
+
#{markdown}
|
140
144
|
|
141
145
|
#{categorized_markdown[:links]}
|
142
146
|
|
@@ -204,6 +208,11 @@ module RubyLsp
|
|
204
208
|
Constant::SymbolKind::FIELD
|
205
209
|
end
|
206
210
|
end
|
211
|
+
|
212
|
+
sig { params(sorbet_level: RubyDocument::SorbetLevel).returns(T::Boolean) }
|
213
|
+
def sorbet_level_true_or_higher?(sorbet_level)
|
214
|
+
sorbet_level == RubyDocument::SorbetLevel::True || sorbet_level == RubyDocument::SorbetLevel::Strict
|
215
|
+
end
|
207
216
|
end
|
208
217
|
end
|
209
218
|
end
|
@@ -54,8 +54,6 @@ module RubyLsp
|
|
54
54
|
end
|
55
55
|
|
56
56
|
entry.mixin_operations.each do |mixin_operation|
|
57
|
-
next if mixin_operation.is_a?(RubyIndexer::Entry::Extend)
|
58
|
-
|
59
57
|
mixin_name = mixin_operation.module_name
|
60
58
|
resolved_mixin_entries = @index.resolve(mixin_name, entry.nesting)
|
61
59
|
next unless resolved_mixin_entries
|
@@ -75,14 +73,12 @@ module RubyLsp
|
|
75
73
|
|
76
74
|
sig { params(entry: RubyIndexer::Entry).returns(Interface::TypeHierarchyItem) }
|
77
75
|
def hierarchy_item(entry)
|
78
|
-
range = range_from_location(entry.location)
|
79
|
-
|
80
76
|
Interface::TypeHierarchyItem.new(
|
81
77
|
name: entry.name,
|
82
78
|
kind: kind_for_entry(entry),
|
83
79
|
uri: URI::Generic.from_path(path: entry.file_path).to_s,
|
84
|
-
range:
|
85
|
-
selection_range:
|
80
|
+
range: range_from_location(entry.location),
|
81
|
+
selection_range: range_from_location(entry.name_location),
|
86
82
|
detail: entry.file_name,
|
87
83
|
)
|
88
84
|
end
|
@@ -3,6 +3,16 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
class RubyDocument < Document
|
6
|
+
class SorbetLevel < T::Enum
|
7
|
+
enums do
|
8
|
+
None = new("none")
|
9
|
+
Ignore = new("ignore")
|
10
|
+
False = new("false")
|
11
|
+
True = new("true")
|
12
|
+
Strict = new("strict")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
sig { override.returns(Prism::ParseResult) }
|
7
17
|
def parse
|
8
18
|
return @parse_result unless @needs_parsing
|
@@ -10,5 +20,69 @@ module RubyLsp
|
|
10
20
|
@needs_parsing = false
|
11
21
|
@parse_result = Prism.parse(@source)
|
12
22
|
end
|
23
|
+
|
24
|
+
sig { override.returns(T::Boolean) }
|
25
|
+
def syntax_error?
|
26
|
+
@parse_result.failure?
|
27
|
+
end
|
28
|
+
|
29
|
+
sig { override.returns(LanguageId) }
|
30
|
+
def language_id
|
31
|
+
LanguageId::Ruby
|
32
|
+
end
|
33
|
+
|
34
|
+
sig { returns(SorbetLevel) }
|
35
|
+
def sorbet_level
|
36
|
+
sigil = parse_result.magic_comments.find do |comment|
|
37
|
+
comment.key == "typed"
|
38
|
+
end&.value
|
39
|
+
|
40
|
+
case sigil
|
41
|
+
when "ignore"
|
42
|
+
SorbetLevel::Ignore
|
43
|
+
when "false"
|
44
|
+
SorbetLevel::False
|
45
|
+
when "true"
|
46
|
+
SorbetLevel::True
|
47
|
+
when "strict", "strong"
|
48
|
+
SorbetLevel::Strict
|
49
|
+
else
|
50
|
+
SorbetLevel::None
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
sig do
|
55
|
+
params(
|
56
|
+
range: T::Hash[Symbol, T.untyped],
|
57
|
+
node_types: T::Array[T.class_of(Prism::Node)],
|
58
|
+
).returns(T.nilable(Prism::Node))
|
59
|
+
end
|
60
|
+
def locate_first_within_range(range, node_types: [])
|
61
|
+
scanner = create_scanner
|
62
|
+
start_position = scanner.find_char_position(range[:start])
|
63
|
+
end_position = scanner.find_char_position(range[:end])
|
64
|
+
desired_range = (start_position...end_position)
|
65
|
+
queue = T.let(@parse_result.value.child_nodes.compact, T::Array[T.nilable(Prism::Node)])
|
66
|
+
|
67
|
+
until queue.empty?
|
68
|
+
candidate = queue.shift
|
69
|
+
|
70
|
+
# Skip nil child nodes
|
71
|
+
next if candidate.nil?
|
72
|
+
|
73
|
+
# Add the next child_nodes to the queue to be processed. The order here is important! We want to move in the
|
74
|
+
# same order as the visiting mechanism, which means searching the child nodes before moving on to the next
|
75
|
+
# sibling
|
76
|
+
T.unsafe(queue).unshift(*candidate.child_nodes)
|
77
|
+
|
78
|
+
# Skip if the current node doesn't cover the desired position
|
79
|
+
loc = candidate.location
|
80
|
+
|
81
|
+
if desired_range.cover?(loc.start_offset...loc.end_offset) &&
|
82
|
+
(node_types.empty? || node_types.any? { |type| candidate.class == type })
|
83
|
+
return candidate
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
13
87
|
end
|
14
88
|
end
|