"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.startCommonLanguageServer = void 0; const index_js_1 = require("@volar/language-service/index.js"); const l10n = require("@vscode/l10n"); const vscode = require("vscode-languageserver"); const vscode_uri_1 = require("vscode-uri"); const types_js_1 = require("../types.js"); const configurationHost_js_1 = require("./configurationHost.js"); const documents_js_1 = require("./documents.js"); const registerFeatures_js_1 = require("./utils/registerFeatures.js"); const serverConfig_js_1 = require("./utils/serverConfig.js"); const workspaces_js_1 = require("./workspaces.js"); const request_light_1 = require("request-light"); function startCommonLanguageServer(connection, _plugins, getRuntimeEnv) { let initParams; let options; let roots = []; let workspaces; let plugins; let documents; let context; let ts; let tsLocalized; const didChangeWatchedFilesCallbacks = new Set(); connection.onInitialize(async (_params) => { initParams = _params; options = initParams.initializationOptions; const env = getRuntimeEnv(initParams, options); context = { server: { initializeParams: initParams, connection, runtimeEnv: { ...env, fs: createFsWithCache(env.fs), }, plugins: _plugins, configurationHost: initParams.capabilities.workspace?.configuration ? (0, configurationHost_js_1.createConfigurationHost)(initParams, connection) : undefined, onDidChangeWatchedFiles: cb => { didChangeWatchedFilesCallbacks.add(cb); return { dispose: () => { didChangeWatchedFilesCallbacks.delete(cb); }, }; }, }, }; ts = await context.server.runtimeEnv.loadTypeScript(options); tsLocalized = initParams.locale ? await context.server.runtimeEnv.loadTypeScriptLocalized(options, initParams.locale) : undefined; plugins = context.server.plugins.map(plugin => plugin(options, { typescript: ts })); documents = (0, documents_js_1.createDocuments)(context.server.runtimeEnv, connection); if (options.l10n) { await l10n.config({ uri: options.l10n.location }); } if (initParams.capabilities.workspace?.workspaceFolders && initParams.workspaceFolders) { roots = initParams.workspaceFolders.map(folder => vscode_uri_1.URI.parse(folder.uri)); } else if (initParams.rootUri) { roots = [vscode_uri_1.URI.parse(initParams.rootUri)]; } else if (initParams.rootPath) { roots = [vscode_uri_1.URI.file(initParams.rootPath)]; } const result = { capabilities: { textDocumentSync: vscode.TextDocumentSyncKind.Incremental, workspace: { // #18 workspaceFolders: { supported: true, changeNotifications: true, }, }, }, }; let config = {}; for (const root of roots) { if (root.scheme === 'file') { const workspaceConfig = (0, serverConfig_js_1.loadConfig)(env.console, root.path, options.configFilePath); if (workspaceConfig) { config = workspaceConfig; break; } } } for (const plugin of plugins) { if (plugin.resolveConfig) { config = await plugin.resolveConfig(config, undefined); } } (0, registerFeatures_js_1.setupCapabilities)(result.capabilities, options, plugins, getSemanticTokensLegend(), config.services ?? {}); await createLanguageServiceHost(); try { // show version on LSP logs const packageJson = require('../package.json'); result.serverInfo = { name: packageJson.name, version: packageJson.version, }; } catch { } return result; }); connection.onInitialized(async () => { context.server.configurationHost?.ready(); context.server.configurationHost?.onDidChangeConfiguration?.(updateHttpSettings); updateHttpSettings(); if (initParams.capabilities.workspace?.workspaceFolders) { connection.workspace.onDidChangeWorkspaceFolders(e => { for (const folder of e.added) { workspaces?.add(vscode_uri_1.URI.parse(folder.uri)); } for (const folder of e.removed) { workspaces?.remove(vscode_uri_1.URI.parse(folder.uri)); } }); } if (options.serverMode !== types_js_1.ServerMode.Syntactic && initParams.capabilities.workspace?.didChangeWatchedFiles?.dynamicRegistration) { const exts = plugins.map(plugin => plugin.watchFileExtensions).flat(); if (exts.length) { connection.client.register(vscode.DidChangeWatchedFilesNotification.type, { watchers: [ { globPattern: `**/*.{${exts.join(',')}}` }, ] }); connection.onDidChangeWatchedFiles(e => { for (const cb of didChangeWatchedFilesCallbacks) { cb(e); } }); } } async function updateHttpSettings() { const httpSettings = await context.server.configurationHost?.getConfiguration?.('http'); (0, request_light_1.configure)(httpSettings?.proxy, httpSettings?.proxyStrictSSL ?? false); } }); connection.onShutdown(async () => { workspaces?.reloadProjects(); }); connection.listen(); function createFsWithCache(fs) { const readFileCache = new Map(); const statCache = new Map(); const readDirectoryCache = new Map(); didChangeWatchedFilesCallbacks.add(({ changes }) => { for (const change of changes) { if (change.type === vscode.FileChangeType.Deleted) { readFileCache.set(change.uri, undefined); statCache.set(change.uri, undefined); const dir = change.uri.substring(0, change.uri.lastIndexOf('/')); readDirectoryCache.delete(dir); } else if (change.type === vscode.FileChangeType.Changed) { readFileCache.delete(change.uri); statCache.delete(change.uri); } else if (change.type === vscode.FileChangeType.Created) { readFileCache.delete(change.uri); statCache.delete(change.uri); const dir = change.uri.substring(0, change.uri.lastIndexOf('/')); readDirectoryCache.delete(dir); } } }); return { readFile: uri => { if (!readFileCache.has(uri)) { readFileCache.set(uri, fs.readFile(uri)); } return readFileCache.get(uri); }, stat: uri => { if (!statCache.has(uri)) { statCache.set(uri, fs.stat(uri)); } return statCache.get(uri); }, readDirectory: uri => { if (!readDirectoryCache.has(uri)) { readDirectoryCache.set(uri, fs.readDirectory(uri)); } return readDirectoryCache.get(uri); }, }; } async function createLanguageServiceHost() { workspaces = (0, workspaces_js_1.createWorkspaces)({ ...context, workspaces: { ts, tsLocalized, initParams, initOptions: options, documents, plugins, }, }, roots); (await import('./features/customFeatures.js')).register(connection, workspaces, context.server.runtimeEnv); (await import('./features/languageFeatures.js')).register(connection, workspaces, initParams, options, getSemanticTokensLegend(), context.server.runtimeEnv, documents); for (const plugin of plugins) { plugin.onInitialized?.(getLanguageService, context.server.runtimeEnv); } async function getLanguageService(uri) { const project = (await workspaces.getProject(uri))?.project; return project?.getLanguageService(); } } function getSemanticTokensLegend() { if (!options.semanticTokensLegend) { return index_js_1.standardSemanticTokensLegend; } return { tokenTypes: [...index_js_1.standardSemanticTokensLegend.tokenTypes, ...options.semanticTokensLegend.tokenTypes], tokenModifiers: [...index_js_1.standardSemanticTokensLegend.tokenModifiers, ...options.semanticTokensLegend.tokenModifiers], }; } } exports.startCommonLanguageServer = startCommonLanguageServer; //# sourceMappingURL=server.js.map