Class: RubyLsp::Requests::Completion

Inherits:
Request
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/ruby_lsp/requests/completion.rb

Overview

![Completion demo](../../completion.gif)

The [completion](microsoft.github.io/language-server-protocol/specification#textDocument_completion) suggests possible completions according to what the developer is typing.

Currently supported targets:

  • Classes

  • Modules

  • Constants

  • Require paths

  • Methods invoked on self only

  • Instance variables

# Example

“‘ruby require “ruby_lsp/requests” # –> completion: suggests `base_request`, `code_actions`, …

RubyLsp::Requests

# –> completion: suggests ‘Completion`, `Hover`, …

“‘

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, global_state, params, sorbet_level, dispatcher) ⇒ Completion

Returns a new instance of Completion.



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
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/ruby_lsp/requests/completion.rb', line 56

def initialize(document, global_state, params, sorbet_level, dispatcher)
  super()
  @target = T.let(nil, T.nilable(Prism::Node))
  @dispatcher = dispatcher
  # Completion always receives the position immediately after the character that was just typed. Here we adjust it
  # back by 1, so that we find the right node
  char_position = document.create_scanner.find_char_position(params[:position]) - 1
  node_context = RubyDocument.locate(
    document.parse_result.value,
    char_position,
    node_types: [
      Prism::CallNode,
      Prism::ConstantReadNode,
      Prism::ConstantPathNode,
      Prism::InstanceVariableReadNode,
      Prism::InstanceVariableAndWriteNode,
      Prism::InstanceVariableOperatorWriteNode,
      Prism::InstanceVariableOrWriteNode,
      Prism::InstanceVariableTargetNode,
      Prism::InstanceVariableWriteNode,
    ],
  )
  @response_builder = T.let(
    ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem].new,
    ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem],
  )

  Listeners::Completion.new(
    @response_builder,
    global_state,
    node_context,
    sorbet_level,
    dispatcher,
    document.uri,
    params.dig(:context, :triggerCharacter),
  )

  Addon.addons.each do |addon|
    addon.create_completion_listener(@response_builder, node_context, dispatcher, document.uri)
  end

  matched = node_context.node
  parent = node_context.parent
  return unless matched && parent

  @target = if parent.is_a?(Prism::ConstantPathNode) && matched.is_a?(Prism::ConstantReadNode)
    parent
  else
    matched
  end
end

Class Method Details

.providerObject



36
37
38
39
40
41
42
43
44
# File 'lib/ruby_lsp/requests/completion.rb', line 36

def provider
  Interface::CompletionOptions.new(
    resolve_provider: true,
    trigger_characters: ["/", "\"", "'", ":", "@", "."],
    completion_item: {
      labelDetailsSupport: true,
    },
  )
end

Instance Method Details

#performObject



109
110
111
112
113
114
# File 'lib/ruby_lsp/requests/completion.rb', line 109

def perform
  return [] unless @target

  @dispatcher.dispatch_once(@target)
  @response_builder.response
end