215 lines
6.4 KiB
JavaScript
215 lines
6.4 KiB
JavaScript
import * as path from 'node:path'
|
|
import * as cp from 'node:child_process'
|
|
import * as rpc from 'vscode-jsonrpc'
|
|
import { beforeAll } from 'vitest'
|
|
|
|
async function init(fixture) {
|
|
let settings = {}
|
|
let docSettings = new Map()
|
|
|
|
let childProcess = cp.fork('./bin/tailwindcss-language-server', { silent: true })
|
|
|
|
const capabilities = {
|
|
textDocument: {
|
|
codeAction: { dynamicRegistration: true },
|
|
codeLens: { dynamicRegistration: true },
|
|
colorProvider: { dynamicRegistration: true },
|
|
completion: {
|
|
completionItem: {
|
|
commitCharactersSupport: true,
|
|
documentationFormat: ['markdown', 'plaintext'],
|
|
snippetSupport: true,
|
|
},
|
|
completionItemKind: {
|
|
valueSet: [
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
|
25,
|
|
],
|
|
},
|
|
contextSupport: true,
|
|
dynamicRegistration: true,
|
|
},
|
|
definition: { dynamicRegistration: true },
|
|
documentHighlight: { dynamicRegistration: true },
|
|
documentLink: { dynamicRegistration: true },
|
|
documentSymbol: {
|
|
dynamicRegistration: true,
|
|
symbolKind: {
|
|
valueSet: [
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
|
25, 26,
|
|
],
|
|
},
|
|
},
|
|
formatting: { dynamicRegistration: true },
|
|
hover: {
|
|
contentFormat: ['markdown', 'plaintext'],
|
|
dynamicRegistration: true,
|
|
},
|
|
implementation: { dynamicRegistration: true },
|
|
onTypeFormatting: { dynamicRegistration: true },
|
|
publishDiagnostics: { relatedInformation: true },
|
|
rangeFormatting: { dynamicRegistration: true },
|
|
references: { dynamicRegistration: true },
|
|
rename: { dynamicRegistration: true },
|
|
signatureHelp: {
|
|
dynamicRegistration: true,
|
|
signatureInformation: { documentationFormat: ['markdown', 'plaintext'] },
|
|
},
|
|
synchronization: {
|
|
didSave: true,
|
|
dynamicRegistration: true,
|
|
willSave: true,
|
|
willSaveWaitUntil: true,
|
|
},
|
|
typeDefinition: { dynamicRegistration: true },
|
|
},
|
|
workspace: {
|
|
applyEdit: true,
|
|
configuration: true,
|
|
didChangeConfiguration: { dynamicRegistration: true },
|
|
didChangeWatchedFiles: { dynamicRegistration: true },
|
|
executeCommand: { dynamicRegistration: true },
|
|
symbol: {
|
|
dynamicRegistration: true,
|
|
symbolKind: {
|
|
valueSet: [
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
|
25, 26,
|
|
],
|
|
},
|
|
},
|
|
workspaceEdit: { documentChanges: true },
|
|
workspaceFolders: true,
|
|
},
|
|
}
|
|
|
|
let connection = rpc.createMessageConnection(
|
|
new rpc.StreamMessageReader(childProcess.stdout),
|
|
new rpc.StreamMessageWriter(childProcess.stdin)
|
|
)
|
|
|
|
connection.listen()
|
|
|
|
await connection.sendRequest(new rpc.RequestType('initialize'), {
|
|
processId: -1,
|
|
// rootPath: '.',
|
|
rootUri: `file://${path.resolve('./tests/fixtures/', fixture)}`,
|
|
capabilities,
|
|
trace: 'off',
|
|
workspaceFolders: [],
|
|
initializationOptions: {
|
|
testMode: true,
|
|
},
|
|
})
|
|
|
|
await connection.sendNotification(new rpc.NotificationType('initialized'))
|
|
|
|
connection.onRequest(new rpc.RequestType('workspace/configuration'), (params) => {
|
|
return params.items.map((item) => {
|
|
if (docSettings.has(item.scopeUri)) {
|
|
return docSettings.get(item.scopeUri)[item.section] ?? {}
|
|
}
|
|
return settings[item.section] ?? {}
|
|
})
|
|
})
|
|
|
|
let initPromise = new Promise((resolve) => {
|
|
connection.onRequest(new rpc.RequestType('client/registerCapability'), ({ registrations }) => {
|
|
if (registrations.findIndex((r) => r.method === 'textDocument/completion') > -1) {
|
|
resolve()
|
|
}
|
|
return null
|
|
})
|
|
})
|
|
|
|
let counter = 0
|
|
|
|
return {
|
|
connection,
|
|
sendRequest(type, params) {
|
|
return connection.sendRequest(new rpc.RequestType(type), params)
|
|
},
|
|
onNotification(type, callback) {
|
|
return connection.onNotification(new rpc.RequestType(type), callback)
|
|
},
|
|
async openDocument({ text, lang = 'html', dir = '', settings = {} }) {
|
|
let uri = `file://${path.resolve('./tests/fixtures', fixture, dir, `file-${counter++}`)}`
|
|
docSettings.set(uri, settings)
|
|
await connection.sendNotification(new rpc.NotificationType('textDocument/didOpen'), {
|
|
textDocument: {
|
|
uri,
|
|
languageId: lang,
|
|
version: 1,
|
|
text,
|
|
},
|
|
})
|
|
|
|
await initPromise
|
|
|
|
return {
|
|
uri,
|
|
async updateSettings(settings) {
|
|
docSettings.set(uri, settings)
|
|
await connection.sendNotification(
|
|
new rpc.NotificationType('workspace/didChangeConfiguration')
|
|
)
|
|
},
|
|
}
|
|
},
|
|
async updateSettings(newSettings) {
|
|
settings = newSettings
|
|
await connection.sendNotification(
|
|
new rpc.NotificationType('workspace/didChangeConfiguration')
|
|
)
|
|
},
|
|
async updateFile(file, text) {
|
|
let uri = `file://${path.resolve('./tests/fixtures', fixture, file)}`
|
|
|
|
await connection.sendNotification(new rpc.NotificationType('textDocument/didChange'), {
|
|
textDocument: { uri, version: counter++ },
|
|
contentChanges: [{ text }],
|
|
})
|
|
},
|
|
}
|
|
}
|
|
|
|
export function withFixture(fixture, callback) {
|
|
let c = {}
|
|
|
|
beforeAll(async () => {
|
|
// Using the connection object as the prototype lets us access the connection
|
|
// without defining getters for all the methods and also lets us add helpers
|
|
// to the connection object without having to resort to using a Proxy
|
|
Object.setPrototypeOf(c, await init(fixture))
|
|
|
|
return () => c.connection.end()
|
|
})
|
|
|
|
callback(c)
|
|
}
|
|
|
|
// let counter = 0
|
|
|
|
// export async function openDocument(connection, fixture, languageId, text) {
|
|
// let uri = `file://${path.resolve('./tests/fixtures', fixture, `file-${counter++}`)}`
|
|
|
|
// await connection.sendNotification(new rpc.NotificationType('textDocument/didOpen'), {
|
|
// textDocument: {
|
|
// uri,
|
|
// languageId,
|
|
// version: 1,
|
|
// text,
|
|
// },
|
|
// })
|
|
|
|
// await initPromise
|
|
|
|
// return uri
|
|
// }
|
|
|
|
// export async function updateSettings(connection, newSettings) {
|
|
// settings = newSettings
|
|
// await connection.sendNotification(new rpc.NotificationType('workspace/didChangeConfiguration'))
|
|
// }
|