Skip to content

Commit b4a4211

Browse files
committed
chore(lsp): move autocomplete to the lsp
1 parent fceda92 commit b4a4211

4 files changed

Lines changed: 65 additions & 9 deletions

File tree

sqlmesh/lsp/main.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
ApiResponseGetLineage,
2121
ApiResponseGetModels,
2222
)
23+
from sqlmesh.lsp.completions import get_sql_completions
2324
from sqlmesh.lsp.context import (
2425
LSPContext,
2526
ModelTarget,
@@ -456,6 +457,47 @@ def workspace_diagnostic(
456457
)
457458
return types.WorkspaceDiagnosticReport(items=[])
458459

460+
@self.server.feature(types.TEXT_DOCUMENT_COMPLETION)
461+
def completion(
462+
ls: LanguageServer, params: types.CompletionParams
463+
) -> t.Optional[types.CompletionList]:
464+
"""Handle completion requests from the client."""
465+
try:
466+
uri = URI(params.text_document.uri)
467+
context = self._context_get_or_load(uri)
468+
469+
# Get completions using the existing completions module
470+
completion_response = context.get_autocomplete(uri)
471+
472+
completion_items = []
473+
# Add model completions
474+
for model in completion_response.models:
475+
completion_items.append(
476+
types.CompletionItem(
477+
label=model,
478+
kind=types.CompletionItemKind.Reference,
479+
detail="SQLMesh Model",
480+
)
481+
)
482+
# Add keyword completions
483+
for keyword in completion_response.keywords:
484+
completion_items.append(
485+
types.CompletionItem(
486+
label=keyword,
487+
kind=types.CompletionItemKind.Keyword,
488+
detail="SQL Keyword",
489+
)
490+
)
491+
492+
return types.CompletionList(
493+
is_incomplete=False,
494+
items=completion_items,
495+
)
496+
497+
except Exception as e:
498+
get_sql_completions(None, URI(params.text_document.uri))
499+
return None
500+
459501
def _get_diagnostics_for_uri(self, uri: URI) -> t.Tuple[t.List[types.Diagnostic], int]:
460502
"""Get diagnostics for a specific URI, returning (diagnostics, result_id).
461503

vscode/extension/src/extension.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,6 @@ export async function activate(context: vscode.ExtensionContext) {
8484
),
8585
)
8686

87-
context.subscriptions.push(
88-
vscode.languages.registerCompletionItemProvider(
89-
selector,
90-
completionProvider(lspClient),
91-
),
92-
)
93-
9487
// Register the webview
9588
const lineagePanel = new LineagePanel(context.extensionUri, lspClient)
9689
context.subscriptions.push(
@@ -185,6 +178,15 @@ export async function activate(context: vscode.ExtensionContext) {
185178
context.subscriptions.push(lspClient)
186179
}
187180

181+
if (lspClient && !lspClient.hasCompletionCapability()) {
182+
context.subscriptions.push(
183+
vscode.languages.registerCompletionItemProvider(
184+
selector,
185+
completionProvider(lspClient),
186+
),
187+
)
188+
}
189+
188190
traceInfo('Extension activated')
189191
}
190192

vscode/extension/src/lsp/lsp.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ export class LSPClient implements Disposable {
2121
this.client = undefined
2222
}
2323

24+
public hasCompletionCapability(): boolean {
25+
if (!this.client) {
26+
traceError('LSP client is not initialized')
27+
return false
28+
}
29+
const capabilities = this.client.initializeResult?.capabilities
30+
const completion = capabilities?.completionProvider
31+
return completion !== undefined
32+
}
33+
2434
public async start(): Promise<Result<undefined, ErrorType>> {
2535
if (!outputChannel) {
2636
outputChannel = window.createOutputChannel('sqlmesh-lsp')

vscode/extension/tests/completions.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@ test('Autocomplete for model names', async () => {
3838
await window.keyboard.press('Enter')
3939

4040
// Type the beginning of sushi.customers to trigger autocomplete
41-
await window.keyboard.type('sushi.cus')
41+
await window.keyboard.type('sushi.waiter_as_customer')
4242

4343
// Wait a moment for autocomplete to appear
4444
await window.waitForTimeout(500)
4545

4646
// Check if the autocomplete suggestion for sushi.customers is visible
47-
await expect(window.locator('text=sushi.customers')).toBeVisible()
47+
expect(
48+
await window.locator('text=sushi.waiter_as_customer_by_day').count(),
49+
).toBe(1)
4850

4951
await close()
5052
} finally {

0 commit comments

Comments
 (0)