-
Notifications
You must be signed in to change notification settings - Fork 183
/
Copy pathhover.rb
93 lines (78 loc) · 2.82 KB
/
hover.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# typed: strict
# frozen_string_literal: true
require "ruby_lsp/listeners/hover"
module RubyLsp
module Requests
# 
#
# The [hover request](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover)
# displays the documentation for the symbol currently under the cursor.
#
# # Example
#
# ```ruby
# String # -> Hovering over the class reference will show all declaration locations and the documentation
# ```
class Hover < Request
extend T::Sig
extend T::Generic
class << self
extend T::Sig
sig { returns(Interface::HoverOptions) }
def provider
Interface::HoverOptions.new
end
end
ResponseType = type_member { { fixed: T.nilable(Interface::Hover) } }
sig do
params(
document: Document,
global_state: GlobalState,
position: T::Hash[Symbol, T.untyped],
dispatcher: Prism::Dispatcher,
sorbet_level: RubyDocument::SorbetLevel,
).void
end
def initialize(document, global_state, position, dispatcher, sorbet_level)
super()
node_context = document.locate_node(position, node_types: Listeners::Hover::ALLOWED_TARGETS)
target = node_context.node
parent = node_context.parent
if (Listeners::Hover::ALLOWED_TARGETS.include?(parent.class) &&
!Listeners::Hover::ALLOWED_TARGETS.include?(target.class)) ||
(parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
target = determine_target(
T.must(target),
T.must(parent),
position,
)
elsif target.is_a?(Prism::CallNode) && target.name != :require && target.name != :require_relative &&
!covers_position?(target.message_loc, position)
target = nil
end
# Don't need to instantiate any listeners if there's no target
return unless target
@target = T.let(target, T.nilable(Prism::Node))
uri = document.uri
@response_builder = T.let(ResponseBuilders::Hover.new, ResponseBuilders::Hover)
Listeners::Hover.new(@response_builder, global_state, uri, node_context, dispatcher, sorbet_level)
Addon.addons.each do |addon|
addon.create_hover_listener(@response_builder, node_context, dispatcher)
end
@dispatcher = dispatcher
end
sig { override.returns(ResponseType) }
def perform
return unless @target
@dispatcher.dispatch_once(@target)
return if @response_builder.empty?
Interface::Hover.new(
contents: Interface::MarkupContent.new(
kind: "markdown",
value: @response_builder.response,
),
)
end
end
end
end