Class: RubyLsp::Requests::CompletionResolve

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

Overview

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.

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?

Constructor Details

#initialize(global_state, item) ⇒ CompletionResolve

: (GlobalState global_state, Hash[Symbol, untyped] item) -> void



24
25
26
27
28
# File 'lib/ruby_lsp/requests/completion_resolve.rb', line 24

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

Instance Method Details

#performObject

: -> Hash[Symbol, untyped]



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

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 behavior 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
  return keyword_resolve(@item) if @item.dig(:data, :keyword)

  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.is_a?(RubyIndexer::Entry::MethodAlias) || entry.is_a?(RubyIndexer::Entry::ClassVariable)) &&
        entry.owner&.name == owner_name
    end
  end

  first_entry = entries.first #: as !nil

  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