Class: RubyLsp::Requests::CompletionResolve

Inherits:
Request
  • Object
show all
Extended by:
T::Sig
Includes:
Support::Common
Defined in:
lib/ruby_lsp/requests/completion_resolve.rb

Overview

![Completion resolve demo](../../completion_resolve.gif)

The [completionItem/resolve](microsoft.github.io/language-server-protocol/specification#completionItem_resolve) request provides additional information about the currently selected completion. Specifically, the ‘labelDetails` and `documentation` fields are provided, which are omitted from the completion items returned by `textDocument/completion`.

The ‘labelDetails` field lists the files where the completion item is defined, and the `documentation` field includes any available documentation for those definitions.

At most 10 definitions are included, to ensure low latency during request processing and rendering the completion item.

# Example

“‘ruby A # -> as the user cycles through completion items, the documentation will be resolved and displayed “`

Constant Summary collapse

MAX_DOCUMENTATION_ENTRIES =

set a limit on the number of documentation entries returned, to avoid rendering performance issues github.com/Shopify/ruby-lsp/pull/1798

10

Instance Method Summary collapse

Methods included from Support::Common

#categorized_markdown_from_index_entries, #constant_name, #create_code_lens, #each_constant_path_part, #kind_for_entry, #markdown_from_index_entries, #namespace_constant_name, #not_in_dependencies?, #range_from_location, #range_from_node, #self_receiver?, #sorbet_level_true_or_higher?, #visible?

Constructor Details

#initialize(global_state, item) ⇒ CompletionResolve

Returns a new instance of CompletionResolve.



33
34
35
36
37
# File 'lib/ruby_lsp/requests/completion_resolve.rb', line 33

def initialize(global_state, item)
  super()
  @index = T.let(global_state.index, RubyIndexer::Index)
  @item = item
end

Instance Method Details

#performObject



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
# File 'lib/ruby_lsp/requests/completion_resolve.rb', line 40

def perform
  return @item if @item.dig(:data, :skip_resolve)

  # Based on the spec https://microsoft.github.io/language-server-protocol/specification#textDocument_completion,
  # a completion resolve request must always return the original completion item without modifying ANY fields
  # other than detail and documentation (NOT labelDetails). If we modify anything, the completion behaviour might
  # be broken.
  #
  # For example, forgetting to return the `insertText` included in the original item will make the editor use the
  # `label` for the text edit instead
  label = @item[:label].dup
  entries = @index[label] || []

  owner_name = @item.dig(:data, :owner_name)

  if owner_name
    entries = entries.select do |entry|
      (entry.is_a?(RubyIndexer::Entry::Member) || entry.is_a?(RubyIndexer::Entry::InstanceVariable)) &&
        entry.owner&.name == owner_name
    end
  end

  first_entry = T.must(entries.first)

  if first_entry.is_a?(RubyIndexer::Entry::Member)
    label = +"#{label}#{first_entry.decorated_parameters}"
    label << first_entry.formatted_signatures
  end

  guessed_type = @item.dig(:data, :guessed_type)

  extra_links = if guessed_type
    label << "\n\nGuessed receiver: #{guessed_type}"
    "[Learn more about guessed types](#{GUESSED_TYPES_URL})"
  end

  @item[:documentation] = Interface::MarkupContent.new(
    kind: "markdown",
    value: markdown_from_index_entries(label, entries, MAX_DOCUMENTATION_ENTRIES, extra_links: extra_links),
  )

  @item
end