Skip to content

Send CompletionContext so servers return trigger-character completions#193

Merged
shugo merged 2 commits intomainfrom
fix/lsp-completion-trigger-context
Feb 19, 2026
Merged

Send CompletionContext so servers return trigger-character completions#193
shugo merged 2 commits intomainfrom
fix/lsp-completion-trigger-context

Conversation

@shugo
Copy link
Owner

@shugo shugo commented Feb 19, 2026

Without a context, some LSP servers don't return member completions when the cursor is right after a trigger character (e.g. "window."). Now lsp_completion checks completionProvider.triggerCharacters and:

  • sends triggerKind=2 + triggerCharacter when prefix is empty and the character before start_point is a trigger character (e.g. ".")
  • sends triggerKind=1 (Invoked) otherwise

Using triggerKind=2 only when prefix is empty avoids returning the full unfiltered member list while the user is mid-identifier.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves LSP completion results when invoking completion immediately after a server-defined trigger character (e.g., window.) by sending CompletionContext so servers can return member completions in that scenario.

Changes:

  • Extend LSP::Client#completion to accept and send an optional context parameter.
  • Update lsp_completion to detect trigger characters from completionProvider.triggerCharacters and send triggerKind=2 + triggerCharacter when appropriate; otherwise send triggerKind=1.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
lib/textbringer/lsp/client.rb Adds optional context to the completion request payload.
lib/textbringer/commands/lsp.rb Computes CompletionContext based on trigger characters and passes it through to the client completion request.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 52 to 56
context = if prefix.empty? && trigger_chars.include?(char_before_start)
{ triggerKind: 2, triggerCharacter: char_before_start }
else
{ triggerKind: 1 }
end
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

triggerKind is currently set using bare integers (1/2). Consider introducing named constants or at least inline comments (as done for signature help below) so it's clear these correspond to LSP CompletionTriggerKind::Invoked and ::TriggerCharacter and to avoid magic numbers.

Copilot uses AI. Check for mistakes.
Comment on lines 43 to 59
# Determine trigger context: if the character immediately before start_point
# is a completion trigger character, inform the server so it returns
# member completions (e.g. after ".").
trigger_chars = client.server_capabilities
.dig("completionProvider", "triggerCharacters") || []
char_before_start = buffer.save_point {
buffer.goto_char(start_point)
buffer.point > 0 ? (buffer.backward_char; buffer.char_after) : nil
}
context = if prefix.empty? && trigger_chars.include?(char_before_start)
{ triggerKind: 2, triggerCharacter: char_before_start }
else
{ triggerKind: 1 }
end

# Request completion
client.completion(uri: uri, line: line, character: character) do |items, error|
client.completion(uri: uri, line: line, character: character, context: context) do |items, error|
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new trigger-context selection logic (prefix empty + previous character is in completionProvider.triggerCharacters => triggerKind: 2) is behavioral and easy to regress. Please add tests that exercise both branches (trigger-character vs invoked), ideally stubbing a client with server_capabilities and asserting the context sent to client.completion.

Copilot uses AI. Check for mistakes.
Comment on lines +130 to +137
def completion(uri:, line:, character:, context: nil, &callback)
return unless @initialized

params = {
textDocument: { uri: uri },
position: { line: line, character: character }
}
params[:context] = context if context
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

completion now supports sending CompletionContext (via the new context: kwarg), but the client capabilities sent during initialize don't advertise textDocument.completion.contextSupport. Some LSP servers gate their use of completion context on this capability, so this change may not take effect (or may behave inconsistently) unless contextSupport: true is added under textDocument: { completion: ... } in client_capabilities (and the corresponding capability test updated).

Suggested change
def completion(uri:, line:, character:, context: nil, &callback)
return unless @initialized
params = {
textDocument: { uri: uri },
position: { line: line, character: character }
}
params[:context] = context if context
def completion(uri:, line:, character:, &callback)
return unless @initialized
params = {
textDocument: { uri: uri },
position: { line: line, character: character }
}

Copilot uses AI. Check for mistakes.
shugo and others added 2 commits February 19, 2026 11:01
Without a context, some LSP servers don't return member completions
when the cursor is right after a trigger character (e.g. "window.").
Now lsp_completion checks completionProvider.triggerCharacters and:
- sends triggerKind=2 + triggerCharacter when prefix is empty and the
  character before start_point is a trigger character (e.g. ".")
- sends triggerKind=1 (Invoked) otherwise

Using triggerKind=2 only when prefix is empty avoids returning the
full unfiltered member list while the user is mid-identifier.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add inline comments (Invoked / TriggerCharacter) to triggerKind values
- Extract context-building into lsp_completion_context helper method
- Add contextSupport: true to textDocument.completion client capabilities
- Add test_client_capabilities assertion for completion contextSupport
- Add test/textbringer/commands/test_lsp.rb with 6 tests covering both
  branches of the trigger context selection logic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@shugo shugo force-pushed the fix/lsp-completion-trigger-context branch from f81f766 to 8b281c5 Compare February 19, 2026 02:01
@shugo shugo merged commit e371e7b into main Feb 19, 2026
7 checks passed
@shugo shugo deleted the fix/lsp-completion-trigger-context branch February 19, 2026 02:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants