Class: Rigor::LanguageServer::CompletionProvider

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/language_server/completion_provider.rb

Overview

Answers ‘textDocument/completion` requests. v1 (slice 5) ships method completion for `obj.|`: when the cursor sits on a `CallNode` with a known-type receiver, the provider enumerates the receiver’s RBS-known methods and returns each as an LSP ‘CompletionItem`.

Constant-path completion (slice 6), Union / Intersection / Refined / Shape receiver handling (slice 7), and parse-recovery fallback for malformed buffers (slice 8) extend this v1 floor.

LSP ‘CompletionItemKind` values used:

  • 2 = Method

Slice 6 will add 7 (Class), 9 (Module), 21 (Constant).

Constant Summary collapse

KIND_METHOD =

rubocop:disable Metrics/ClassLength

2
KIND_FIELD =
5
KIND_CLASS =
7
KIND_MODULE =
9
KIND_CONSTANT =
21

Instance Method Summary collapse

Constructor Details

#initialize(buffer_table:, project_context:) ⇒ CompletionProvider

Returns a new instance of CompletionProvider.



44
45
46
47
# File 'lib/rigor/language_server/completion_provider.rb', line 44

def initialize(buffer_table:, project_context:)
  @buffer_table = buffer_table
  @project_context = project_context
end

Instance Method Details

#provide(uri:, line:, character:, trigger_character: nil) ⇒ Array<Hash>?

Returns LSP ‘CompletionItem[]` or nil when the cursor isn’t at a position the provider can enumerate completions for. Returning nil maps to ‘result: null` per the LSP spec — clients treat it as “no completions available,” distinct from `[]` which means “we tried and got nothing”.

Returns:

  • (Array<Hash>, nil)

    LSP ‘CompletionItem[]` or nil when the cursor isn’t at a position the provider can enumerate completions for. Returning nil maps to ‘result: null` per the LSP spec — clients treat it as “no completions available,” distinct from `[]` which means “we tried and got nothing”.



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
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/rigor/language_server/completion_provider.rb', line 55

def provide(uri:, line:, character:, trigger_character: nil)
  _ = trigger_character # Trigger info logged-not-routed in v1.
  path = Uri.to_path(uri)
  return nil if path.nil?

  entry = @buffer_table[uri]
  return nil if entry.nil?

  # Slice B4 — parse recovery. The common mid-edit buffer
  # (`obj.` / `Foo::`) doesn't parse cleanly; try inserting
  # a sentinel name at the cursor before falling through.
  bytes_to_parse, locate_at = parse_attempt_bytes(entry.bytes, line, character)
  parse_result = Prism.parse(bytes_to_parse, 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.
  node = locate_node(source: bytes_to_parse, root: parse_result.value,
                     line: locate_at[0] + 1, character: locate_at[1] + 1)
  return nil if node.nil?

  case node
  when Prism::CallNode
    # `hash[:|` patches to `hash[:KEY_SENTINEL]`, an index
    # access call whose argument is the sentinel symbol;
    # NodeLocator at the sentinel returns the inner CallNode
    # for `[]`. Hash-key completion wins when the call is an
    # index access on a HashShape carrier; otherwise fall
    # through to method completion.
    hash_key_completion_for(node, parse_result.value, path) ||
      method_completion_for(node, parse_result.value, path)
  when Prism::SymbolNode
    # The sentinel symbol's NodeLocator hit; walk up via the
    # AST to find the enclosing `[]` call.
    hash_key_completion_for_symbol(node, parse_result.value, path)
  when Prism::ConstantPathNode
    constant_path_completion_for(node, path)
  end
end