Class: Rigor::LanguageServer::HoverProvider
- Inherits:
-
Object
- Object
- Rigor::LanguageServer::HoverProvider
- Defined in:
- lib/rigor/language_server/hover_provider.rb
Overview
Answers ‘textDocument/hover` requests by running the same NodeLocator + ScopeIndexer + `Scope#type_of` chain that `rigor type-of` already drives. The LSP wraps the result in a `Hover` payload with markdown contents.
Per LSP spec § “Position”:
-
‘line` and `character` are 0-based.
-
‘character` counts UTF-16 code units; v1 emits byte counts for ASCII source (UTF-16 conversion is queued, see design doc § “Open questions”).
Instance Method Summary collapse
-
#initialize(buffer_table:, project_context:, renderer: HoverRenderer.new) ⇒ HoverProvider
constructor
A new instance of HoverProvider.
-
#provide(uri:, line:, character:) ⇒ Hash?
An LSP ‘Hover` payload or nil when no expression sits at the queried position.
Constructor Details
#initialize(buffer_table:, project_context:, renderer: HoverRenderer.new) ⇒ HoverProvider
Returns a new instance of HoverProvider.
25 26 27 28 29 |
# File 'lib/rigor/language_server/hover_provider.rb', line 25 def initialize(buffer_table:, project_context:, renderer: HoverRenderer.new) @buffer_table = buffer_table @project_context = project_context @renderer = renderer end |
Instance Method Details
#provide(uri:, line:, character:) ⇒ Hash?
Returns an LSP ‘Hover` payload or nil when no expression sits at the queried position. Returning nil maps to `result: null` per the LSP spec — clients suppress the hover popup in that case.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/rigor/language_server/hover_provider.rb', line 35 def provide(uri:, line:, character:) path = Uri.to_path(uri) return nil if path.nil? entry = @buffer_table[uri] return nil if entry.nil? parse_result = Prism.parse(entry.bytes, filepath: path, version: @project_context.configuration.target_ruby) return nil unless parse_result.errors.empty? # Rigor's NodeLocator uses 1-based line / column; LSP uses # 0-based. Translate at the boundary. node = locate_node(source: entry.bytes, root: parse_result.value, line: line + 1, character: character + 1) return nil if node.nil? scope = base_scope(path) index = Inference::ScopeIndexer.index(parse_result.value, default_scope: scope) node_scope = index[node] type = node_scope.type_of(node) @renderer.render(node: node, type: type, node_scope_lookup: index) end |