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
78
79
# 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

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

  @item
end