@514labs/moose-lsp 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codeActions.d.ts +7 -2
- package/dist/codeActions.js +57 -10
- package/dist/codeActions.js.map +1 -1
- package/dist/codeActions.test.js +64 -2
- package/dist/codeActions.test.js.map +1 -1
- package/dist/diagnostics.d.ts +9 -1
- package/dist/diagnostics.js +24 -0
- package/dist/diagnostics.js.map +1 -1
- package/dist/diagnostics.test.js +56 -5
- package/dist/diagnostics.test.js.map +1 -1
- package/dist/node_modules/@514labs/moose-sql-validator-wasm/package.json +1 -1
- package/dist/node_modules/@514labs/moose-sql-validator-wasm/pkg/sql_validator_bg.wasm +0 -0
- package/dist/pythonSqlExtractor.js +5 -1
- package/dist/pythonSqlExtractor.js.map +1 -1
- package/dist/server.integration.test.js +222 -26
- package/dist/server.integration.test.js.map +1 -1
- package/dist/server.js +209 -87
- package/dist/server.js.map +1 -1
- package/dist/serverLogic.js +9 -0
- package/dist/serverLogic.js.map +1 -1
- package/dist/serverLogic.test.js +127 -10
- package/dist/serverLogic.test.js.map +1 -1
- package/dist/sqlExtractor.js +43 -12
- package/dist/sqlExtractor.js.map +1 -1
- package/dist/sqlExtractor.test.js +106 -4
- package/dist/sqlExtractor.test.js.map +1 -1
- package/dist/sqlLocations.d.ts +9 -1
- package/dist/sqlLocations.js +9 -1
- package/dist/sqlLocations.js.map +1 -1
- package/dist/sqlLocations.test.js +49 -1
- package/dist/sqlLocations.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.integration.test.ts"],"sourcesContent":["import assert from 'node:assert';\nimport { type ChildProcess, spawn } from 'node:child_process';\nimport * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { after, before, describe, test } from 'node:test';\n\n// ---------------------------------------------------------------------------\n// LSP message types\n// ---------------------------------------------------------------------------\n\ninterface LspMessage {\n jsonrpc: '2.0';\n id?: number;\n method?: string;\n params?: unknown;\n result?: unknown;\n error?: unknown;\n}\n\ninterface LspDiagnostic {\n range: {\n start: { line: number; character: number };\n end: { line: number; character: number };\n };\n severity: number;\n message: string;\n source?: string;\n}\n\ninterface LspCompletionItem {\n label: string;\n kind?: number;\n detail?: string;\n documentation?: { kind: string; value: string } | string;\n insertText?: string;\n insertTextFormat?: number;\n sortText?: string;\n}\n\n// LSP CompletionItemKind constants\nconst CompletionItemKind = {\n Function: 3,\n Keyword: 14,\n TypeParameter: 25,\n Class: 7,\n Constant: 21,\n Property: 10,\n Method: 2,\n} as const;\n\n// ---------------------------------------------------------------------------\n// LspClient — improved with Buffer-based parsing and concurrent request support\n// ---------------------------------------------------------------------------\n\nclass LspClient {\n private process: ChildProcess;\n private buffer = Buffer.alloc(0);\n private messages: LspMessage[] = [];\n private nextId = 1;\n private pendingRequests = new Map<\n number,\n { resolve: (msg: LspMessage) => void; reject: (err: Error) => void }\n >();\n private notificationListeners: Array<(msg: LspMessage) => void> = [];\n private stderrChunks: string[] = [];\n\n constructor(serverPath: string) {\n this.process = spawn('node', [serverPath, '--stdio'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n this.process.stdout?.on('data', (data: Buffer) => {\n this.buffer = Buffer.concat([this.buffer, data]);\n this.parseMessages();\n });\n\n this.process.stderr?.on('data', (data: Buffer) => {\n this.stderrChunks.push(data.toString());\n });\n }\n\n private parseMessages() {\n while (true) {\n const headerEndIndex = this.buffer.indexOf('\\r\\n\\r\\n');\n if (headerEndIndex === -1) break;\n\n const headerStr = this.buffer\n .subarray(0, headerEndIndex)\n .toString('utf-8');\n const match = headerStr.match(/Content-Length:\\s*(\\d+)/i);\n if (!match) break;\n\n const contentLength = parseInt(match[1], 10);\n const contentStart = headerEndIndex + 4;\n const contentEnd = contentStart + contentLength;\n\n if (this.buffer.length < contentEnd) break;\n\n const content = this.buffer\n .subarray(contentStart, contentEnd)\n .toString('utf-8');\n this.buffer = this.buffer.subarray(contentEnd);\n\n const message = JSON.parse(content) as LspMessage;\n this.messages.push(message);\n\n // Resolve pending request if this is a response\n if (message.id !== undefined) {\n const pending = this.pendingRequests.get(message.id);\n if (pending) {\n this.pendingRequests.delete(message.id);\n pending.resolve(message);\n }\n }\n\n // Notify listeners for server-initiated messages (notifications)\n if (message.method && message.id === undefined) {\n for (const listener of this.notificationListeners) {\n listener(message);\n }\n }\n }\n }\n\n send(message: LspMessage): void {\n const content = JSON.stringify(message);\n const header = `Content-Length: ${Buffer.byteLength(content)}\\r\\n\\r\\n`;\n this.process.stdin?.write(header + content);\n }\n\n async request(\n method: string,\n params: unknown,\n timeoutMs = 10000,\n ): Promise<LspMessage> {\n const id = this.nextId++;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(id);\n reject(\n new Error(`Timeout waiting for response to ${method} (id=${id})`),\n );\n }, timeoutMs);\n\n // Check if response already arrived\n const existing = this.messages.find((m) => m.id === id);\n if (existing) {\n clearTimeout(timeout);\n resolve(existing);\n return;\n }\n\n this.pendingRequests.set(id, {\n resolve: (msg) => {\n clearTimeout(timeout);\n resolve(msg);\n },\n reject: (err) => {\n clearTimeout(timeout);\n reject(err);\n },\n });\n\n this.send({ jsonrpc: '2.0', id, method, params });\n });\n }\n\n notify(method: string, params: unknown): void {\n this.send({ jsonrpc: '2.0', method, params });\n }\n\n openDocument(uri: string, languageId: string, text: string): void {\n this.notify('textDocument/didOpen', {\n textDocument: { uri, languageId, version: 1, text },\n });\n }\n\n changeDocument(uri: string, version: number, text: string): void {\n this.notify('textDocument/didChange', {\n textDocument: { uri, version },\n contentChanges: [{ text }],\n });\n }\n\n saveDocument(uri: string): void {\n this.notify('textDocument/didSave', {\n textDocument: { uri },\n });\n }\n\n waitForDiagnostics(uri: string, timeoutMs = 10000): Promise<LspDiagnostic[]> {\n return new Promise((resolve, reject) => {\n const deadline = setTimeout(() => {\n cleanup();\n reject(new Error(`Timeout waiting for diagnostics for ${uri}`));\n }, timeoutMs);\n\n const listener = (msg: LspMessage) => {\n if (msg.method !== 'textDocument/publishDiagnostics') return;\n const params = msg.params as {\n uri: string;\n diagnostics: LspDiagnostic[];\n };\n if (params.uri === uri) {\n cleanup();\n resolve(params.diagnostics);\n }\n };\n\n const cleanup = () => {\n clearTimeout(deadline);\n const idx = this.notificationListeners.indexOf(listener);\n if (idx !== -1) this.notificationListeners.splice(idx, 1);\n };\n\n // Check messages already received\n for (let i = this.messages.length - 1; i >= 0; i--) {\n const m = this.messages[i];\n if (m.method === 'textDocument/publishDiagnostics') {\n const params = m.params as {\n uri: string;\n diagnostics: LspDiagnostic[];\n };\n if (params.uri === uri) {\n clearTimeout(deadline);\n resolve(params.diagnostics);\n return;\n }\n }\n }\n\n this.notificationListeners.push(listener);\n });\n }\n\n /**\n * Waits for fresh diagnostics that arrive after this call.\n * Ignores any diagnostics already in the message buffer.\n */\n waitForFreshDiagnostics(\n uri: string,\n timeoutMs = 10000,\n ): Promise<LspDiagnostic[]> {\n return new Promise((resolve, reject) => {\n const deadline = setTimeout(() => {\n cleanup();\n reject(new Error(`Timeout waiting for fresh diagnostics for ${uri}`));\n }, timeoutMs);\n\n const listener = (msg: LspMessage) => {\n if (msg.method !== 'textDocument/publishDiagnostics') return;\n const params = msg.params as {\n uri: string;\n diagnostics: LspDiagnostic[];\n };\n if (params.uri === uri) {\n cleanup();\n resolve(params.diagnostics);\n }\n };\n\n const cleanup = () => {\n clearTimeout(deadline);\n const idx = this.notificationListeners.indexOf(listener);\n if (idx !== -1) this.notificationListeners.splice(idx, 1);\n };\n\n this.notificationListeners.push(listener);\n });\n }\n\n getMessages(): LspMessage[] {\n return [...this.messages];\n }\n\n getStderr(): string {\n return this.stderrChunks.join('');\n }\n\n getLogMessages(): string[] {\n return this.messages\n .filter((m) => m.method === 'window/logMessage')\n .map((m) => (m.params as { message: string }).message);\n }\n\n close(): void {\n this.process.kill();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst serverPath = path.join(__dirname, '..', 'dist', 'server.js');\n\n/**\n * Given file content and a search string, returns the 0-indexed\n * line/character position immediately after the last character of the match.\n */\nfunction cursorAfter(\n fileContent: string,\n searchText: string,\n): { line: number; character: number } {\n const idx = fileContent.indexOf(searchText);\n if (idx === -1) {\n throw new Error(`cursorAfter: \"${searchText}\" not found in content`);\n }\n const endIdx = idx + searchText.length;\n const before = fileContent.slice(0, endIdx);\n const lines = before.split('\\n');\n return {\n line: lines.length - 1,\n character: lines[lines.length - 1].length,\n };\n}\n\nasync function initializeClient(\n client: LspClient,\n rootUri: string,\n snippetSupport = true,\n): Promise<LspMessage> {\n const response = await client.request('initialize', {\n processId: null,\n rootUri,\n capabilities: {\n textDocument: {\n completion: {\n completionItem: {\n snippetSupport,\n },\n },\n synchronization: {\n didSave: true,\n },\n },\n },\n });\n client.notify('initialized', {});\n return response;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture: TypeScript project\n// ---------------------------------------------------------------------------\n\nconst TS_TEST_FILE_CONTENT = `import { sql } from '@514labs/moose-lib';\n\n// Valid SQL — should produce no diagnostics\nconst valid = sql\\`SELECT count() FROM users\\`;\n\n// Invalid SQL — should produce an error diagnostic\nconst invalid = sql\\`SELCT * FROM users\\`;\n\n// Completions: default context (cursor after \"SELECT \")\nconst comp1 = sql\\`SELECT \\`;\n\n// Context-aware: ENGINE =\nconst engine = sql\\`CREATE TABLE t ENGINE = \\`;\n\n// Context-aware: FORMAT\nconst format = sql\\`SELECT * FORMAT \\`;\n\n// Context-aware: SETTINGS\nconst settings = sql\\`SELECT * SETTINGS \\`;\n\n// Context-aware: column definition (data types)\nconst coldef = sql\\`CREATE TABLE t (id \\`;\n\n// Context-aware: FROM (table functions)\nconst fromCtx = sql\\`SELECT * FROM \\`;\n\n// Hover targets\nconst hover = sql\\`SELECT count() FROM users WHERE toUInt32(id) > 0\\`;\n\n// Format SQL target (lowercase)\nconst fmt = sql\\`select * from users where id = 1\\`;\n\n// Combinators\nconst comb = sql\\`SELECT sumIf(amount, active), countIf(status) FROM orders\\`;\n\n// Prefix filtering\nconst prefix = sql\\`SELECT cou\\`;\n\n// Combinator prefix filtering\nconst combPrefix = sql\\`SELECT sum\\`;\n\n// Default context (empty SQL — triggers Default completions with all kinds)\nconst defaultCtx = sql\\`\\`;\n`;\n\nasync function createTsFixture(): Promise<string> {\n const tmpDir = await fs.mkdtemp(\n path.join(os.tmpdir(), 'moose-lsp-integ-ts-'),\n );\n\n // package.json\n await fs.writeFile(\n path.join(tmpDir, 'package.json'),\n JSON.stringify({\n name: 'test-moose-ts',\n dependencies: { '@514labs/moose-lib': '*' },\n }),\n );\n\n // tsconfig.json\n await fs.writeFile(\n path.join(tmpDir, 'tsconfig.json'),\n JSON.stringify({\n compilerOptions: {\n target: 'ES2020',\n module: 'commonjs',\n strict: true,\n esModuleInterop: true,\n moduleResolution: 'node',\n },\n include: ['app/**/*.ts'],\n }),\n );\n\n // Minimal moose-lib shim\n const mooseLibDir = path.join(\n tmpDir,\n 'node_modules',\n '@514labs',\n 'moose-lib',\n );\n await fs.mkdir(mooseLibDir, { recursive: true });\n await fs.writeFile(\n path.join(mooseLibDir, 'package.json'),\n JSON.stringify({\n name: '@514labs/moose-lib',\n main: 'index.js',\n types: 'index.d.ts',\n }),\n );\n await fs.writeFile(\n path.join(mooseLibDir, 'index.js'),\n 'module.exports.sql = function sql() { return \"\"; };\\n',\n );\n await fs.writeFile(\n path.join(mooseLibDir, 'index.d.ts'),\n 'export declare function sql(strings: TemplateStringsArray, ...values: unknown[]): string;\\n',\n );\n\n // Test TypeScript file\n const appDir = path.join(tmpDir, 'app');\n await fs.mkdir(appDir, { recursive: true });\n await fs.writeFile(path.join(appDir, 'test.ts'), TS_TEST_FILE_CONTENT);\n\n return tmpDir;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture: Python project\n// ---------------------------------------------------------------------------\n\nconst PY_TEST_FILE_CONTENT = `from moose_lib import sql\n\n# Invalid SQL\nquery = sql(\"SELCT * FROM users\")\n`;\n\nasync function createPyFixture(): Promise<string> {\n const tmpDir = await fs.mkdtemp(\n path.join(os.tmpdir(), 'moose-lsp-integ-py-'),\n );\n\n await fs.writeFile(\n path.join(tmpDir, 'pyproject.toml'),\n `[project]\\nname = \"test-moose-py\"\\ndependencies = [\"moose-lib\"]\\n`,\n );\n\n const appDir = path.join(tmpDir, 'app');\n await fs.mkdir(appDir, { recursive: true });\n await fs.writeFile(path.join(appDir, 'test.py'), PY_TEST_FILE_CONTENT);\n\n return tmpDir;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture: TypeScript project with docker-compose (version detection)\n// ---------------------------------------------------------------------------\n\nasync function createTsFixtureWithDockerCompose(\n chVersion: string,\n): Promise<string> {\n const tmpDir = await createTsFixture();\n\n await fs.writeFile(\n path.join(tmpDir, 'docker-compose.dev.override.yaml'),\n `services:\\n clickhousedb:\\n image: clickhouse/clickhouse-server:${chVersion}\\n`,\n );\n\n return tmpDir;\n}\n\n// ===========================================================================\n// TEST SUITES\n// ===========================================================================\n\n// ---------------------------------------------------------------------------\n// 1. TypeScript features (single server)\n// ---------------------------------------------------------------------------\n\ndescribe('TypeScript LSP features', () => {\n let client: LspClient;\n let tmpDir: string;\n const tsFileUri = () => `file://${path.join(tmpDir, 'app', 'test.ts')}`;\n\n before(async () => {\n tmpDir = await createTsFixture();\n client = new LspClient(serverPath);\n await initializeClient(client, `file://${tmpDir}`);\n // Open the test file — triggers initial validation\n client.openDocument(tsFileUri(), 'typescript', TS_TEST_FILE_CONTENT);\n // Wait for the initial diagnostics to arrive\n await client.waitForDiagnostics(tsFileUri());\n });\n\n after(async () => {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n });\n\n // ---- Feature 1: Error Diagnostics ----\n\n test('valid SQL produces no error diagnostics on that template', async () => {\n // The server publishes diagnostics for the whole file.\n // We check that the \"valid\" template line has no diagnostic.\n const validLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const valid'),\n );\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const onValidLine = diagnostics.filter(\n (d) => d.range.start.line === validLine,\n );\n assert.strictEqual(\n onValidLine.length,\n 0,\n `Expected no diagnostics on the valid SQL line, got: ${JSON.stringify(onValidLine)}`,\n );\n });\n\n test('invalid SQL produces an error diagnostic', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const invalidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const invalid'),\n );\n const onInvalidLine = diagnostics.filter(\n (d) => d.range.start.line === invalidLine,\n );\n assert.ok(\n onInvalidLine.length > 0,\n `Expected at least one diagnostic on the invalid SQL line (${invalidLine})`,\n );\n const diag = onInvalidLine[0];\n assert.strictEqual(diag.severity, 1, 'Severity should be Error (1)');\n assert.strictEqual(diag.source, 'moose-sql');\n });\n\n test('fixing SQL clears diagnostic on that line', async () => {\n const invalidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const invalid'),\n );\n\n const fixedContent = TS_TEST_FILE_CONTENT.replace(\n 'SELCT * FROM users',\n 'SELECT * FROM users',\n );\n\n // Send the change, wait for TextDocuments to process it, then save\n client.changeDocument(tsFileUri(), 2, fixedContent);\n await new Promise((r) => setTimeout(r, 100));\n client.saveDocument(tsFileUri());\n\n // Wait for diagnostics that no longer contain the SELCT error\n const deadline = Date.now() + 10000;\n let lastDiagnostics: LspDiagnostic[] = [];\n while (Date.now() < deadline) {\n lastDiagnostics = await client.waitForFreshDiagnostics(tsFileUri());\n const onFixedLine = lastDiagnostics.filter(\n (d) => d.range.start.line === invalidLine && d.source === 'moose-sql',\n );\n if (onFixedLine.length === 0) break;\n // Got stale diagnostics, wait for the next publish\n }\n\n const onFixedLine = lastDiagnostics.filter(\n (d) => d.range.start.line === invalidLine && d.source === 'moose-sql',\n );\n assert.strictEqual(\n onFixedLine.length,\n 0,\n `Expected no diagnostic on the fixed line (${invalidLine}), got: ${JSON.stringify(onFixedLine)}`,\n );\n\n // Restore original content for subsequent tests\n client.changeDocument(tsFileUri(), 3, TS_TEST_FILE_CONTENT);\n await new Promise((r) => setTimeout(r, 100));\n client.saveDocument(tsFileUri());\n await client.waitForFreshDiagnostics(tsFileUri());\n });\n\n // ---- Feature 2: Auto-Complete ----\n\n test('completions inside SQL template returns items', async () => {\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'comp1 = sql`SELECT ');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(Array.isArray(items), 'Result should be an array');\n assert.ok(items.length > 0, 'Should have completion items');\n });\n\n test('SelectClause context returns only functions', async () => {\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'comp1 = sql`SELECT ');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const kinds = new Set(items.map((i) => i.kind));\n assert.ok(\n kinds.has(CompletionItemKind.Function) ||\n kinds.has(CompletionItemKind.Method),\n 'Should include function or method completions',\n );\n // SelectClause context only returns functions (no keywords, data types, etc.)\n for (const item of items) {\n assert.ok(\n item.kind === CompletionItemKind.Function ||\n item.kind === CompletionItemKind.Method,\n `SelectClause should only have functions, got kind=${item.kind} for \"${item.label}\"`,\n );\n }\n });\n\n test('completions outside SQL template returns empty', async () => {\n // Line 0 is the import line — outside any sql template\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: { line: 0, character: 5 },\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(Array.isArray(items), 'Result should be an array');\n assert.strictEqual(\n items.length,\n 0,\n 'Should have no completions outside template',\n );\n });\n\n test('prefix filtering narrows completions', async () => {\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'prefix = sql`SELECT cou');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have some completions');\n const labels = items.map((i) => i.label.toLowerCase());\n assert.ok(\n labels.some((l) => l.startsWith('count')),\n `Should include count*, got: ${labels.slice(0, 10).join(', ')}`,\n );\n // Every item should start with 'cou'\n for (const item of items) {\n assert.ok(\n item.label.toLowerCase().startsWith('cou'),\n `Item \"${item.label}\" should start with \"cou\"`,\n );\n }\n });\n\n // ---- Feature 3: Context-Aware Completions ----\n\n test('ENGINE = context returns table engines', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'engine = sql`CREATE TABLE t ENGINE = ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have engine completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'MergeTree'),\n `Should include MergeTree, got: ${labels.slice(0, 10).join(', ')}`,\n );\n // All items should be engines (Class kind)\n for (const item of items) {\n assert.strictEqual(\n item.kind,\n CompletionItemKind.Class,\n `Engine item \"${item.label}\" should have kind=Class(${CompletionItemKind.Class}), got ${item.kind}`,\n );\n }\n });\n\n test('FORMAT context returns formats', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'format = sql`SELECT * FORMAT ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have format completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'JSON'),\n `Should include JSON, got: ${labels.slice(0, 10).join(', ')}`,\n );\n for (const item of items) {\n assert.strictEqual(\n item.kind,\n CompletionItemKind.Constant,\n `Format item \"${item.label}\" should have kind=Constant(${CompletionItemKind.Constant}), got ${item.kind}`,\n );\n }\n });\n\n test('SETTINGS context returns settings', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'settings = sql`SELECT * SETTINGS ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have settings completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'max_threads'),\n `Should include max_threads, got: ${labels.slice(0, 15).join(', ')}`,\n );\n for (const item of items) {\n assert.strictEqual(\n item.kind,\n CompletionItemKind.Property,\n `Setting item \"${item.label}\" should have kind=Property(${CompletionItemKind.Property}), got ${item.kind}`,\n );\n }\n });\n\n test('column definition context returns data types', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'coldef = sql`CREATE TABLE t (id ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have data type completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'UInt64'),\n `Should include UInt64, got: ${labels.slice(0, 15).join(', ')}`,\n );\n assert.ok(\n labels.some((l) => l === 'String'),\n `Should include String, got: ${labels.slice(0, 15).join(', ')}`,\n );\n });\n\n test('FROM context returns table functions', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'fromCtx = sql`SELECT * FROM ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have FROM completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'file' || l === 'url'),\n `Should include table functions like file/url, got: ${labels.slice(0, 15).join(', ')}`,\n );\n });\n\n // ---- Feature 4: Hover Documentation ----\n\n test('hover on known function shows documentation', async () => {\n // Find \"count\" in the hover line\n const hoverLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`SELECT count()'),\n );\n // \"count\" starts after \"SELECT \"\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[hoverLine];\n const countCharIdx = lineText.indexOf('count');\n assert.ok(countCharIdx !== -1, 'Should find count in hover line');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: hoverLine, character: countCharIdx + 1 },\n });\n assert.ok(response.result, 'Hover should return a result for count');\n const hover = response.result as {\n contents: { kind: string; value: string };\n };\n assert.ok(\n hover.contents.value.length > 0,\n 'Hover content should not be empty',\n );\n assert.strictEqual(\n hover.contents.kind,\n 'markdown',\n 'Hover should be markdown',\n );\n });\n\n test('hover on keyword shows documentation', async () => {\n // Hover over SELECT on the hover line\n const hoverLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`SELECT count()'),\n );\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[hoverLine];\n const selectIdx = lineText.indexOf('SELECT');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: hoverLine, character: selectIdx + 1 },\n });\n assert.ok(\n response.result,\n 'Hover should return a result for SELECT keyword',\n );\n });\n\n test('hover outside SQL template returns null', async () => {\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: 0, character: 5 },\n });\n assert.strictEqual(\n response.result,\n null,\n 'Hover outside template should be null',\n );\n });\n\n test('hover on unknown word returns null', async () => {\n // \"users\" is a table name, not a known ClickHouse function/keyword\n const hoverLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`SELECT count() FROM users'),\n );\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[hoverLine];\n const usersIdx = lineText.indexOf('users');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: hoverLine, character: usersIdx + 1 },\n });\n assert.strictEqual(\n response.result,\n null,\n 'Hover on unknown word should be null',\n );\n });\n\n // ---- Feature 5: Code Actions — Format SQL ----\n\n test('Format SQL action is offered for valid lowercase SQL', async () => {\n const fmtLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`select * from users'),\n );\n\n const response = await client.request('textDocument/codeAction', {\n textDocument: { uri: tsFileUri() },\n range: {\n start: { line: fmtLine, character: 15 },\n end: { line: fmtLine, character: 15 },\n },\n context: { diagnostics: [] },\n });\n\n const actions = response.result as Array<{\n title: string;\n edit?: { changes: Record<string, Array<{ newText: string }>> };\n }>;\n assert.ok(Array.isArray(actions), 'Code actions should be an array');\n const formatAction = actions.find((a) => a.title.includes('Format'));\n assert.ok(formatAction, 'Should offer a Format SQL action');\n });\n\n test('Format SQL produces uppercase keywords', async () => {\n const fmtLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`select * from users'),\n );\n\n const response = await client.request('textDocument/codeAction', {\n textDocument: { uri: tsFileUri() },\n range: {\n start: { line: fmtLine, character: 15 },\n end: { line: fmtLine, character: 15 },\n },\n context: { diagnostics: [] },\n });\n\n const actions = response.result as Array<{\n title: string;\n edit?: { changes: Record<string, Array<{ newText: string }>> };\n }>;\n const formatAction = actions.find((a) => a.title.includes('Format'));\n assert.ok(formatAction?.edit, 'Format action should have an edit');\n const edits = Object.values(\n (\n formatAction as {\n edit: { changes: Record<string, Array<{ newText: string }>> };\n }\n ).edit.changes,\n ).flat();\n assert.ok(edits.length > 0, 'Should have at least one text edit');\n const newText = edits[0].newText;\n assert.ok(\n newText.includes('SELECT') && newText.includes('FROM'),\n `Formatted SQL should contain uppercase keywords, got: ${newText}`,\n );\n });\n\n test('Format SQL not offered for invalid SQL', async () => {\n const invalidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`SELCT * FROM users'),\n );\n\n const response = await client.request('textDocument/codeAction', {\n textDocument: { uri: tsFileUri() },\n range: {\n start: { line: invalidLine, character: 15 },\n end: { line: invalidLine, character: 15 },\n },\n context: { diagnostics: [] },\n });\n\n const actions = response.result as Array<{ title: string }>;\n const formatAction = (actions || []).find((a) =>\n a.title.includes('Format'),\n );\n assert.ok(!formatAction, 'Should NOT offer Format SQL for invalid SQL');\n });\n\n // ---- Feature 8: Aggregate Combinator Functions ----\n\n test('sumIf appears in completions after \"sum\" prefix', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'combPrefix = sql`SELECT sum',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'sumIf'),\n `Should include sumIf combinator, got: ${labels.slice(0, 20).join(', ')}`,\n );\n });\n\n test('combinator function has documentation', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'combPrefix = sql`SELECT sum',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const sumIf = items.find((i) => i.label === 'sumIf');\n assert.ok(sumIf, 'Should have sumIf item');\n assert.ok(sumIf.documentation, 'sumIf should have documentation');\n const docValue =\n typeof sumIf.documentation === 'string'\n ? sumIf.documentation\n : (sumIf.documentation as { value: string }).value;\n assert.ok(\n docValue.toLowerCase().includes('combinator') ||\n docValue.toLowerCase().includes('aggregate') ||\n docValue.toLowerCase().includes('if'),\n `sumIf docs should mention combinator/aggregate, got: ${docValue.slice(0, 200)}`,\n );\n });\n\n test('hover on combinator function shows info', async () => {\n const combLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('countIf(status)'),\n );\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[combLine];\n const countIfIdx = lineText.indexOf('countIf');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: combLine, character: countIfIdx + 1 },\n });\n assert.ok(response.result, 'Hover should return info for countIf');\n const hover = response.result as {\n contents: { kind: string; value: string };\n };\n assert.ok(\n hover.contents.value.length > 0,\n 'countIf hover should have content',\n );\n });\n\n // ---- Feature 9: Multi-word Keywords ----\n\n test('GROUP BY appears in default context completions', async () => {\n // Use the empty SQL template which triggers Default context (all completions)\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'defaultCtx = sql`');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'GROUP BY'),\n `Should include \"GROUP BY\" keyword, got sample: ${labels.slice(0, 30).join(', ')}`,\n );\n });\n\n test('ORDER BY appears in default context completions', async () => {\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'defaultCtx = sql`');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'ORDER BY'),\n `Should include \"ORDER BY\" keyword, got sample: ${labels.slice(0, 30).join(', ')}`,\n );\n });\n});\n\n// ---------------------------------------------------------------------------\n// 2. Snippet toggle (separate servers needed)\n// ---------------------------------------------------------------------------\n\ndescribe('Snippet support toggle', () => {\n test('snippets enabled: function completion has snippet format', async () => {\n const tmpDir = await createTsFixture();\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`, true);\n\n // Use the test.ts file already in the fixture (included in tsconfig)\n const uri = `file://${path.join(tmpDir, 'app', 'test.ts')}`;\n client.openDocument(uri, 'typescript', TS_TEST_FILE_CONTENT);\n await client.waitForDiagnostics(uri);\n\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'prefix = sql`SELECT cou');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const countItem = items.find((i) => i.label === 'count');\n assert.ok(\n countItem,\n `Should have count completion, got: ${items\n .map((i) => i.label)\n .slice(0, 10)\n .join(', ')}`,\n );\n assert.strictEqual(\n countItem.insertText,\n 'count($1)$0',\n 'Snippet mode should produce snippet insertText',\n );\n assert.strictEqual(\n countItem.insertTextFormat,\n 2,\n 'insertTextFormat should be Snippet (2)',\n );\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n\n test('snippets disabled: function completion has plain format', async () => {\n const tmpDir = await createTsFixture();\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`, false);\n\n // Use the test.ts file already in the fixture (included in tsconfig)\n const uri = `file://${path.join(tmpDir, 'app', 'test.ts')}`;\n client.openDocument(uri, 'typescript', TS_TEST_FILE_CONTENT);\n await client.waitForDiagnostics(uri);\n\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'prefix = sql`SELECT cou');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const countItem = items.find((i) => i.label === 'count');\n assert.ok(\n countItem,\n `Should have count completion, got: ${items\n .map((i) => i.label)\n .slice(0, 10)\n .join(', ')}`,\n );\n assert.strictEqual(\n countItem.insertText,\n 'count()',\n 'Non-snippet mode should produce plain insertText',\n );\n assert.strictEqual(\n countItem.insertTextFormat,\n 1,\n 'insertTextFormat should be PlainText (1)',\n );\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n});\n\n// ---------------------------------------------------------------------------\n// 3. ClickHouse version detection\n// ---------------------------------------------------------------------------\n\ndescribe('ClickHouse version detection', () => {\n test('detects version from docker-compose', async () => {\n const tmpDir = await createTsFixtureWithDockerCompose('25.6');\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`);\n const logs = client.getLogMessages();\n assert.ok(\n logs.some((l) => l.includes('Detected ClickHouse version: 25.6')),\n `Should detect version 25.6. Logs: ${logs.join(' | ')}`,\n );\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n\n test('falls back to latest when no docker-compose', async () => {\n const tmpDir = await createTsFixture();\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`);\n const logs = client.getLogMessages();\n assert.ok(\n logs.some(\n (l) =>\n l.includes('No ClickHouse version detected, using latest') ||\n l.includes('using latest'),\n ),\n `Should fall back to latest. Logs: ${logs.join(' | ')}`,\n );\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n});\n\n// ---------------------------------------------------------------------------\n// 4. Python project diagnostics\n// ---------------------------------------------------------------------------\n\ndescribe('Python LSP features', () => {\n test('Python invalid SQL produces a diagnostic', async () => {\n const tmpDir = await createPyFixture();\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`);\n\n const pyUri = `file://${path.join(tmpDir, 'app', 'test.py')}`;\n client.openDocument(pyUri, 'python', PY_TEST_FILE_CONTENT);\n\n const diagnostics = await client.waitForDiagnostics(pyUri);\n assert.ok(\n diagnostics.length > 0,\n `Expected diagnostics for invalid Python SQL, got none`,\n );\n assert.strictEqual(\n diagnostics[0].severity,\n 1,\n 'Should be Error severity',\n );\n assert.strictEqual(diagnostics[0].source, 'moose-sql');\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n});\n\n// ---------------------------------------------------------------------------\n// 5. Original basic tests (preserved)\n// ---------------------------------------------------------------------------\n\ndescribe('Server basic protocol', () => {\n test('responds to initialize request', async () => {\n const client = new LspClient(serverPath);\n\n try {\n const response = await client.request('initialize', {\n processId: null,\n rootUri: 'file:///tmp/test-project',\n capabilities: {},\n });\n\n assert.ok(response.result, 'Should have result');\n const result = response.result as {\n capabilities: { textDocumentSync: unknown };\n };\n assert.ok(result.capabilities, 'Should have capabilities');\n assert.ok(\n result.capabilities.textDocumentSync,\n 'Should have textDocumentSync capability',\n );\n } finally {\n client.close();\n }\n });\n\n test('handles didSave notification and logs message', async () => {\n const client = new LspClient(serverPath);\n\n try {\n await client.request('initialize', {\n processId: null,\n rootUri: 'file:///tmp/test-project',\n capabilities: {\n textDocument: {\n synchronization: {\n didSave: true,\n },\n },\n },\n });\n\n client.notify('initialized', {});\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n client.openDocument(\n 'file:///tmp/test-project/app/test.ts',\n 'typescript',\n 'const x = 1;',\n );\n\n await new Promise((resolve) => setTimeout(resolve, 50));\n\n client.saveDocument('file:///tmp/test-project/app/test.ts');\n\n // Wait for the didSave log\n const deadline = Date.now() + 3000;\n let found = false;\n while (Date.now() < deadline) {\n const logs = client.getLogMessages();\n if (logs.some((l) => l.includes('didSave received'))) {\n found = true;\n break;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n\n assert.ok(found, 'Should log didSave received message');\n } finally {\n client.close();\n }\n });\n});\n"],"mappings":"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","names":["serverPath","before","assert","onFixedLine"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.integration.test.ts"],"sourcesContent":["import assert from 'node:assert';\nimport { type ChildProcess, spawn } from 'node:child_process';\nimport * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { after, before, describe, test } from 'node:test';\n\n// ---------------------------------------------------------------------------\n// LSP message types\n// ---------------------------------------------------------------------------\n\ninterface LspMessage {\n jsonrpc: '2.0';\n id?: number;\n method?: string;\n params?: unknown;\n result?: unknown;\n error?: unknown;\n}\n\ninterface LspDiagnostic {\n range: {\n start: { line: number; character: number };\n end: { line: number; character: number };\n };\n severity: number;\n message: string;\n source?: string;\n}\n\ninterface LspCompletionItem {\n label: string;\n kind?: number;\n detail?: string;\n documentation?: { kind: string; value: string } | string;\n insertText?: string;\n insertTextFormat?: number;\n sortText?: string;\n}\n\n// LSP CompletionItemKind constants\nconst CompletionItemKind = {\n Function: 3,\n Keyword: 14,\n TypeParameter: 25,\n Class: 7,\n Constant: 21,\n Property: 10,\n Method: 2,\n} as const;\n\n// ---------------------------------------------------------------------------\n// LspClient — improved with Buffer-based parsing and concurrent request support\n// ---------------------------------------------------------------------------\n\nclass LspClient {\n private process: ChildProcess;\n private buffer = Buffer.alloc(0);\n private messages: LspMessage[] = [];\n private nextId = 1;\n private pendingRequests = new Map<\n number,\n { resolve: (msg: LspMessage) => void; reject: (err: Error) => void }\n >();\n private notificationListeners: Array<(msg: LspMessage) => void> = [];\n private stderrChunks: string[] = [];\n\n constructor(serverPath: string) {\n this.process = spawn('node', [serverPath, '--stdio'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n this.process.stdout?.on('data', (data: Buffer) => {\n this.buffer = Buffer.concat([this.buffer, data]);\n this.parseMessages();\n });\n\n this.process.stderr?.on('data', (data: Buffer) => {\n this.stderrChunks.push(data.toString());\n });\n }\n\n private parseMessages() {\n while (true) {\n const headerEndIndex = this.buffer.indexOf('\\r\\n\\r\\n');\n if (headerEndIndex === -1) break;\n\n const headerStr = this.buffer\n .subarray(0, headerEndIndex)\n .toString('utf-8');\n const match = headerStr.match(/Content-Length:\\s*(\\d+)/i);\n if (!match) break;\n\n const contentLength = parseInt(match[1], 10);\n const contentStart = headerEndIndex + 4;\n const contentEnd = contentStart + contentLength;\n\n if (this.buffer.length < contentEnd) break;\n\n const content = this.buffer\n .subarray(contentStart, contentEnd)\n .toString('utf-8');\n this.buffer = this.buffer.subarray(contentEnd);\n\n const message = JSON.parse(content) as LspMessage;\n this.messages.push(message);\n\n // Resolve pending request if this is a response\n if (message.id !== undefined) {\n const pending = this.pendingRequests.get(message.id);\n if (pending) {\n this.pendingRequests.delete(message.id);\n pending.resolve(message);\n }\n }\n\n // Notify listeners for server-initiated messages (notifications)\n if (message.method && message.id === undefined) {\n for (const listener of this.notificationListeners) {\n listener(message);\n }\n }\n }\n }\n\n send(message: LspMessage): void {\n const content = JSON.stringify(message);\n const header = `Content-Length: ${Buffer.byteLength(content)}\\r\\n\\r\\n`;\n this.process.stdin?.write(header + content);\n }\n\n async request(\n method: string,\n params: unknown,\n timeoutMs = 10000,\n ): Promise<LspMessage> {\n const id = this.nextId++;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(id);\n reject(\n new Error(`Timeout waiting for response to ${method} (id=${id})`),\n );\n }, timeoutMs);\n\n // Check if response already arrived\n const existing = this.messages.find((m) => m.id === id);\n if (existing) {\n clearTimeout(timeout);\n resolve(existing);\n return;\n }\n\n this.pendingRequests.set(id, {\n resolve: (msg) => {\n clearTimeout(timeout);\n resolve(msg);\n },\n reject: (err) => {\n clearTimeout(timeout);\n reject(err);\n },\n });\n\n this.send({ jsonrpc: '2.0', id, method, params });\n });\n }\n\n notify(method: string, params: unknown): void {\n this.send({ jsonrpc: '2.0', method, params });\n }\n\n openDocument(uri: string, languageId: string, text: string): void {\n this.notify('textDocument/didOpen', {\n textDocument: { uri, languageId, version: 1, text },\n });\n }\n\n changeDocument(uri: string, version: number, text: string): void {\n this.notify('textDocument/didChange', {\n textDocument: { uri, version },\n contentChanges: [{ text }],\n });\n }\n\n saveDocument(uri: string): void {\n this.notify('textDocument/didSave', {\n textDocument: { uri },\n });\n }\n\n waitForDiagnostics(uri: string, timeoutMs = 10000): Promise<LspDiagnostic[]> {\n return new Promise((resolve, reject) => {\n const deadline = setTimeout(() => {\n cleanup();\n reject(new Error(`Timeout waiting for diagnostics for ${uri}`));\n }, timeoutMs);\n\n const listener = (msg: LspMessage) => {\n if (msg.method !== 'textDocument/publishDiagnostics') return;\n const params = msg.params as {\n uri: string;\n diagnostics: LspDiagnostic[];\n };\n if (params.uri === uri) {\n cleanup();\n resolve(params.diagnostics);\n }\n };\n\n const cleanup = () => {\n clearTimeout(deadline);\n const idx = this.notificationListeners.indexOf(listener);\n if (idx !== -1) this.notificationListeners.splice(idx, 1);\n };\n\n // Check messages already received\n for (let i = this.messages.length - 1; i >= 0; i--) {\n const m = this.messages[i];\n if (m.method === 'textDocument/publishDiagnostics') {\n const params = m.params as {\n uri: string;\n diagnostics: LspDiagnostic[];\n };\n if (params.uri === uri) {\n clearTimeout(deadline);\n resolve(params.diagnostics);\n return;\n }\n }\n }\n\n this.notificationListeners.push(listener);\n });\n }\n\n /**\n * Waits for fresh diagnostics that arrive after this call.\n * Ignores any diagnostics already in the message buffer.\n */\n waitForFreshDiagnostics(\n uri: string,\n timeoutMs = 10000,\n ): Promise<LspDiagnostic[]> {\n return new Promise((resolve, reject) => {\n const deadline = setTimeout(() => {\n cleanup();\n reject(new Error(`Timeout waiting for fresh diagnostics for ${uri}`));\n }, timeoutMs);\n\n const listener = (msg: LspMessage) => {\n if (msg.method !== 'textDocument/publishDiagnostics') return;\n const params = msg.params as {\n uri: string;\n diagnostics: LspDiagnostic[];\n };\n if (params.uri === uri) {\n cleanup();\n resolve(params.diagnostics);\n }\n };\n\n const cleanup = () => {\n clearTimeout(deadline);\n const idx = this.notificationListeners.indexOf(listener);\n if (idx !== -1) this.notificationListeners.splice(idx, 1);\n };\n\n this.notificationListeners.push(listener);\n });\n }\n\n getMessages(): LspMessage[] {\n return [...this.messages];\n }\n\n getStderr(): string {\n return this.stderrChunks.join('');\n }\n\n getLogMessages(): string[] {\n return this.messages\n .filter((m) => m.method === 'window/logMessage')\n .map((m) => (m.params as { message: string }).message);\n }\n\n close(): void {\n this.process.kill();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst serverPath = path.join(__dirname, '..', 'dist', 'server.js');\n\n/**\n * Given file content and a search string, returns the 0-indexed\n * line/character position immediately after the last character of the match.\n */\nfunction cursorAfter(\n fileContent: string,\n searchText: string,\n): { line: number; character: number } {\n const idx = fileContent.indexOf(searchText);\n if (idx === -1) {\n throw new Error(`cursorAfter: \"${searchText}\" not found in content`);\n }\n const endIdx = idx + searchText.length;\n const before = fileContent.slice(0, endIdx);\n const lines = before.split('\\n');\n return {\n line: lines.length - 1,\n character: lines[lines.length - 1].length,\n };\n}\n\nasync function initializeClient(\n client: LspClient,\n rootUri: string,\n snippetSupport = true,\n): Promise<LspMessage> {\n const response = await client.request('initialize', {\n processId: null,\n rootUri,\n capabilities: {\n textDocument: {\n completion: {\n completionItem: {\n snippetSupport,\n },\n },\n synchronization: {\n didSave: true,\n },\n },\n },\n });\n client.notify('initialized', {});\n return response;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture: TypeScript project\n// ---------------------------------------------------------------------------\n\nconst TS_TEST_FILE_CONTENT = `import { sql } from '@514labs/moose-lib';\n\n// Valid SQL — should produce no diagnostics\nconst valid = sql\\`SELECT count() FROM users\\`;\n\n// Invalid SQL — should produce an error diagnostic\nconst invalid = sql\\`SELCT * FROM users\\`;\n\n// Completions: default context (cursor after \"SELECT \")\nconst comp1 = sql\\`SELECT \\`;\n\n// Context-aware: ENGINE =\nconst engine = sql\\`CREATE TABLE t ENGINE = \\`;\n\n// Context-aware: FORMAT\nconst format = sql\\`SELECT * FORMAT \\`;\n\n// Context-aware: SETTINGS\nconst settings = sql\\`SELECT * SETTINGS \\`;\n\n// Context-aware: column definition (data types)\nconst coldef = sql\\`CREATE TABLE t (id \\`;\n\n// Context-aware: FROM (table functions)\nconst fromCtx = sql\\`SELECT * FROM \\`;\n\n// Hover targets\nconst hover = sql\\`SELECT count() FROM users WHERE toUInt32(id) > 0\\`;\n\n// Format SQL target (lowercase)\nconst fmt = sql\\`select * from users where id = 1\\`;\n\n// Combinators\nconst comb = sql\\`SELECT sumIf(amount, active), countIf(status) FROM orders\\`;\n\n// Prefix filtering\nconst prefix = sql\\`SELECT cou\\`;\n\n// Combinator prefix filtering\nconst combPrefix = sql\\`SELECT sum\\`;\n\n// Default context (empty SQL — triggers Default completions with all kinds)\nconst defaultCtx = sql\\`\\`;\n\n// sql.statement — valid SQL, should validate\nconst stmtValid = sql.statement\\`SELECT count() FROM users\\`;\n\n// sql.statement — invalid SQL, should produce error\nconst stmtInvalid = sql.statement\\`SELCT * FROM users\\`;\n\n// sql.fragment — invalid as standalone SQL, should NOT produce error\nconst frag = sql.fragment\\`status = 'active' AND amount > 0\\`;\n\n// sql.fragment — hover target\nconst fragHover = sql.fragment\\`toUInt32(id) > 0\\`;\n\n// sql.fragment — completions target\nconst fragComp = sql.fragment\\`cou\\`;\n`;\n\nasync function createTsFixture(): Promise<string> {\n const tmpDir = await fs.mkdtemp(\n path.join(os.tmpdir(), 'moose-lsp-integ-ts-'),\n );\n\n // package.json\n await fs.writeFile(\n path.join(tmpDir, 'package.json'),\n JSON.stringify({\n name: 'test-moose-ts',\n dependencies: { '@514labs/moose-lib': '*' },\n }),\n );\n\n // tsconfig.json\n await fs.writeFile(\n path.join(tmpDir, 'tsconfig.json'),\n JSON.stringify({\n compilerOptions: {\n target: 'ES2020',\n module: 'commonjs',\n strict: true,\n esModuleInterop: true,\n moduleResolution: 'node',\n },\n include: ['app/**/*.ts'],\n }),\n );\n\n // Minimal moose-lib shim\n const mooseLibDir = path.join(\n tmpDir,\n 'node_modules',\n '@514labs',\n 'moose-lib',\n );\n await fs.mkdir(mooseLibDir, { recursive: true });\n await fs.writeFile(\n path.join(mooseLibDir, 'package.json'),\n JSON.stringify({\n name: '@514labs/moose-lib',\n main: 'index.js',\n types: 'index.d.ts',\n }),\n );\n await fs.writeFile(\n path.join(mooseLibDir, 'index.js'),\n `\nconst handler = function(strings, ...values) { return strings.join(''); };\nhandler.statement = handler;\nhandler.fragment = handler;\nmodule.exports.sql = handler;\n`,\n );\n await fs.writeFile(\n path.join(mooseLibDir, 'index.d.ts'),\n `\ninterface SqlTemplateTag {\n (strings: TemplateStringsArray, ...values: unknown[]): string;\n statement(strings: TemplateStringsArray, ...values: unknown[]): string;\n fragment(strings: TemplateStringsArray, ...values: unknown[]): string;\n}\nexport declare const sql: SqlTemplateTag;\n`,\n );\n\n // Test TypeScript file\n const appDir = path.join(tmpDir, 'app');\n await fs.mkdir(appDir, { recursive: true });\n await fs.writeFile(path.join(appDir, 'test.ts'), TS_TEST_FILE_CONTENT);\n\n return tmpDir;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture: Python project\n// ---------------------------------------------------------------------------\n\nconst PY_TEST_FILE_CONTENT = `from moose_lib import sql\n\n# Invalid SQL\nquery = sql(\"SELCT * FROM users\")\n`;\n\nasync function createPyFixture(): Promise<string> {\n const tmpDir = await fs.mkdtemp(\n path.join(os.tmpdir(), 'moose-lsp-integ-py-'),\n );\n\n await fs.writeFile(\n path.join(tmpDir, 'pyproject.toml'),\n `[project]\\nname = \"test-moose-py\"\\ndependencies = [\"moose-lib\"]\\n`,\n );\n\n const appDir = path.join(tmpDir, 'app');\n await fs.mkdir(appDir, { recursive: true });\n await fs.writeFile(path.join(appDir, 'test.py'), PY_TEST_FILE_CONTENT);\n\n return tmpDir;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture: TypeScript project with docker-compose (version detection)\n// ---------------------------------------------------------------------------\n\nasync function createTsFixtureWithDockerCompose(\n chVersion: string,\n): Promise<string> {\n const tmpDir = await createTsFixture();\n\n await fs.writeFile(\n path.join(tmpDir, 'docker-compose.dev.override.yaml'),\n `services:\\n clickhousedb:\\n image: clickhouse/clickhouse-server:${chVersion}\\n`,\n );\n\n return tmpDir;\n}\n\n// ===========================================================================\n// TEST SUITES\n// ===========================================================================\n\n// ---------------------------------------------------------------------------\n// 1. TypeScript features (single server)\n// ---------------------------------------------------------------------------\n\ndescribe('TypeScript LSP features', () => {\n let client: LspClient;\n let tmpDir: string;\n const tsFileUri = () => `file://${path.join(tmpDir, 'app', 'test.ts')}`;\n\n before(async () => {\n tmpDir = await createTsFixture();\n client = new LspClient(serverPath);\n await initializeClient(client, `file://${tmpDir}`);\n // Open the test file — triggers initial validation\n client.openDocument(tsFileUri(), 'typescript', TS_TEST_FILE_CONTENT);\n // Wait for the initial diagnostics to arrive\n await client.waitForDiagnostics(tsFileUri());\n });\n\n after(async () => {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n });\n\n // ---- Feature 1: Error Diagnostics ----\n\n test('valid SQL produces no error diagnostics on that template', async () => {\n // The server publishes diagnostics for the whole file.\n // We check that the \"valid\" template line has no error diagnostic.\n // (It may have a deprecation hint for bare sql tags.)\n const validLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const valid'),\n );\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const errorsOnValidLine = diagnostics.filter(\n (d) => d.range.start.line === validLine && d.severity === 1,\n );\n assert.strictEqual(\n errorsOnValidLine.length,\n 0,\n `Expected no error diagnostics on the valid SQL line, got: ${JSON.stringify(errorsOnValidLine)}`,\n );\n });\n\n test('invalid SQL produces an error diagnostic', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const invalidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const invalid'),\n );\n const errorsOnInvalidLine = diagnostics.filter(\n (d) => d.range.start.line === invalidLine && d.severity === 1,\n );\n assert.ok(\n errorsOnInvalidLine.length > 0,\n `Expected at least one error diagnostic on the invalid SQL line (${invalidLine})`,\n );\n const diag = errorsOnInvalidLine[0];\n assert.strictEqual(diag.severity, 1, 'Severity should be Error (1)');\n assert.strictEqual(diag.source, 'moose-sql');\n });\n\n test('fixing SQL clears diagnostic on that line', async () => {\n const invalidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const invalid'),\n );\n\n const fixedContent = TS_TEST_FILE_CONTENT.replace(\n 'SELCT * FROM users',\n 'SELECT * FROM users',\n );\n\n // Send the change, wait for TextDocuments to process it, then save\n client.changeDocument(tsFileUri(), 2, fixedContent);\n await new Promise((r) => setTimeout(r, 100));\n client.saveDocument(tsFileUri());\n\n // Wait for diagnostics that no longer contain the SELCT error\n // (deprecation hints may still be present on the line)\n const deadline = Date.now() + 10000;\n let lastDiagnostics: LspDiagnostic[] = [];\n while (Date.now() < deadline) {\n lastDiagnostics = await client.waitForFreshDiagnostics(tsFileUri());\n const errorsOnFixedLine = lastDiagnostics.filter(\n (d) =>\n d.range.start.line === invalidLine &&\n d.source === 'moose-sql' &&\n d.severity === 1,\n );\n if (errorsOnFixedLine.length === 0) break;\n // Got stale diagnostics, wait for the next publish\n }\n\n const errorsOnFixedLine = lastDiagnostics.filter(\n (d) =>\n d.range.start.line === invalidLine &&\n d.source === 'moose-sql' &&\n d.severity === 1,\n );\n assert.strictEqual(\n errorsOnFixedLine.length,\n 0,\n `Expected no error diagnostic on the fixed line (${invalidLine}), got: ${JSON.stringify(errorsOnFixedLine)}`,\n );\n\n // Restore original content for subsequent tests\n client.changeDocument(tsFileUri(), 3, TS_TEST_FILE_CONTENT);\n await new Promise((r) => setTimeout(r, 100));\n client.saveDocument(tsFileUri());\n await client.waitForFreshDiagnostics(tsFileUri());\n });\n\n // ---- Feature 2: Auto-Complete ----\n\n test('completions inside SQL template returns items', async () => {\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'comp1 = sql`SELECT ');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(Array.isArray(items), 'Result should be an array');\n assert.ok(items.length > 0, 'Should have completion items');\n });\n\n test('SelectClause context returns only functions', async () => {\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'comp1 = sql`SELECT ');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const kinds = new Set(items.map((i) => i.kind));\n assert.ok(\n kinds.has(CompletionItemKind.Function) ||\n kinds.has(CompletionItemKind.Method),\n 'Should include function or method completions',\n );\n // SelectClause context only returns functions (no keywords, data types, etc.)\n for (const item of items) {\n assert.ok(\n item.kind === CompletionItemKind.Function ||\n item.kind === CompletionItemKind.Method,\n `SelectClause should only have functions, got kind=${item.kind} for \"${item.label}\"`,\n );\n }\n });\n\n test('completions outside SQL template returns empty', async () => {\n // Line 0 is the import line — outside any sql template\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: { line: 0, character: 5 },\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(Array.isArray(items), 'Result should be an array');\n assert.strictEqual(\n items.length,\n 0,\n 'Should have no completions outside template',\n );\n });\n\n test('prefix filtering narrows completions', async () => {\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'prefix = sql`SELECT cou');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have some completions');\n const labels = items.map((i) => i.label.toLowerCase());\n assert.ok(\n labels.some((l) => l.startsWith('count')),\n `Should include count*, got: ${labels.slice(0, 10).join(', ')}`,\n );\n // Every item should start with 'cou'\n for (const item of items) {\n assert.ok(\n item.label.toLowerCase().startsWith('cou'),\n `Item \"${item.label}\" should start with \"cou\"`,\n );\n }\n });\n\n // ---- Feature 3: Context-Aware Completions ----\n\n test('ENGINE = context returns table engines', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'engine = sql`CREATE TABLE t ENGINE = ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have engine completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'MergeTree'),\n `Should include MergeTree, got: ${labels.slice(0, 10).join(', ')}`,\n );\n // All items should be engines (Class kind)\n for (const item of items) {\n assert.strictEqual(\n item.kind,\n CompletionItemKind.Class,\n `Engine item \"${item.label}\" should have kind=Class(${CompletionItemKind.Class}), got ${item.kind}`,\n );\n }\n });\n\n test('FORMAT context returns formats', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'format = sql`SELECT * FORMAT ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have format completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'JSON'),\n `Should include JSON, got: ${labels.slice(0, 10).join(', ')}`,\n );\n for (const item of items) {\n assert.strictEqual(\n item.kind,\n CompletionItemKind.Constant,\n `Format item \"${item.label}\" should have kind=Constant(${CompletionItemKind.Constant}), got ${item.kind}`,\n );\n }\n });\n\n test('SETTINGS context returns settings', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'settings = sql`SELECT * SETTINGS ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have settings completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'max_threads'),\n `Should include max_threads, got: ${labels.slice(0, 15).join(', ')}`,\n );\n for (const item of items) {\n assert.strictEqual(\n item.kind,\n CompletionItemKind.Property,\n `Setting item \"${item.label}\" should have kind=Property(${CompletionItemKind.Property}), got ${item.kind}`,\n );\n }\n });\n\n test('column definition context returns data types', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'coldef = sql`CREATE TABLE t (id ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have data type completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'UInt64'),\n `Should include UInt64, got: ${labels.slice(0, 15).join(', ')}`,\n );\n assert.ok(\n labels.some((l) => l === 'String'),\n `Should include String, got: ${labels.slice(0, 15).join(', ')}`,\n );\n });\n\n test('FROM context returns table functions', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'fromCtx = sql`SELECT * FROM ',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(items.length > 0, 'Should have FROM completions');\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'file' || l === 'url'),\n `Should include table functions like file/url, got: ${labels.slice(0, 15).join(', ')}`,\n );\n });\n\n // ---- Feature 4: Hover Documentation ----\n\n test('hover on known function shows documentation', async () => {\n // Find \"count\" in the hover line\n const hoverLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`SELECT count()'),\n );\n // \"count\" starts after \"SELECT \"\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[hoverLine];\n const countCharIdx = lineText.indexOf('count');\n assert.ok(countCharIdx !== -1, 'Should find count in hover line');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: hoverLine, character: countCharIdx + 1 },\n });\n assert.ok(response.result, 'Hover should return a result for count');\n const hover = response.result as {\n contents: { kind: string; value: string };\n };\n assert.ok(\n hover.contents.value.length > 0,\n 'Hover content should not be empty',\n );\n assert.strictEqual(\n hover.contents.kind,\n 'markdown',\n 'Hover should be markdown',\n );\n });\n\n test('hover on keyword shows documentation', async () => {\n // Hover over SELECT on the hover line\n const hoverLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`SELECT count()'),\n );\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[hoverLine];\n const selectIdx = lineText.indexOf('SELECT');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: hoverLine, character: selectIdx + 1 },\n });\n assert.ok(\n response.result,\n 'Hover should return a result for SELECT keyword',\n );\n });\n\n test('hover outside SQL template returns null', async () => {\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: 0, character: 5 },\n });\n assert.strictEqual(\n response.result,\n null,\n 'Hover outside template should be null',\n );\n });\n\n test('hover on unknown word returns null', async () => {\n // \"users\" is a table name, not a known ClickHouse function/keyword\n const hoverLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`SELECT count() FROM users'),\n );\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[hoverLine];\n const usersIdx = lineText.indexOf('users');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: hoverLine, character: usersIdx + 1 },\n });\n assert.strictEqual(\n response.result,\n null,\n 'Hover on unknown word should be null',\n );\n });\n\n // ---- Feature 5: Code Actions — Format SQL ----\n\n test('Format SQL action is offered for valid lowercase SQL', async () => {\n const fmtLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`select * from users'),\n );\n\n const response = await client.request('textDocument/codeAction', {\n textDocument: { uri: tsFileUri() },\n range: {\n start: { line: fmtLine, character: 15 },\n end: { line: fmtLine, character: 15 },\n },\n context: { diagnostics: [] },\n });\n\n const actions = response.result as Array<{\n title: string;\n edit?: { changes: Record<string, Array<{ newText: string }>> };\n }>;\n assert.ok(Array.isArray(actions), 'Code actions should be an array');\n const formatAction = actions.find((a) => a.title.includes('Format'));\n assert.ok(formatAction, 'Should offer a Format SQL action');\n });\n\n test('Format SQL produces uppercase keywords', async () => {\n const fmtLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`select * from users'),\n );\n\n const response = await client.request('textDocument/codeAction', {\n textDocument: { uri: tsFileUri() },\n range: {\n start: { line: fmtLine, character: 15 },\n end: { line: fmtLine, character: 15 },\n },\n context: { diagnostics: [] },\n });\n\n const actions = response.result as Array<{\n title: string;\n edit?: { changes: Record<string, Array<{ newText: string }>> };\n }>;\n const formatAction = actions.find((a) => a.title.includes('Format'));\n assert.ok(formatAction?.edit, 'Format action should have an edit');\n const edits = Object.values(\n (\n formatAction as {\n edit: { changes: Record<string, Array<{ newText: string }>> };\n }\n ).edit.changes,\n ).flat();\n assert.ok(edits.length > 0, 'Should have at least one text edit');\n const newText = edits[0].newText;\n assert.ok(\n newText.includes('SELECT') && newText.includes('FROM'),\n `Formatted SQL should contain uppercase keywords, got: ${newText}`,\n );\n });\n\n test('Format SQL not offered for invalid SQL', async () => {\n const invalidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('sql`SELCT * FROM users'),\n );\n\n const response = await client.request('textDocument/codeAction', {\n textDocument: { uri: tsFileUri() },\n range: {\n start: { line: invalidLine, character: 15 },\n end: { line: invalidLine, character: 15 },\n },\n context: { diagnostics: [] },\n });\n\n const actions = response.result as Array<{ title: string }>;\n const formatAction = (actions || []).find((a) =>\n a.title.includes('Format'),\n );\n assert.ok(!formatAction, 'Should NOT offer Format SQL for invalid SQL');\n });\n\n // ---- Feature 8: Aggregate Combinator Functions ----\n\n test('sumIf appears in completions after \"sum\" prefix', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'combPrefix = sql`SELECT sum',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'sumIf'),\n `Should include sumIf combinator, got: ${labels.slice(0, 20).join(', ')}`,\n );\n });\n\n test('combinator function has documentation', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'combPrefix = sql`SELECT sum',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const sumIf = items.find((i) => i.label === 'sumIf');\n assert.ok(sumIf, 'Should have sumIf item');\n assert.ok(sumIf.documentation, 'sumIf should have documentation');\n const docValue =\n typeof sumIf.documentation === 'string'\n ? sumIf.documentation\n : (sumIf.documentation as { value: string }).value;\n assert.ok(\n docValue.toLowerCase().includes('combinator') ||\n docValue.toLowerCase().includes('aggregate') ||\n docValue.toLowerCase().includes('if'),\n `sumIf docs should mention combinator/aggregate, got: ${docValue.slice(0, 200)}`,\n );\n });\n\n test('hover on combinator function shows info', async () => {\n const combLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('countIf(status)'),\n );\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[combLine];\n const countIfIdx = lineText.indexOf('countIf');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: combLine, character: countIfIdx + 1 },\n });\n assert.ok(response.result, 'Hover should return info for countIf');\n const hover = response.result as {\n contents: { kind: string; value: string };\n };\n assert.ok(\n hover.contents.value.length > 0,\n 'countIf hover should have content',\n );\n });\n\n // ---- Feature 9: Multi-word Keywords ----\n\n test('GROUP BY appears in default context completions', async () => {\n // Use the empty SQL template which triggers Default context (all completions)\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'defaultCtx = sql`');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'GROUP BY'),\n `Should include \"GROUP BY\" keyword, got sample: ${labels.slice(0, 30).join(', ')}`,\n );\n });\n\n test('ORDER BY appears in default context completions', async () => {\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'defaultCtx = sql`');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const labels = items.map((i) => i.label);\n assert.ok(\n labels.some((l) => l === 'ORDER BY'),\n `Should include \"ORDER BY\" keyword, got sample: ${labels.slice(0, 30).join(', ')}`,\n );\n });\n\n // ---- Feature: sql.statement / sql.fragment handling ----\n\n test('sql.statement with valid SQL produces no error diagnostics', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const stmtValidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const stmtValid'),\n );\n const errors = diagnostics.filter(\n (d) => d.range.start.line === stmtValidLine && d.severity === 1,\n );\n assert.strictEqual(\n errors.length,\n 0,\n `Expected no error diagnostics on valid sql.statement line, got: ${JSON.stringify(errors)}`,\n );\n });\n\n test('sql.statement with invalid SQL produces error diagnostic', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const stmtInvalidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const stmtInvalid'),\n );\n const errors = diagnostics.filter(\n (d) => d.range.start.line === stmtInvalidLine && d.severity === 1,\n );\n assert.ok(\n errors.length > 0,\n `Expected error diagnostic on invalid sql.statement line (${stmtInvalidLine})`,\n );\n assert.strictEqual(errors[0].source, 'moose-sql');\n });\n\n test('sql.fragment does NOT produce validation errors', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const fragLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const frag ='),\n );\n const errors = diagnostics.filter(\n (d) => d.range.start.line === fragLine && d.severity === 1,\n );\n assert.strictEqual(\n errors.length,\n 0,\n `Expected no error diagnostics on sql.fragment line, got: ${JSON.stringify(errors)}`,\n );\n });\n\n test('hover works inside sql.fragment', async () => {\n const fragHoverLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const fragHover'),\n );\n const lineText = TS_TEST_FILE_CONTENT.split('\\n')[fragHoverLine];\n const toUInt32Idx = lineText.indexOf('toUInt32');\n assert.ok(toUInt32Idx !== -1, 'Should find toUInt32 in fragHover line');\n\n const response = await client.request('textDocument/hover', {\n textDocument: { uri: tsFileUri() },\n position: { line: fragHoverLine, character: toUInt32Idx + 1 },\n });\n assert.ok(\n response.result,\n 'Hover should return a result for toUInt32 inside fragment',\n );\n const hover = response.result as {\n contents: { kind: string; value: string };\n };\n assert.ok(\n hover.contents.value.length > 0,\n 'Hover content should not be empty',\n );\n });\n\n test('completions work inside sql.fragment', async () => {\n const pos = cursorAfter(\n TS_TEST_FILE_CONTENT,\n 'fragComp = sql.fragment`cou',\n );\n const response = await client.request('textDocument/completion', {\n textDocument: { uri: tsFileUri() },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n assert.ok(Array.isArray(items), 'Result should be an array');\n assert.ok(items.length > 0, 'Should have completion items inside fragment');\n const labels = items.map((i) => i.label.toLowerCase());\n assert.ok(\n labels.some((l) => l.startsWith('count')),\n `Should include count* completions inside fragment, got: ${labels.slice(0, 10).join(', ')}`,\n );\n });\n\n test('bare sql tag produces deprecation hint diagnostic', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const validLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const valid = sql`'),\n );\n const hints = diagnostics.filter(\n (d) => d.range.start.line === validLine && d.severity === 4, // Hint\n );\n assert.ok(\n hints.length > 0,\n `Expected deprecation hint on bare sql line (${validLine}), got diagnostics: ${JSON.stringify(\n diagnostics.filter((d) => d.range.start.line === validLine),\n )}`,\n );\n assert.ok(\n hints[0].message.includes('deprecated'),\n 'Hint message should mention deprecated',\n );\n });\n\n test('sql.statement does NOT produce deprecation hint', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const stmtValidLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const stmtValid'),\n );\n const hints = diagnostics.filter(\n (d) => d.range.start.line === stmtValidLine && d.severity === 4,\n );\n assert.strictEqual(\n hints.length,\n 0,\n `Expected no deprecation hint on sql.statement line, got: ${JSON.stringify(hints)}`,\n );\n });\n\n test('sql.fragment does NOT produce deprecation hint', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const fragLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const frag ='),\n );\n const hints = diagnostics.filter(\n (d) => d.range.start.line === fragLine && d.severity === 4,\n );\n assert.strictEqual(\n hints.length,\n 0,\n `Expected no deprecation hint on sql.fragment line, got: ${JSON.stringify(hints)}`,\n );\n });\n\n test('code action offers quick fixes for bare sql deprecation', async () => {\n const diagnostics = await client.waitForDiagnostics(tsFileUri());\n const validLine = TS_TEST_FILE_CONTENT.split('\\n').findIndex((l) =>\n l.includes('const valid = sql`'),\n );\n const hints = diagnostics.filter(\n (d) => d.range.start.line === validLine && d.severity === 4,\n );\n assert.ok(\n hints.length > 0,\n 'Should have deprecation hint to pass as context',\n );\n\n const response = await client.request('textDocument/codeAction', {\n textDocument: { uri: tsFileUri() },\n range: {\n start: { line: validLine, character: 15 },\n end: { line: validLine, character: 15 },\n },\n context: { diagnostics: hints },\n });\n\n const actions = response.result as Array<{\n title: string;\n kind?: string;\n edit?: { changes: Record<string, Array<{ newText: string }>> };\n }>;\n assert.ok(Array.isArray(actions), 'Code actions should be an array');\n\n const statementAction = actions.find((a) =>\n a.title.includes('sql.statement'),\n );\n assert.ok(statementAction, 'Should offer Convert to sql.statement action');\n assert.ok(\n statementAction.edit?.changes?.[tsFileUri()]?.some(\n (e) => e.newText === 'sql.statement',\n ),\n 'Statement action should replace with sql.statement',\n );\n\n const fragmentAction = actions.find((a) =>\n a.title.includes('sql.fragment'),\n );\n assert.ok(fragmentAction, 'Should offer Convert to sql.fragment action');\n assert.ok(\n fragmentAction.edit?.changes?.[tsFileUri()]?.some(\n (e) => e.newText === 'sql.fragment',\n ),\n 'Fragment action should replace with sql.fragment',\n );\n });\n});\n\n// ---------------------------------------------------------------------------\n// 2. Snippet toggle (separate servers needed)\n// ---------------------------------------------------------------------------\n\ndescribe('Snippet support toggle', () => {\n test('snippets enabled: function completion has snippet format', async () => {\n const tmpDir = await createTsFixture();\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`, true);\n\n // Use the test.ts file already in the fixture (included in tsconfig)\n const uri = `file://${path.join(tmpDir, 'app', 'test.ts')}`;\n client.openDocument(uri, 'typescript', TS_TEST_FILE_CONTENT);\n await client.waitForDiagnostics(uri);\n\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'prefix = sql`SELECT cou');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const countItem = items.find((i) => i.label === 'count');\n assert.ok(\n countItem,\n `Should have count completion, got: ${items\n .map((i) => i.label)\n .slice(0, 10)\n .join(', ')}`,\n );\n assert.strictEqual(\n countItem.insertText,\n 'count($1)$0',\n 'Snippet mode should produce snippet insertText',\n );\n assert.strictEqual(\n countItem.insertTextFormat,\n 2,\n 'insertTextFormat should be Snippet (2)',\n );\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n\n test('snippets disabled: function completion has plain format', async () => {\n const tmpDir = await createTsFixture();\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`, false);\n\n // Use the test.ts file already in the fixture (included in tsconfig)\n const uri = `file://${path.join(tmpDir, 'app', 'test.ts')}`;\n client.openDocument(uri, 'typescript', TS_TEST_FILE_CONTENT);\n await client.waitForDiagnostics(uri);\n\n const pos = cursorAfter(TS_TEST_FILE_CONTENT, 'prefix = sql`SELECT cou');\n const response = await client.request('textDocument/completion', {\n textDocument: { uri },\n position: pos,\n });\n const items = response.result as LspCompletionItem[];\n const countItem = items.find((i) => i.label === 'count');\n assert.ok(\n countItem,\n `Should have count completion, got: ${items\n .map((i) => i.label)\n .slice(0, 10)\n .join(', ')}`,\n );\n assert.strictEqual(\n countItem.insertText,\n 'count()',\n 'Non-snippet mode should produce plain insertText',\n );\n assert.strictEqual(\n countItem.insertTextFormat,\n 1,\n 'insertTextFormat should be PlainText (1)',\n );\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n});\n\n// ---------------------------------------------------------------------------\n// 3. ClickHouse version detection\n// ---------------------------------------------------------------------------\n\ndescribe('ClickHouse version detection', () => {\n test('detects version from docker-compose', async () => {\n const tmpDir = await createTsFixtureWithDockerCompose('25.6');\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`);\n const logs = client.getLogMessages();\n assert.ok(\n logs.some((l) => l.includes('Detected ClickHouse version: 25.6')),\n `Should detect version 25.6. Logs: ${logs.join(' | ')}`,\n );\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n\n test('falls back to latest when no docker-compose', async () => {\n const tmpDir = await createTsFixture();\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`);\n const logs = client.getLogMessages();\n assert.ok(\n logs.some(\n (l) =>\n l.includes('No ClickHouse version detected, using latest') ||\n l.includes('using latest'),\n ),\n `Should fall back to latest. Logs: ${logs.join(' | ')}`,\n );\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n});\n\n// ---------------------------------------------------------------------------\n// 4. Python project diagnostics\n// ---------------------------------------------------------------------------\n\ndescribe('Python LSP features', () => {\n test('Python invalid SQL produces a diagnostic', async () => {\n const tmpDir = await createPyFixture();\n const client = new LspClient(serverPath);\n\n try {\n await initializeClient(client, `file://${tmpDir}`);\n\n const pyUri = `file://${path.join(tmpDir, 'app', 'test.py')}`;\n client.openDocument(pyUri, 'python', PY_TEST_FILE_CONTENT);\n\n const diagnostics = await client.waitForDiagnostics(pyUri);\n const errors = diagnostics.filter((d) => d.severity === 1);\n assert.ok(\n errors.length > 0,\n `Expected error diagnostics for invalid Python SQL, got none`,\n );\n assert.strictEqual(errors[0].severity, 1, 'Should be Error severity');\n assert.strictEqual(errors[0].source, 'moose-sql');\n } finally {\n client.close();\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n });\n});\n\n// ---------------------------------------------------------------------------\n// 5. Original basic tests (preserved)\n// ---------------------------------------------------------------------------\n\ndescribe('Server basic protocol', () => {\n test('responds to initialize request', async () => {\n const client = new LspClient(serverPath);\n\n try {\n const response = await client.request('initialize', {\n processId: null,\n rootUri: 'file:///tmp/test-project',\n capabilities: {},\n });\n\n assert.ok(response.result, 'Should have result');\n const result = response.result as {\n capabilities: { textDocumentSync: unknown };\n };\n assert.ok(result.capabilities, 'Should have capabilities');\n assert.ok(\n result.capabilities.textDocumentSync,\n 'Should have textDocumentSync capability',\n );\n } finally {\n client.close();\n }\n });\n\n test('handles didSave notification and logs message', async () => {\n const client = new LspClient(serverPath);\n\n try {\n await client.request('initialize', {\n processId: null,\n rootUri: 'file:///tmp/test-project',\n capabilities: {\n textDocument: {\n synchronization: {\n didSave: true,\n },\n },\n },\n });\n\n client.notify('initialized', {});\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n client.openDocument(\n 'file:///tmp/test-project/app/test.ts',\n 'typescript',\n 'const x = 1;',\n );\n\n await new Promise((resolve) => setTimeout(resolve, 50));\n\n client.saveDocument('file:///tmp/test-project/app/test.ts');\n\n // Wait for the didSave log\n const deadline = Date.now() + 3000;\n let found = false;\n while (Date.now() < deadline) {\n const logs = client.getLogMessages();\n if (logs.some((l) => l.includes('didSave received'))) {\n found = true;\n break;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n\n assert.ok(found, 'Should log didSave received message');\n } finally {\n client.close();\n }\n });\n});\n"],"mappings":"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","names":["serverPath","before","assert","errorsOnFixedLine"]}
|