ruby-lsp 0.23.17 → 0.23.18
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/index.rb +5 -0
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -9
- data/lib/ruby_indexer/test/prefix_tree_test.rb +8 -8
- data/lib/ruby_lsp/client_capabilities.rb +6 -1
- data/lib/ruby_lsp/document.rb +6 -2
- data/lib/ruby_lsp/erb_document.rb +1 -4
- data/lib/ruby_lsp/internal.rb +6 -1
- data/lib/ruby_lsp/listeners/hover.rb +8 -5
- data/lib/ruby_lsp/listeners/test_discovery.rb +1 -1
- data/lib/ruby_lsp/listeners/test_style.rb +1 -1
- data/lib/ruby_lsp/rbs_document.rb +1 -4
- data/lib/ruby_lsp/requests/code_lens.rb +1 -1
- data/lib/ruby_lsp/requests/definition.rb +0 -2
- data/lib/ruby_lsp/requests/hover.rb +1 -4
- data/lib/ruby_lsp/requests/request.rb +1 -1
- data/lib/ruby_lsp/requests/support/test_item.rb +1 -1
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +1 -4
- data/lib/ruby_lsp/response_builders/document_symbol.rb +1 -2
- data/lib/ruby_lsp/response_builders/hover.rb +1 -4
- data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +1 -2
- data/lib/ruby_lsp/response_builders/signature_help.rb +1 -2
- data/lib/ruby_lsp/response_builders/test_collection.rb +9 -20
- data/lib/ruby_lsp/ruby_document.rb +1 -4
- data/lib/ruby_lsp/server.rb +40 -1
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +16 -6
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +6 -23
- data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +5 -17
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ccc13fa3f30ae54cbb92ce72ea8ae2c6707a94cbed29991c6df6eb424de1797e
|
4
|
+
data.tar.gz: d30bbc7515361249d332006aac49f73256912cedf5afd0690e6ac37970ed3bcb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7667f639640708645275f8c8980d0da6a40943883729eb96f6c7d5ebbf26dbe66f167bcc0dccef77899a7f028db20c029a0c9808646b7113ce2cfed4cf48d689
|
7
|
+
data.tar.gz: 84f1da1bb1150b55e8667f2ca8aac9249e0d86cae5c4a9d9ac6494c79eba7c17d54bbed43aa8c4a263614e9cbec1d0e8a30876395295c86b3747d62020bf2a4e
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.23.
|
1
|
+
0.23.18
|
@@ -32,14 +32,14 @@ module RubyIndexer
|
|
32
32
|
# `Value` type.
|
33
33
|
#
|
34
34
|
# See https://en.wikipedia.org/wiki/Trie for more information
|
35
|
+
#: [Value]
|
35
36
|
class PrefixTree
|
36
|
-
extend T::Generic
|
37
|
-
|
38
|
-
Value = type_member
|
39
|
-
|
40
37
|
#: -> void
|
41
38
|
def initialize
|
42
|
-
@root = Node.new(
|
39
|
+
@root = Node.new(
|
40
|
+
"",
|
41
|
+
"", #: as untyped
|
42
|
+
) #: Node[Value]
|
43
43
|
end
|
44
44
|
|
45
45
|
# Search the PrefixTree based on a given `prefix`. If `foo` is an entry in the tree, then searching for `fo` will
|
@@ -106,11 +106,8 @@ module RubyIndexer
|
|
106
106
|
node
|
107
107
|
end
|
108
108
|
|
109
|
+
#: [Value]
|
109
110
|
class Node
|
110
|
-
extend T::Generic
|
111
|
-
|
112
|
-
Value = type_member
|
113
|
-
|
114
111
|
#: Hash[String, Node[Value]]
|
115
112
|
attr_reader :children
|
116
113
|
|
@@ -22,7 +22,7 @@ module RubyIndexer
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_multiple_items
|
25
|
-
tree = PrefixTree[String]
|
25
|
+
tree = PrefixTree.new #: PrefixTree[String]
|
26
26
|
["foo", "bar", "baz"].each { |item| tree.insert(item, item) }
|
27
27
|
|
28
28
|
assert_equal(["baz", "bar", "foo"], tree.search(""))
|
@@ -34,7 +34,7 @@ module RubyIndexer
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def test_multiple_prefixes
|
37
|
-
tree = PrefixTree[String]
|
37
|
+
tree = PrefixTree.new #: PrefixTree[String]
|
38
38
|
["fo", "foo"].each { |item| tree.insert(item, item) }
|
39
39
|
|
40
40
|
assert_equal(["fo", "foo"], tree.search(""))
|
@@ -45,7 +45,7 @@ module RubyIndexer
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_multiple_prefixes_with_shuffled_order
|
48
|
-
tree = PrefixTree[String]
|
48
|
+
tree = PrefixTree.new #: PrefixTree[String]
|
49
49
|
[
|
50
50
|
"foo/bar/base",
|
51
51
|
"foo/bar/on",
|
@@ -97,7 +97,7 @@ module RubyIndexer
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def test_deletion
|
100
|
-
tree = PrefixTree[String]
|
100
|
+
tree = PrefixTree.new #: PrefixTree[String]
|
101
101
|
["foo/bar", "foo/baz"].each { |item| tree.insert(item, item) }
|
102
102
|
assert_equal(["foo/baz", "foo/bar"], tree.search("foo"))
|
103
103
|
|
@@ -107,7 +107,7 @@ module RubyIndexer
|
|
107
107
|
end
|
108
108
|
|
109
109
|
def test_delete_does_not_impact_other_keys_with_the_same_value
|
110
|
-
tree = PrefixTree[String]
|
110
|
+
tree = PrefixTree.new #: PrefixTree[String]
|
111
111
|
tree.insert("key1", "value")
|
112
112
|
tree.insert("key2", "value")
|
113
113
|
assert_equal(["value", "value"], tree.search("key"))
|
@@ -118,7 +118,7 @@ module RubyIndexer
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def test_deleted_node_is_removed_from_the_tree
|
121
|
-
tree = PrefixTree[String]
|
121
|
+
tree = PrefixTree.new #: PrefixTree[String]
|
122
122
|
tree.insert("foo/bar", "foo/bar")
|
123
123
|
assert_equal(["foo/bar"], tree.search("foo"))
|
124
124
|
|
@@ -128,7 +128,7 @@ module RubyIndexer
|
|
128
128
|
end
|
129
129
|
|
130
130
|
def test_deleting_non_terminal_nodes
|
131
|
-
tree = PrefixTree[String]
|
131
|
+
tree = PrefixTree.new #: PrefixTree[String]
|
132
132
|
tree.insert("abc", "value1")
|
133
133
|
tree.insert("abcdef", "value2")
|
134
134
|
|
@@ -138,7 +138,7 @@ module RubyIndexer
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def test_overriding_values
|
141
|
-
tree = PrefixTree[Integer]
|
141
|
+
tree = PrefixTree.new #: PrefixTree[Integer]
|
142
142
|
|
143
143
|
tree.insert("foo/bar", 123)
|
144
144
|
assert_equal([123], tree.search("foo/bar"))
|
@@ -10,7 +10,8 @@ module RubyLsp
|
|
10
10
|
:supports_request_delegation,
|
11
11
|
:window_show_message_supports_extra_properties,
|
12
12
|
:supports_progress,
|
13
|
-
:supports_diagnostic_refresh
|
13
|
+
:supports_diagnostic_refresh,
|
14
|
+
:supports_code_lens_refresh
|
14
15
|
|
15
16
|
#: -> void
|
16
17
|
def initialize
|
@@ -34,6 +35,9 @@ module RubyLsp
|
|
34
35
|
|
35
36
|
# The editor supports server initiated refresh for diagnostics
|
36
37
|
@supports_diagnostic_refresh = false #: bool
|
38
|
+
|
39
|
+
# The editor supports server initiated refresh for code lenses
|
40
|
+
@supports_code_lens_refresh = false #: bool
|
37
41
|
end
|
38
42
|
|
39
43
|
#: (Hash[Symbol, untyped] capabilities) -> void
|
@@ -61,6 +65,7 @@ module RubyLsp
|
|
61
65
|
@supports_progress = progress if progress
|
62
66
|
|
63
67
|
@supports_diagnostic_refresh = workspace_capabilities.dig(:diagnostics, :refreshSupport) || false
|
68
|
+
@supports_code_lens_refresh = workspace_capabilities.dig(:codeLens, :refreshSupport) || false
|
64
69
|
end
|
65
70
|
|
66
71
|
#: -> bool
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -2,13 +2,12 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
+
#: [ParseResultType]
|
5
6
|
class Document
|
6
7
|
extend T::Sig
|
7
8
|
extend T::Helpers
|
8
|
-
extend T::Generic
|
9
9
|
|
10
10
|
class LocationNotFoundError < StandardError; end
|
11
|
-
ParseResultType = type_member
|
12
11
|
|
13
12
|
# This maximum number of characters for providing expensive features, like semantic highlighting and diagnostics.
|
14
13
|
# This is the same number used by the TypeScript extension in VS Code
|
@@ -86,6 +85,11 @@ module RubyLsp
|
|
86
85
|
@cache[request_name]
|
87
86
|
end
|
88
87
|
|
88
|
+
#: (String request_name) -> void
|
89
|
+
def clear_cache(request_name)
|
90
|
+
@cache[request_name] = EMPTY_CACHE
|
91
|
+
end
|
92
|
+
|
89
93
|
#: (Array[Hash[Symbol, untyped]] edits, version: Integer) -> void
|
90
94
|
def push_edits(edits, version:)
|
91
95
|
edits.each do |edit|
|
@@ -2,11 +2,8 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
+
#: [ParseResultType = Prism::ParseResult]
|
5
6
|
class ERBDocument < Document
|
6
|
-
extend T::Generic
|
7
|
-
|
8
|
-
ParseResultType = type_member { { fixed: Prism::ParseResult } }
|
9
|
-
|
10
7
|
#: String
|
11
8
|
attr_reader :host_language_source
|
12
9
|
|
data/lib/ruby_lsp/internal.rb
CHANGED
@@ -14,7 +14,12 @@ Bundler.ui.level = :silent
|
|
14
14
|
|
15
15
|
require "json"
|
16
16
|
require "uri"
|
17
|
-
require "cgi"
|
17
|
+
require "cgi/escape"
|
18
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.5")
|
19
|
+
# Just requiring `cgi/escape` leaves CGI.unescape broken on older rubies
|
20
|
+
# Some background on why this is necessary: https://bugs.ruby-lang.org/issues/21258
|
21
|
+
require "cgi/util"
|
22
|
+
end
|
18
23
|
require "set"
|
19
24
|
require "strscan"
|
20
25
|
require "prism"
|
@@ -86,6 +86,14 @@ module RubyLsp
|
|
86
86
|
|
87
87
|
#: (Prism::StringNode node) -> void
|
88
88
|
def on_string_node_enter(node)
|
89
|
+
if @path && File.basename(@path) == GEMFILE_NAME
|
90
|
+
call_node = @node_context.call_node
|
91
|
+
if call_node && call_node.name == :gem && call_node.arguments&.arguments&.first == node
|
92
|
+
generate_gem_hover(call_node)
|
93
|
+
return
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
89
97
|
generate_heredoc_hover(node)
|
90
98
|
end
|
91
99
|
|
@@ -123,11 +131,6 @@ module RubyLsp
|
|
123
131
|
|
124
132
|
#: (Prism::CallNode node) -> void
|
125
133
|
def on_call_node_enter(node)
|
126
|
-
if @path && File.basename(@path) == GEMFILE_NAME && node.name == :gem
|
127
|
-
generate_gem_hover(node)
|
128
|
-
return
|
129
|
-
end
|
130
|
-
|
131
134
|
return if @sorbet_level.true_or_higher? && self_receiver?(node)
|
132
135
|
|
133
136
|
message = node.message
|
@@ -71,7 +71,7 @@ module RubyLsp
|
|
71
71
|
slice.gsub(/((?<=::)|^)[a-z]\w*/, DYNAMIC_REFERENCE_MARKER)
|
72
72
|
end
|
73
73
|
|
74
|
-
#: (Prism::ClassNode node
|
74
|
+
#: (Prism::ClassNode node) { (String name, Array[String] ancestors) -> void } -> void
|
75
75
|
def with_test_ancestor_tracking(node, &block)
|
76
76
|
@visibility_stack << :public
|
77
77
|
name = constant_name(node.constant_path)
|
@@ -2,11 +2,8 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
+
#: [ParseResultType = Array[RBS::AST::Declarations::Base]]
|
5
6
|
class RBSDocument < Document
|
6
|
-
extend T::Generic
|
7
|
-
|
8
|
-
ParseResultType = type_member { { fixed: T::Array[RBS::AST::Declarations::Base] } }
|
9
|
-
|
10
7
|
#: (source: String, version: Integer, uri: URI::Generic, global_state: GlobalState) -> void
|
11
8
|
def initialize(source:, version:, uri:, global_state:)
|
12
9
|
@syntax_error = false #: bool
|
@@ -9,8 +9,6 @@ module RubyLsp
|
|
9
9
|
# request](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition) jumps to the
|
10
10
|
# definition of the symbol under the cursor.
|
11
11
|
class Definition < Request
|
12
|
-
extend T::Generic
|
13
|
-
|
14
12
|
#: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
|
15
13
|
def initialize(document, global_state, position, dispatcher, sorbet_level)
|
16
14
|
super()
|
@@ -7,9 +7,8 @@ module RubyLsp
|
|
7
7
|
module Requests
|
8
8
|
# The [hover request](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover)
|
9
9
|
# displays the documentation for the symbol currently under the cursor.
|
10
|
+
#: [ResponseType = Interface::Hover?]
|
10
11
|
class Hover < Request
|
11
|
-
extend T::Generic
|
12
|
-
|
13
12
|
class << self
|
14
13
|
#: -> Interface::HoverOptions
|
15
14
|
def provider
|
@@ -17,8 +16,6 @@ module RubyLsp
|
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
|
-
ResponseType = type_member { { fixed: T.nilable(Interface::Hover) } }
|
21
|
-
|
22
19
|
#: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
|
23
20
|
def initialize(document, global_state, position, dispatcher, sorbet_level)
|
24
21
|
super()
|
@@ -19,7 +19,7 @@ module RubyLsp
|
|
19
19
|
#: Interface::Range
|
20
20
|
attr_reader :range
|
21
21
|
|
22
|
-
#: (String id, String label, URI::Generic uri, Interface::Range range, Symbol
|
22
|
+
#: (String id, String label, URI::Generic uri, Interface::Range range, framework: Symbol) -> void
|
23
23
|
def initialize(id, label, uri, range, framework:)
|
24
24
|
@id = id
|
25
25
|
@label = label
|
@@ -3,9 +3,8 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module ResponseBuilders
|
6
|
+
#: [ResponseType = Array[Interface::DocumentSymbol]]
|
6
7
|
class DocumentSymbol < ResponseBuilder
|
7
|
-
ResponseType = type_member { { fixed: T::Array[Interface::DocumentSymbol] } }
|
8
|
-
|
9
8
|
class SymbolHierarchyRoot
|
10
9
|
#: Array[Interface::DocumentSymbol]
|
11
10
|
attr_reader :children
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module ResponseBuilders
|
6
|
+
#: [ResponseType = Interface::SemanticTokens]
|
6
7
|
class SemanticHighlighting < ResponseBuilder
|
7
8
|
class UndefinedTokenType < StandardError; end
|
8
9
|
|
@@ -45,8 +46,6 @@ module RubyLsp
|
|
45
46
|
default_library: 9,
|
46
47
|
}.freeze #: Hash[Symbol, Integer]
|
47
48
|
|
48
|
-
ResponseType = type_member { { fixed: Interface::SemanticTokens } }
|
49
|
-
|
50
49
|
#: ((^(Integer arg0) -> Integer | Prism::CodeUnitsCache) code_units_cache) -> void
|
51
50
|
def initialize(code_units_cache)
|
52
51
|
super()
|
@@ -3,11 +3,8 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module ResponseBuilders
|
6
|
+
#: [ResponseType = Requests::Support::TestItem]
|
6
7
|
class TestCollection < ResponseBuilder
|
7
|
-
extend T::Generic
|
8
|
-
|
9
|
-
ResponseType = type_member { { fixed: Requests::Support::TestItem } }
|
10
|
-
|
11
8
|
#: Array[Interface::CodeLens]
|
12
9
|
attr_reader :code_lens
|
13
10
|
|
@@ -25,34 +22,26 @@ module RubyLsp
|
|
25
22
|
|
26
23
|
#: (ResponseType item) -> void
|
27
24
|
def add_code_lens(item)
|
28
|
-
range = item.range
|
29
25
|
arguments = [item.uri.to_standardized_path, item.id]
|
26
|
+
start = item.range.start
|
27
|
+
range = Interface::Range.new(
|
28
|
+
start: start,
|
29
|
+
end: Interface::Position.new(line: start.line, character: start.character + 1),
|
30
|
+
)
|
30
31
|
|
31
32
|
@code_lens << Interface::CodeLens.new(
|
32
33
|
range: range,
|
33
|
-
|
34
|
-
title: "▶ Run",
|
35
|
-
command: "rubyLsp.runTest",
|
36
|
-
arguments: arguments,
|
37
|
-
),
|
34
|
+
data: { arguments: arguments, kind: "run_test" },
|
38
35
|
)
|
39
36
|
|
40
37
|
@code_lens << Interface::CodeLens.new(
|
41
38
|
range: range,
|
42
|
-
|
43
|
-
title: "▶ Run In Terminal",
|
44
|
-
command: "rubyLsp.runTestInTerminal",
|
45
|
-
arguments: arguments,
|
46
|
-
),
|
39
|
+
data: { arguments: arguments, kind: "run_test_in_terminal" },
|
47
40
|
)
|
48
41
|
|
49
42
|
@code_lens << Interface::CodeLens.new(
|
50
43
|
range: range,
|
51
|
-
|
52
|
-
title: "⚙ Debug",
|
53
|
-
command: "rubyLsp.debugTest",
|
54
|
-
arguments: arguments,
|
55
|
-
),
|
44
|
+
data: { arguments: arguments, kind: "debug_test" },
|
56
45
|
)
|
57
46
|
end
|
58
47
|
|
@@ -2,11 +2,8 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
+
#: [ParseResultType = Prism::ParseResult]
|
5
6
|
class RubyDocument < Document
|
6
|
-
extend T::Generic
|
7
|
-
|
8
|
-
ParseResultType = type_member { { fixed: Prism::ParseResult } }
|
9
|
-
|
10
7
|
METHODS_THAT_CHANGE_DECLARATIONS = [
|
11
8
|
:private_constant,
|
12
9
|
:attr_reader,
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -32,6 +32,8 @@ module RubyLsp
|
|
32
32
|
text_document_document_link(message)
|
33
33
|
when "textDocument/codeLens"
|
34
34
|
text_document_code_lens(message)
|
35
|
+
when "codeLens/resolve"
|
36
|
+
code_lens_resolve(message)
|
35
37
|
when "textDocument/semanticTokens/full"
|
36
38
|
text_document_semantic_tokens_full(message)
|
37
39
|
when "textDocument/semanticTokens/full/delta"
|
@@ -1124,7 +1126,7 @@ module RubyLsp
|
|
1124
1126
|
# Clear all document caches for pull diagnostics
|
1125
1127
|
@global_state.synchronize do
|
1126
1128
|
@store.each do |_uri, document|
|
1127
|
-
document.
|
1129
|
+
document.clear_cache("textDocument/diagnostic")
|
1128
1130
|
end
|
1129
1131
|
end
|
1130
1132
|
|
@@ -1280,9 +1282,25 @@ module RubyLsp
|
|
1280
1282
|
# allocations and garbage collections are faster
|
1281
1283
|
GC.compact unless @test_mode
|
1282
1284
|
|
1285
|
+
@global_state.synchronize do
|
1286
|
+
# If we linearize ancestors while the index is not fully populated, we may end up caching incorrect results
|
1287
|
+
# that were missing namespaces. After indexing is complete, we need to clear the ancestors cache and start
|
1288
|
+
# again
|
1289
|
+
@global_state.index.clear_ancestors
|
1290
|
+
|
1291
|
+
# The results for code lens depend on ancestor linearization, so we need to clear any previously computed
|
1292
|
+
# responses
|
1293
|
+
@store.each { |_uri, document| document.clear_cache("textDocument/codeLens") }
|
1294
|
+
end
|
1295
|
+
|
1283
1296
|
# Always end the progress notification even if indexing failed or else it never goes away and the user has no
|
1284
1297
|
# way of dismissing it
|
1285
1298
|
end_progress("indexing-progress")
|
1299
|
+
|
1300
|
+
# Request a code lens refresh if we populated them before all test parent classes were indexed
|
1301
|
+
if @global_state.client_capabilities.supports_code_lens_refresh
|
1302
|
+
send_message(Request.new(id: @current_request_id, method: "workspace/codeLens/refresh", params: nil))
|
1303
|
+
end
|
1286
1304
|
end
|
1287
1305
|
end
|
1288
1306
|
|
@@ -1497,5 +1515,26 @@ module RubyLsp
|
|
1497
1515
|
},
|
1498
1516
|
))
|
1499
1517
|
end
|
1518
|
+
|
1519
|
+
#: (Hash[Symbol, untyped] message) -> void
|
1520
|
+
def code_lens_resolve(message)
|
1521
|
+
code_lens = message[:params]
|
1522
|
+
args = code_lens.dig(:data, :arguments)
|
1523
|
+
|
1524
|
+
case code_lens.dig(:data, :kind)
|
1525
|
+
when "run_test"
|
1526
|
+
code_lens[:command] = Interface::Command.new(title: "▶ Run", command: "rubyLsp.runTest", arguments: args)
|
1527
|
+
when "run_test_in_terminal"
|
1528
|
+
code_lens[:command] =
|
1529
|
+
Interface::Command.new(title: "▶ Run in terminal", command: "rubyLsp.runTestInTerminal", arguments: args)
|
1530
|
+
when "debug_test"
|
1531
|
+
code_lens[:command] = Interface::Command.new(title: "⚙ Debug", command: "rubyLsp.debugTest", arguments: args)
|
1532
|
+
end
|
1533
|
+
|
1534
|
+
send_message(Result.new(
|
1535
|
+
id: message[:id],
|
1536
|
+
response: code_lens,
|
1537
|
+
))
|
1538
|
+
end
|
1500
1539
|
end
|
1501
1540
|
end
|
@@ -59,9 +59,9 @@ module RubyLsp
|
|
59
59
|
@io.close
|
60
60
|
end
|
61
61
|
|
62
|
-
#: (id: String, uri: URI::Generic) -> void
|
63
|
-
def start_test(id:, uri:)
|
64
|
-
send_message("start", id: id, uri: uri.to_s)
|
62
|
+
#: (id: String, uri: URI::Generic, ?line: Integer?) -> void
|
63
|
+
def start_test(id:, uri:, line: nil)
|
64
|
+
send_message("start", id: id, uri: uri.to_s, line: line)
|
65
65
|
end
|
66
66
|
|
67
67
|
#: (id: String, uri: URI::Generic) -> void
|
@@ -84,6 +84,17 @@ module RubyLsp
|
|
84
84
|
send_message("error", id: id, message: message, uri: uri.to_s)
|
85
85
|
end
|
86
86
|
|
87
|
+
#: (Method | UnboundMethod) -> [URI::Generic, Integer?]?
|
88
|
+
def uri_and_line_for(method_object)
|
89
|
+
file_path, line = method_object.source_location
|
90
|
+
return unless file_path
|
91
|
+
return if file_path.start_with?("(eval at ")
|
92
|
+
|
93
|
+
uri = URI::Generic.from_path(path: File.expand_path(file_path))
|
94
|
+
zero_based_line = line ? line - 1 : nil
|
95
|
+
[uri, zero_based_line]
|
96
|
+
end
|
97
|
+
|
87
98
|
# Gather the results returned by Coverage.result and format like the VS Code test explorer expects
|
88
99
|
#
|
89
100
|
# Coverage result format:
|
@@ -115,10 +126,9 @@ module RubyLsp
|
|
115
126
|
def gather_coverage_results
|
116
127
|
# Ignore coverage results inside dependencies
|
117
128
|
bundle_path = Bundler.bundle_path.to_s
|
118
|
-
default_gems_path = File.dirname(RbConfig::CONFIG["rubylibdir"])
|
119
129
|
|
120
130
|
result = Coverage.result.reject do |file_path, _coverage_info|
|
121
|
-
file_path.start_with?(bundle_path
|
131
|
+
file_path.start_with?(bundle_path) || !file_path.start_with?(Dir.pwd)
|
122
132
|
end
|
123
133
|
|
124
134
|
result.to_h do |file_path, coverage_info|
|
@@ -163,7 +173,7 @@ module RubyLsp
|
|
163
173
|
|
164
174
|
private
|
165
175
|
|
166
|
-
#: (
|
176
|
+
#: (String?, **untyped) -> void
|
167
177
|
def send_message(method_name, **params)
|
168
178
|
json_message = { method: method_name, params: params }.to_json
|
169
179
|
@io.write("Content-Length: #{json_message.bytesize}\r\n\r\n#{json_message}")
|
@@ -51,16 +51,19 @@ module RubyLsp
|
|
51
51
|
|
52
52
|
#: (singleton(Minitest::Test) test_class, String method_name) -> void
|
53
53
|
def prerecord(test_class, method_name)
|
54
|
-
uri =
|
54
|
+
uri, line = LspReporter.instance.uri_and_line_for(test_class.instance_method(method_name))
|
55
55
|
return unless uri
|
56
56
|
|
57
|
-
LspReporter.instance.start_test(id: "#{test_class.name}##{method_name}", uri: uri)
|
57
|
+
LspReporter.instance.start_test(id: "#{test_class.name}##{method_name}", uri: uri, line: line)
|
58
58
|
end
|
59
59
|
|
60
60
|
#: (Minitest::Result result) -> void
|
61
61
|
def record(result)
|
62
62
|
id = "#{result.klass}##{result.name}"
|
63
|
-
|
63
|
+
file_path, _line = result.source_location
|
64
|
+
return unless file_path
|
65
|
+
|
66
|
+
uri = URI::Generic.from_path(path: File.expand_path(file_path))
|
64
67
|
|
65
68
|
if result.error?
|
66
69
|
message = result.failures.first.message
|
@@ -79,26 +82,6 @@ module RubyLsp
|
|
79
82
|
def report
|
80
83
|
LspReporter.instance.shutdown
|
81
84
|
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
#: (Minitest::Result result) -> URI::Generic
|
86
|
-
def uri_from_result(result)
|
87
|
-
file = result.source_location[0]
|
88
|
-
absolute_path = File.expand_path(file, Dir.pwd)
|
89
|
-
URI::Generic.from_path(path: absolute_path)
|
90
|
-
end
|
91
|
-
|
92
|
-
#: (singleton(Minitest::Test) test_class, String method_name) -> URI::Generic?
|
93
|
-
def uri_from_test_class(test_class, method_name)
|
94
|
-
file, _line = test_class.instance_method(method_name).source_location
|
95
|
-
return unless file
|
96
|
-
|
97
|
-
return if file.start_with?("(eval at ") # test is dynamically defined
|
98
|
-
|
99
|
-
absolute_path = File.expand_path(file, Dir.pwd)
|
100
|
-
URI::Generic.from_path(path: absolute_path)
|
101
|
-
end
|
102
85
|
end
|
103
86
|
end
|
104
87
|
|
@@ -26,12 +26,12 @@ module RubyLsp
|
|
26
26
|
def test_started(test)
|
27
27
|
super
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
return unless @current_uri
|
29
|
+
uri, line = LspReporter.instance.uri_and_line_for(test.method(test.method_name))
|
30
|
+
return unless uri
|
32
31
|
|
33
|
-
@
|
34
|
-
|
32
|
+
@current_uri = uri
|
33
|
+
@current_test_id = "#{test.class.name}##{test.method_name}"
|
34
|
+
LspReporter.instance.start_test(id: @current_test_id, uri: @current_uri, line: line)
|
35
35
|
end
|
36
36
|
|
37
37
|
#: (::Test::Unit::TestCase test) -> void
|
@@ -62,18 +62,6 @@ module RubyLsp
|
|
62
62
|
LspReporter.instance.shutdown
|
63
63
|
end
|
64
64
|
|
65
|
-
#: (::Test::Unit::TestCase test) -> URI::Generic?
|
66
|
-
def uri_for_test(test)
|
67
|
-
location = test.method(test.method_name).source_location
|
68
|
-
return unless location
|
69
|
-
|
70
|
-
file, _line = location
|
71
|
-
return if file.start_with?("(eval at ")
|
72
|
-
|
73
|
-
absolute_path = File.expand_path(file, Dir.pwd)
|
74
|
-
URI::Generic.from_path(path: absolute_path)
|
75
|
-
end
|
76
|
-
|
77
65
|
#: -> void
|
78
66
|
def attach_to_mediator
|
79
67
|
# Events we care about
|