ruby-lsp 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/VERSION +1 -1
- data/exe/ruby-lsp-check +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +35 -5
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +141 -5
- data/lib/ruby_indexer/lib/ruby_indexer/visitor.rb +66 -18
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +39 -16
- data/lib/ruby_indexer/test/configuration_test.rb +2 -0
- data/lib/ruby_indexer/test/constant_test.rb +213 -11
- data/lib/ruby_indexer/test/index_test.rb +20 -0
- data/lib/ruby_lsp/{extension.rb → addon.rb} +27 -25
- data/lib/ruby_lsp/check_docs.rb +7 -8
- data/lib/ruby_lsp/document.rb +35 -38
- data/lib/ruby_lsp/event_emitter.rb +239 -77
- data/lib/ruby_lsp/executor.rb +45 -55
- data/lib/ruby_lsp/internal.rb +2 -3
- data/lib/ruby_lsp/listener.rb +8 -7
- data/lib/ruby_lsp/parameter_scope.rb +33 -0
- data/lib/ruby_lsp/requests/base_request.rb +3 -3
- data/lib/ruby_lsp/requests/code_action_resolve.rb +14 -14
- data/lib/ruby_lsp/requests/code_lens.rb +39 -63
- data/lib/ruby_lsp/requests/completion.rb +54 -32
- data/lib/ruby_lsp/requests/definition.rb +30 -27
- data/lib/ruby_lsp/requests/diagnostics.rb +26 -3
- data/lib/ruby_lsp/requests/document_highlight.rb +18 -19
- data/lib/ruby_lsp/requests/document_link.rb +53 -10
- data/lib/ruby_lsp/requests/document_symbol.rb +82 -75
- data/lib/ruby_lsp/requests/folding_ranges.rb +199 -222
- data/lib/ruby_lsp/requests/formatting.rb +5 -6
- data/lib/ruby_lsp/requests/hover.rb +33 -22
- data/lib/ruby_lsp/requests/inlay_hints.rb +2 -3
- data/lib/ruby_lsp/requests/selection_ranges.rb +65 -40
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +187 -145
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +3 -4
- data/lib/ruby_lsp/requests/support/annotation.rb +18 -17
- data/lib/ruby_lsp/requests/support/common.rb +17 -26
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +67 -42
- data/lib/ruby_lsp/requests/support/highlight_target.rb +64 -45
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +9 -4
- data/lib/ruby_lsp/requests/support/selection_range.rb +5 -4
- data/lib/ruby_lsp/requests/support/sorbet.rb +2 -57
- data/lib/ruby_lsp/requests/support/syntax_tree_formatting_runner.rb +7 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -1
- data/lib/ruby_lsp/server.rb +6 -44
- data/lib/ruby_lsp/setup_bundler.rb +22 -11
- data/lib/ruby_lsp/utils.rb +2 -12
- metadata +11 -30
@@ -5,12 +5,13 @@ module RubyLsp
|
|
5
5
|
module Requests
|
6
6
|
module Support
|
7
7
|
module Common
|
8
|
-
# WARNING: Methods in this class may be used by Ruby LSP
|
9
|
-
# or
|
8
|
+
# WARNING: Methods in this class may be used by Ruby LSP addons such as
|
9
|
+
# https://github.com/Shopify/ruby-lsp-rails, or addons by created by developers outside of Shopify, so be
|
10
|
+
# cautious of changing anything.
|
10
11
|
extend T::Sig
|
11
12
|
|
12
|
-
sig { params(node:
|
13
|
-
def
|
13
|
+
sig { params(node: YARP::Node).returns(Interface::Range) }
|
14
|
+
def range_from_node(node)
|
14
15
|
loc = node.location
|
15
16
|
|
16
17
|
Interface::Range.new(
|
@@ -22,28 +23,18 @@ module RubyLsp
|
|
22
23
|
)
|
23
24
|
end
|
24
25
|
|
25
|
-
sig
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
case constant
|
36
|
-
when SyntaxTree::ConstPathRef
|
37
|
-
name.prepend("#{constant.constant.value}::")
|
38
|
-
when SyntaxTree::VarRef
|
39
|
-
name.prepend("#{constant.value.value}::")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
name
|
26
|
+
sig { params(location: YARP::Location).returns(Interface::Range) }
|
27
|
+
def range_from_location(location)
|
28
|
+
Interface::Range.new(
|
29
|
+
start: Interface::Position.new(
|
30
|
+
line: location.start_line - 1,
|
31
|
+
character: location.start_column,
|
32
|
+
),
|
33
|
+
end: Interface::Position.new(line: location.end_line - 1, character: location.end_column),
|
34
|
+
)
|
44
35
|
end
|
45
36
|
|
46
|
-
sig { params(node: T.nilable(
|
37
|
+
sig { params(node: T.nilable(YARP::Node), range: T.nilable(T::Range[Integer])).returns(T::Boolean) }
|
47
38
|
def visible?(node, range)
|
48
39
|
return true if range.nil?
|
49
40
|
return false if node.nil?
|
@@ -54,7 +45,7 @@ module RubyLsp
|
|
54
45
|
|
55
46
|
sig do
|
56
47
|
params(
|
57
|
-
node:
|
48
|
+
node: YARP::Node,
|
58
49
|
title: String,
|
59
50
|
command_name: String,
|
60
51
|
arguments: T.nilable(T::Array[T.untyped]),
|
@@ -62,7 +53,7 @@ module RubyLsp
|
|
62
53
|
).returns(Interface::CodeLens)
|
63
54
|
end
|
64
55
|
def create_code_lens(node, title:, command_name:, arguments:, data:)
|
65
|
-
range =
|
56
|
+
range = range_from_node(node)
|
66
57
|
|
67
58
|
Interface::CodeLens.new(
|
68
59
|
range: range,
|
@@ -1,55 +1,80 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "singleton"
|
5
|
+
|
4
6
|
module RubyLsp
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
sig { returns(String) }
|
10
|
-
def detected_formatter
|
11
|
-
# NOTE: Intentionally no $ at end, since we want to match rubocop-shopify, etc.
|
12
|
-
if direct_dependency?(/^rubocop/)
|
13
|
-
"rubocop"
|
14
|
-
elsif direct_dependency?(/^syntax_tree$/)
|
15
|
-
"syntax_tree"
|
16
|
-
else
|
17
|
-
"none"
|
18
|
-
end
|
19
|
-
end
|
7
|
+
class DependencyDetector
|
8
|
+
include Singleton
|
9
|
+
extend T::Sig
|
20
10
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
11
|
+
sig { returns(String) }
|
12
|
+
attr_reader :detected_formatter
|
13
|
+
|
14
|
+
sig { returns(String) }
|
15
|
+
attr_reader :detected_test_library
|
16
|
+
|
17
|
+
sig { returns(T::Boolean) }
|
18
|
+
attr_reader :typechecker
|
19
|
+
|
20
|
+
sig { void }
|
21
|
+
def initialize
|
22
|
+
@detected_formatter = T.let(detect_formatter, String)
|
23
|
+
@detected_test_library = T.let(detect_test_library, String)
|
24
|
+
@typechecker = T.let(detect_typechecker, T::Boolean)
|
25
|
+
end
|
38
26
|
|
39
|
-
|
40
|
-
|
41
|
-
|
27
|
+
sig { returns(String) }
|
28
|
+
def detect_formatter
|
29
|
+
# NOTE: Intentionally no $ at end, since we want to match rubocop-shopify, etc.
|
30
|
+
if direct_dependency?(/^rubocop/)
|
31
|
+
"rubocop"
|
32
|
+
elsif direct_dependency?(/^syntax_tree$/)
|
33
|
+
"syntax_tree"
|
34
|
+
else
|
35
|
+
"none"
|
42
36
|
end
|
37
|
+
end
|
43
38
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
39
|
+
sig { returns(String) }
|
40
|
+
def detect_test_library
|
41
|
+
# A Rails app may have a dependency on minitest, but we would instead want to use the Rails test runner provided
|
42
|
+
# by ruby-lsp-rails.
|
43
|
+
if direct_dependency?(/^rails$/)
|
44
|
+
"rails"
|
45
|
+
# NOTE: Intentionally ends with $ to avoid mis-matching minitest-reporters, etc. in a Rails app.
|
46
|
+
elsif direct_dependency?(/^minitest$/)
|
47
|
+
"minitest"
|
48
|
+
elsif direct_dependency?(/^test-unit/)
|
49
|
+
"test-unit"
|
50
|
+
elsif direct_dependency?(/^rspec/)
|
51
|
+
"rspec"
|
52
|
+
else
|
53
|
+
"unknown"
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
53
|
-
|
57
|
+
sig { params(gem_pattern: Regexp).returns(T::Boolean) }
|
58
|
+
def direct_dependency?(gem_pattern)
|
59
|
+
dependency_keys.grep(gem_pattern).any?
|
60
|
+
end
|
61
|
+
|
62
|
+
sig { returns(T::Boolean) }
|
63
|
+
def detect_typechecker
|
64
|
+
direct_dependency?(/^sorbet/) || direct_dependency?(/^sorbet-static-and-runtime/)
|
65
|
+
end
|
66
|
+
|
67
|
+
sig { returns(T::Array[String]) }
|
68
|
+
def dependency_keys
|
69
|
+
@dependency_keys ||= T.let(
|
70
|
+
begin
|
71
|
+
Bundler.with_original_env { Bundler.default_gemfile }
|
72
|
+
Bundler.locked_gems.dependencies.keys
|
73
|
+
rescue Bundler::GemfileNotFound
|
74
|
+
[]
|
75
|
+
end,
|
76
|
+
T.nilable(T::Array[String]),
|
77
|
+
)
|
78
|
+
end
|
54
79
|
end
|
55
80
|
end
|
@@ -16,81 +16,100 @@ module RubyLsp
|
|
16
16
|
sig { returns(Integer) }
|
17
17
|
attr_reader :type
|
18
18
|
|
19
|
-
sig { returns(
|
20
|
-
attr_reader :
|
19
|
+
sig { returns(YARP::Location) }
|
20
|
+
attr_reader :location
|
21
21
|
|
22
|
-
sig { params(type: Integer,
|
23
|
-
def initialize(type:,
|
22
|
+
sig { params(type: Integer, location: YARP::Location).void }
|
23
|
+
def initialize(type:, location:)
|
24
24
|
@type = type
|
25
|
-
@
|
25
|
+
@location = location
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
sig { params(node:
|
29
|
+
sig { params(node: YARP::Node).void }
|
30
30
|
def initialize(node)
|
31
31
|
@node = node
|
32
32
|
@value = T.let(value(node), T.nilable(String))
|
33
33
|
end
|
34
34
|
|
35
|
-
sig { params(other:
|
35
|
+
sig { params(other: YARP::Node).returns(T.nilable(HighlightMatch)) }
|
36
36
|
def highlight_type(other)
|
37
|
-
matched_highlight(other) if
|
37
|
+
matched_highlight(other) if @value && @value == value(other)
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
41
41
|
|
42
42
|
# Match the target type (where the cursor is positioned) with the `other` type (the node we're currently
|
43
43
|
# visiting)
|
44
|
-
sig { params(other:
|
44
|
+
sig { params(other: YARP::Node).returns(T.nilable(HighlightMatch)) }
|
45
45
|
def matched_highlight(other)
|
46
46
|
case @node
|
47
47
|
# Method definitions and invocations
|
48
|
-
when
|
49
|
-
SyntaxTree::CommandCall, SyntaxTree::DefNode
|
48
|
+
when YARP::CallNode, YARP::DefNode
|
50
49
|
case other
|
51
|
-
when
|
52
|
-
HighlightMatch.new(type: READ,
|
53
|
-
when
|
54
|
-
HighlightMatch.new(type: WRITE,
|
50
|
+
when YARP::CallNode
|
51
|
+
HighlightMatch.new(type: READ, location: other.location)
|
52
|
+
when YARP::DefNode
|
53
|
+
HighlightMatch.new(type: WRITE, location: other.name_loc)
|
55
54
|
end
|
56
55
|
# Variables, parameters and constants
|
57
|
-
|
58
|
-
SyntaxTree::VarRef, SyntaxTree::Ident
|
56
|
+
else
|
59
57
|
case other
|
60
|
-
when
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
58
|
+
when YARP::GlobalVariableTargetNode, YARP::InstanceVariableTargetNode, YARP::ConstantPathTargetNode,
|
59
|
+
YARP::ConstantTargetNode, YARP::ClassVariableTargetNode, YARP::LocalVariableTargetNode,
|
60
|
+
YARP::BlockParameterNode, YARP::RequiredParameterNode
|
61
|
+
|
62
|
+
HighlightMatch.new(type: WRITE, location: other.location)
|
63
|
+
when YARP::LocalVariableWriteNode, YARP::KeywordParameterNode, YARP::RestParameterNode,
|
64
|
+
YARP::OptionalParameterNode, YARP::KeywordRestParameterNode, YARP::LocalVariableAndWriteNode,
|
65
|
+
YARP::LocalVariableOperatorWriteNode, YARP::LocalVariableOrWriteNode, YARP::ClassVariableWriteNode,
|
66
|
+
YARP::ClassVariableOrWriteNode, YARP::ClassVariableOperatorWriteNode, YARP::ClassVariableAndWriteNode,
|
67
|
+
YARP::ConstantWriteNode, YARP::ConstantOrWriteNode, YARP::ConstantOperatorWriteNode,
|
68
|
+
YARP::InstanceVariableWriteNode, YARP::ConstantAndWriteNode, YARP::InstanceVariableOrWriteNode,
|
69
|
+
YARP::InstanceVariableAndWriteNode, YARP::InstanceVariableOperatorWriteNode,
|
70
|
+
YARP::GlobalVariableWriteNode, YARP::GlobalVariableOrWriteNode, YARP::GlobalVariableAndWriteNode,
|
71
|
+
YARP::GlobalVariableOperatorWriteNode
|
72
|
+
|
73
|
+
HighlightMatch.new(type: WRITE, location: T.must(other.name_loc)) if other.name
|
74
|
+
when YARP::ConstantPathWriteNode, YARP::ConstantPathOrWriteNode, YARP::ConstantPathAndWriteNode,
|
75
|
+
YARP::ConstantPathOperatorWriteNode
|
76
|
+
|
77
|
+
HighlightMatch.new(type: WRITE, location: other.target.location)
|
78
|
+
when YARP::LocalVariableReadNode, YARP::ConstantPathNode, YARP::ConstantReadNode,
|
79
|
+
YARP::InstanceVariableReadNode, YARP::ClassVariableReadNode, YARP::GlobalVariableReadNode
|
80
|
+
|
81
|
+
HighlightMatch.new(type: READ, location: other.location)
|
82
|
+
when YARP::ClassNode, YARP::ModuleNode
|
83
|
+
HighlightMatch.new(type: WRITE, location: other.constant_path.location)
|
72
84
|
end
|
73
85
|
end
|
74
86
|
end
|
75
87
|
|
76
|
-
sig { params(node:
|
88
|
+
sig { params(node: YARP::Node).returns(T.nilable(String)) }
|
77
89
|
def value(node)
|
78
90
|
case node
|
79
|
-
when
|
80
|
-
|
81
|
-
|
82
|
-
node.
|
83
|
-
when
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
91
|
+
when YARP::ConstantReadNode, YARP::ConstantPathNode, YARP::BlockArgumentNode, YARP::ConstantTargetNode,
|
92
|
+
YARP::ConstantPathWriteNode, YARP::ConstantPathTargetNode, YARP::ConstantPathOrWriteNode,
|
93
|
+
YARP::ConstantPathOperatorWriteNode, YARP::ConstantPathAndWriteNode
|
94
|
+
node.slice
|
95
|
+
when YARP::GlobalVariableReadNode, YARP::GlobalVariableAndWriteNode, YARP::GlobalVariableOperatorWriteNode,
|
96
|
+
YARP::GlobalVariableOrWriteNode, YARP::GlobalVariableTargetNode, YARP::GlobalVariableWriteNode,
|
97
|
+
YARP::InstanceVariableAndWriteNode, YARP::InstanceVariableOperatorWriteNode,
|
98
|
+
YARP::InstanceVariableOrWriteNode, YARP::InstanceVariableReadNode, YARP::InstanceVariableTargetNode,
|
99
|
+
YARP::InstanceVariableWriteNode, YARP::ConstantAndWriteNode, YARP::ConstantOperatorWriteNode,
|
100
|
+
YARP::ConstantOrWriteNode, YARP::ConstantWriteNode, YARP::ClassVariableAndWriteNode,
|
101
|
+
YARP::ClassVariableOperatorWriteNode, YARP::ClassVariableOrWriteNode, YARP::ClassVariableReadNode,
|
102
|
+
YARP::ClassVariableTargetNode, YARP::ClassVariableWriteNode, YARP::LocalVariableAndWriteNode,
|
103
|
+
YARP::LocalVariableOperatorWriteNode, YARP::LocalVariableOrWriteNode, YARP::LocalVariableReadNode,
|
104
|
+
YARP::LocalVariableTargetNode, YARP::LocalVariableWriteNode, YARP::DefNode, YARP::BlockParameterNode,
|
105
|
+
YARP::KeywordParameterNode, YARP::KeywordRestParameterNode, YARP::OptionalParameterNode,
|
106
|
+
YARP::RequiredParameterNode, YARP::RestParameterNode
|
107
|
+
|
108
|
+
node.name.to_s
|
109
|
+
when YARP::CallNode
|
110
|
+
node.message
|
111
|
+
when YARP::ClassNode, YARP::ModuleNode
|
112
|
+
node.constant_path.slice
|
94
113
|
end
|
95
114
|
end
|
96
115
|
end
|
@@ -20,14 +20,19 @@ module RubyLsp
|
|
20
20
|
extend T::Sig
|
21
21
|
|
22
22
|
MESSAGE = <<~EOS
|
23
|
-
An internal error occurred
|
23
|
+
An internal error occurred %s.
|
24
24
|
Updating to a newer version of RuboCop may solve this.
|
25
25
|
For more details, run RuboCop on the command line.
|
26
26
|
EOS
|
27
27
|
|
28
|
-
sig { params(rubocop_error: RuboCop::ErrorWithAnalyzedFileLocation).void }
|
28
|
+
sig { params(rubocop_error: T.any(RuboCop::ErrorWithAnalyzedFileLocation, StandardError)).void }
|
29
29
|
def initialize(rubocop_error)
|
30
|
-
message =
|
30
|
+
message = case rubocop_error
|
31
|
+
when RuboCop::ErrorWithAnalyzedFileLocation
|
32
|
+
format(MESSAGE, "for the #{rubocop_error.cop.name} cop")
|
33
|
+
when StandardError
|
34
|
+
format(MESSAGE, rubocop_error.message)
|
35
|
+
end
|
31
36
|
super(message)
|
32
37
|
end
|
33
38
|
end
|
@@ -87,7 +92,7 @@ module RubyLsp
|
|
87
92
|
raise Formatting::Error, error.message
|
88
93
|
rescue RuboCop::ValidationError => error
|
89
94
|
raise ConfigurationError, error.message
|
90
|
-
rescue
|
95
|
+
rescue StandardError => error
|
91
96
|
raise InternalRuboCopError, error
|
92
97
|
end
|
93
98
|
|
@@ -9,10 +9,11 @@ module RubyLsp
|
|
9
9
|
|
10
10
|
sig { params(position: Document::PositionShape).returns(T::Boolean) }
|
11
11
|
def cover?(position)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
start_covered = range.start.line < position[:line] ||
|
13
|
+
(range.start.line == position[:line] && range.start.character <= position[:character])
|
14
|
+
end_covered = range.end.line > position[:line] ||
|
15
|
+
(range.end.line == position[:line] && range.end.character >= position[:character])
|
16
|
+
start_covered && end_covered
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
@@ -42,66 +42,11 @@ module RubyLsp
|
|
42
42
|
|
43
43
|
sig do
|
44
44
|
params(
|
45
|
-
node:
|
45
|
+
node: YARP::CallNode,
|
46
46
|
).returns(T::Boolean)
|
47
47
|
end
|
48
48
|
def annotation?(node)
|
49
|
-
|
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
|
-
message = node.message
|
67
|
-
ANNOTATIONS[message.value] unless message.is_a?(Symbol)
|
68
|
-
else
|
69
|
-
T.absurd(node)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
sig do
|
74
|
-
params(receiver: T.any(SyntaxTree::CallNode, SyntaxTree::VCall)).returns(T.nilable(String))
|
75
|
-
end
|
76
|
-
def receiver_name(receiver)
|
77
|
-
case receiver
|
78
|
-
when SyntaxTree::CallNode
|
79
|
-
node_name(receiver.receiver)
|
80
|
-
when SyntaxTree::VCall
|
81
|
-
nil
|
82
|
-
else
|
83
|
-
T.absurd(receiver)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
sig do
|
88
|
-
params(node: T.nilable(SyntaxTree::Node)).returns(T.nilable(String))
|
89
|
-
end
|
90
|
-
def node_name(node)
|
91
|
-
case node
|
92
|
-
when SyntaxTree::VarRef
|
93
|
-
node.value.value
|
94
|
-
when SyntaxTree::CallNode
|
95
|
-
node_name(node.receiver)
|
96
|
-
when SyntaxTree::VCall
|
97
|
-
node_name(node.value)
|
98
|
-
when SyntaxTree::Ident, SyntaxTree::Backtick, SyntaxTree::Const, SyntaxTree::Op
|
99
|
-
node.value
|
100
|
-
when NilClass, SyntaxTree::Node
|
101
|
-
nil
|
102
|
-
else
|
103
|
-
T.absurd(node)
|
104
|
-
end
|
49
|
+
!!ANNOTATIONS[node.name]&.match?(node)
|
105
50
|
end
|
106
51
|
end
|
107
52
|
end
|
@@ -39,12 +39,15 @@ module RubyLsp
|
|
39
39
|
# If the project is using Sorbet, we let Sorbet handle symbols defined inside the project itself and RBIs, but
|
40
40
|
# we still return entries defined in gems to allow developers to jump directly to the source
|
41
41
|
file_path = entry.file_path
|
42
|
-
if DependencyDetector
|
42
|
+
if DependencyDetector.instance.typechecker && bundle_path && !file_path.start_with?(bundle_path) &&
|
43
43
|
!file_path.start_with?(RbConfig::CONFIG["rubylibdir"])
|
44
44
|
|
45
45
|
next
|
46
46
|
end
|
47
47
|
|
48
|
+
# We should never show private symbols when searching the entire workspace
|
49
|
+
next if entry.visibility == :private
|
50
|
+
|
48
51
|
kind = kind_for_entry(entry)
|
49
52
|
loc = entry.location
|
50
53
|
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -86,7 +86,7 @@ module RubyLsp
|
|
86
86
|
@message_dispatcher.join
|
87
87
|
@store.clear
|
88
88
|
|
89
|
-
|
89
|
+
Addon.addons.each(&:deactivate)
|
90
90
|
finalize_request(Result.new(response: nil), request)
|
91
91
|
when "exit"
|
92
92
|
# We return zero if shutdown has already been received or one otherwise as per the recommendation in the spec
|
@@ -153,55 +153,17 @@ module RubyLsp
|
|
153
153
|
error: {
|
154
154
|
code: Constant::ErrorCodes::INTERNAL_ERROR,
|
155
155
|
message: error.inspect,
|
156
|
-
data:
|
156
|
+
data: {
|
157
|
+
errorClass: error.class.name,
|
158
|
+
errorMessage: error.message,
|
159
|
+
backtrace: error.backtrace&.map { |bt| bt.sub(/^#{Dir.home}/, "~") }&.join("\n"),
|
160
|
+
},
|
157
161
|
},
|
158
162
|
)
|
159
163
|
elsif response != VOID
|
160
164
|
@writer.write(id: request[:id], result: response)
|
161
165
|
end
|
162
|
-
|
163
|
-
request_time = result.request_time
|
164
|
-
if request_time
|
165
|
-
@writer.write(method: "telemetry/event", params: telemetry_params(request, request_time, error))
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
sig do
|
171
|
-
params(
|
172
|
-
request: T::Hash[Symbol, T.untyped],
|
173
|
-
request_time: Float,
|
174
|
-
error: T.nilable(Exception),
|
175
|
-
).returns(T::Hash[Symbol, T.any(String, Float)])
|
176
|
-
end
|
177
|
-
def telemetry_params(request, request_time, error)
|
178
|
-
uri = request.dig(:params, :textDocument, :uri)
|
179
|
-
params = {
|
180
|
-
request: request[:method],
|
181
|
-
lspVersion: RubyLsp::VERSION,
|
182
|
-
requestTime: request_time,
|
183
|
-
}
|
184
|
-
|
185
|
-
if error
|
186
|
-
params[:errorClass] = error.class.name
|
187
|
-
params[:errorMessage] = error.message
|
188
|
-
|
189
|
-
log_params = request[:params]
|
190
|
-
params[:params] = log_params.reject { |k, _| k == :textDocument }.to_json if log_params
|
191
|
-
|
192
|
-
backtrace = error.backtrace
|
193
|
-
params[:backtrace] = backtrace.map { |bt| bt.sub(/^#{Dir.home}/, "~") }.join("\n") if backtrace
|
194
166
|
end
|
195
|
-
|
196
|
-
if uri
|
197
|
-
home = URI::Generic.from_path(path: Dir.home)
|
198
|
-
|
199
|
-
parsed_uri = URI(uri)
|
200
|
-
path = parsed_uri.path
|
201
|
-
params[:uri] = path ? path.sub(T.must(home.path), "~") : parsed_uri.opaque
|
202
|
-
end
|
203
|
-
|
204
|
-
params
|
205
167
|
end
|
206
168
|
end
|
207
169
|
end
|
@@ -175,20 +175,24 @@ module RubyLsp
|
|
175
175
|
# weren't a part of the Gemfile, then we need to run `bundle install` for the first time to generate the
|
176
176
|
# Gemfile.lock with them included or else Bundler will complain that they're missing. We can only update if the
|
177
177
|
# custom `.ruby-lsp/Gemfile.lock` already exists and includes both gems
|
178
|
-
command = +""
|
179
178
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
179
|
+
# When not updating, we run `(bundle check || bundle install)`
|
180
|
+
# When updating, we run `((bundle check && bundle update ruby-lsp debug) || bundle install)`
|
181
|
+
command = +"(bundle check"
|
182
|
+
|
183
|
+
if should_bundle_update?
|
184
184
|
# If ruby-lsp or debug are not in the Gemfile, try to update them to the latest version
|
185
|
-
command
|
185
|
+
command.prepend("(")
|
186
|
+
command << " && bundle update "
|
186
187
|
command << "ruby-lsp " unless @dependencies["ruby-lsp"]
|
187
|
-
command << "debug
|
188
|
+
command << "debug" unless @dependencies["debug"]
|
189
|
+
command << ")"
|
188
190
|
|
189
191
|
@last_updated_path.write(Time.now.iso8601)
|
190
192
|
end
|
191
193
|
|
194
|
+
command << " || bundle install) "
|
195
|
+
|
192
196
|
# Redirect stdout to stderr to prevent going into an infinite loop. The extension might confuse stdout output with
|
193
197
|
# responses
|
194
198
|
command << "1>&2"
|
@@ -200,10 +204,17 @@ module RubyLsp
|
|
200
204
|
end
|
201
205
|
|
202
206
|
sig { returns(T::Boolean) }
|
203
|
-
def
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
+
def should_bundle_update?
|
208
|
+
# If both `ruby-lsp` and `debug` are in the Gemfile, then we shouldn't try to upgrade them or else it will produce
|
209
|
+
# version control changes
|
210
|
+
return false if @dependencies["ruby-lsp"] && @dependencies["debug"]
|
211
|
+
|
212
|
+
# If the custom lockfile doesn't include either the `ruby-lsp` or `debug`, we need to run bundle install before
|
213
|
+
# updating
|
214
|
+
return false if custom_bundle_dependencies["ruby-lsp"].nil? || custom_bundle_dependencies["debug"].nil?
|
215
|
+
|
216
|
+
# If the last updated file doesn't exist or was updated more than 4 hours ago, we should update
|
217
|
+
!@last_updated_path.exist? || Time.parse(@last_updated_path.read) < (Time.now - FOUR_HOURS)
|
207
218
|
end
|
208
219
|
end
|
209
220
|
end
|
data/lib/ruby_lsp/utils.rb
CHANGED
@@ -41,20 +41,10 @@ module RubyLsp
|
|
41
41
|
sig { returns(T.nilable(Exception)) }
|
42
42
|
attr_reader :error
|
43
43
|
|
44
|
-
sig {
|
45
|
-
|
46
|
-
|
47
|
-
sig do
|
48
|
-
params(
|
49
|
-
response: T.untyped,
|
50
|
-
error: T.nilable(Exception),
|
51
|
-
request_time: T.nilable(Float),
|
52
|
-
).void
|
53
|
-
end
|
54
|
-
def initialize(response:, error: nil, request_time: nil)
|
44
|
+
sig { params(response: T.untyped, error: T.nilable(Exception)).void }
|
45
|
+
def initialize(response:, error: nil)
|
55
46
|
@response = response
|
56
47
|
@error = error
|
57
|
-
@request_time = request_time
|
58
48
|
end
|
59
49
|
end
|
60
50
|
|