Revamping to matrix style
This commit is contained in:
8
node_modules/@volar/language-server/lib/features/configurations.d.ts
generated
vendored
Normal file
8
node_modules/@volar/language-server/lib/features/configurations.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import * as vscode from 'vscode-languageserver';
|
||||
import { LanguageServerState } from '../types';
|
||||
export declare function register(server: LanguageServerState): {
|
||||
get: <T>(section: string, scopeUri?: string) => Promise<T | undefined>;
|
||||
onDidChange: (cb: vscode.NotificationHandler<vscode.DidChangeConfigurationParams>) => {
|
||||
dispose(): void;
|
||||
};
|
||||
};
|
||||
49
node_modules/@volar/language-server/lib/features/configurations.js
generated
vendored
Normal file
49
node_modules/@volar/language-server/lib/features/configurations.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.register = register;
|
||||
const vscode = require("vscode-languageserver");
|
||||
function register(server) {
|
||||
const configurations = new Map();
|
||||
const didChangeCallbacks = new Set();
|
||||
server.onInitialized(() => {
|
||||
server.connection.onDidChangeConfiguration(params => {
|
||||
configurations.clear(); // TODO: clear only the configurations that changed
|
||||
for (const cb of didChangeCallbacks) {
|
||||
cb(params);
|
||||
}
|
||||
});
|
||||
const didChangeConfiguration = server.initializeParams.capabilities.workspace?.didChangeConfiguration;
|
||||
if (didChangeConfiguration?.dynamicRegistration) {
|
||||
server.connection.client.register(vscode.DidChangeConfigurationNotification.type);
|
||||
}
|
||||
});
|
||||
return {
|
||||
get,
|
||||
onDidChange,
|
||||
};
|
||||
function get(section, scopeUri) {
|
||||
if (!server.initializeParams.capabilities.workspace?.configuration) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
const didChangeConfiguration = server.initializeParams.capabilities.workspace?.didChangeConfiguration;
|
||||
if (!scopeUri && didChangeConfiguration) {
|
||||
if (!configurations.has(section)) {
|
||||
configurations.set(section, getConfigurationWorker(section, scopeUri));
|
||||
}
|
||||
return configurations.get(section);
|
||||
}
|
||||
return getConfigurationWorker(section, scopeUri);
|
||||
}
|
||||
function onDidChange(cb) {
|
||||
didChangeCallbacks.add(cb);
|
||||
return {
|
||||
dispose() {
|
||||
didChangeCallbacks.delete(cb);
|
||||
},
|
||||
};
|
||||
}
|
||||
async function getConfigurationWorker(section, scopeUri) {
|
||||
return (await server.connection.workspace.getConfiguration({ scopeUri, section })) ?? undefined /* replace null to undefined */;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=configurations.js.map
|
||||
2
node_modules/@volar/language-server/lib/features/editorFeatures.d.ts
generated
vendored
Normal file
2
node_modules/@volar/language-server/lib/features/editorFeatures.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import type { LanguageServerState } from '../types';
|
||||
export declare function register(server: LanguageServerState): void;
|
||||
186
node_modules/@volar/language-server/lib/features/editorFeatures.js
generated
vendored
Normal file
186
node_modules/@volar/language-server/lib/features/editorFeatures.js
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.register = register;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
const protocol_1 = require("../../protocol");
|
||||
function register(server) {
|
||||
server.onInitialize(() => {
|
||||
const { project } = server;
|
||||
const scriptVersions = (0, language_service_1.createUriMap)();
|
||||
const scriptVersionSnapshots = new WeakSet();
|
||||
server.connection.onRequest(protocol_1.GetMatchTsConfigRequest.type, async (params) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.uri);
|
||||
const languageService = (await project.getLanguageService(uri));
|
||||
const tsProject = languageService.context.project.typescript;
|
||||
if (tsProject?.configFileName) {
|
||||
const { configFileName, uriConverter } = tsProject;
|
||||
return { uri: uriConverter.asUri(configFileName).toString() };
|
||||
}
|
||||
});
|
||||
server.connection.onRequest(protocol_1.GetVirtualFileRequest.type, async (document) => {
|
||||
const uri = vscode_uri_1.URI.parse(document.uri);
|
||||
const languageService = (await project.getLanguageService(uri));
|
||||
const documentUri = vscode_uri_1.URI.parse(document.uri);
|
||||
const sourceScript = languageService.context.language.scripts.get(documentUri);
|
||||
if (sourceScript?.generated) {
|
||||
return prune(sourceScript.generated.root);
|
||||
}
|
||||
function prune(virtualCode) {
|
||||
const uri = languageService.context.encodeEmbeddedDocumentUri(sourceScript.id, virtualCode.id);
|
||||
let version = scriptVersions.get(uri) ?? 0;
|
||||
if (!scriptVersionSnapshots.has(virtualCode.snapshot)) {
|
||||
version++;
|
||||
scriptVersions.set(uri, version);
|
||||
scriptVersionSnapshots.add(virtualCode.snapshot);
|
||||
}
|
||||
return {
|
||||
fileUri: sourceScript.id.toString(),
|
||||
virtualCodeId: virtualCode.id,
|
||||
languageId: virtualCode.languageId,
|
||||
embeddedCodes: virtualCode.embeddedCodes?.map(prune) || [],
|
||||
version,
|
||||
disabled: languageService.context.disabledEmbeddedDocumentUris.has(uri),
|
||||
};
|
||||
}
|
||||
});
|
||||
server.connection.onRequest(protocol_1.GetVirtualCodeRequest.type, async (params) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.fileUri);
|
||||
const languageService = (await project.getLanguageService(uri));
|
||||
const sourceScript = languageService.context.language.scripts.get(vscode_uri_1.URI.parse(params.fileUri));
|
||||
const virtualCode = sourceScript?.generated?.embeddedCodes.get(params.virtualCodeId);
|
||||
if (virtualCode) {
|
||||
const mappings = {};
|
||||
for (const [sourceScript, map] of languageService.context.language.maps.forEach(virtualCode)) {
|
||||
mappings[sourceScript.id.toString()] = map.mappings;
|
||||
}
|
||||
return {
|
||||
content: virtualCode.snapshot.getText(0, virtualCode.snapshot.getLength()),
|
||||
mappings,
|
||||
};
|
||||
}
|
||||
});
|
||||
server.connection.onNotification(protocol_1.WriteVirtualFilesNotification.type, async (params) => {
|
||||
// webpack compatibility
|
||||
const _require = eval('require');
|
||||
const fs = _require('fs');
|
||||
const uri = vscode_uri_1.URI.parse(params.uri);
|
||||
const languageService = (await project.getLanguageService(uri));
|
||||
const tsProject = languageService.context.project.typescript;
|
||||
if (tsProject) {
|
||||
const { languageServiceHost } = tsProject;
|
||||
for (const fileName of languageServiceHost.getScriptFileNames()) {
|
||||
if (!fs.existsSync(fileName)) {
|
||||
// global virtual files
|
||||
const snapshot = languageServiceHost.getScriptSnapshot(fileName);
|
||||
if (snapshot) {
|
||||
fs.writeFile(fileName, snapshot.getText(0, snapshot.getLength()), () => { });
|
||||
}
|
||||
}
|
||||
else {
|
||||
const uri = tsProject.uriConverter.asUri(fileName);
|
||||
const sourceScript = languageService.context.language.scripts.get(uri);
|
||||
if (sourceScript?.generated) {
|
||||
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
||||
if (serviceScript) {
|
||||
const { snapshot } = serviceScript.code;
|
||||
fs.writeFile(fileName + serviceScript.extension, snapshot.getText(0, snapshot.getLength()), () => { });
|
||||
}
|
||||
if (sourceScript.generated.languagePlugin.typescript?.getExtraServiceScripts) {
|
||||
for (const extraServiceScript of sourceScript.generated.languagePlugin.typescript.getExtraServiceScripts(uri.toString(), sourceScript.generated.root)) {
|
||||
const { snapshot } = extraServiceScript.code;
|
||||
fs.writeFile(fileName, snapshot.getText(0, snapshot.getLength()), () => { });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
server.connection.onRequest(protocol_1.LoadedTSFilesMetaRequest.type, async () => {
|
||||
const sourceFilesData = new Map();
|
||||
for (const languageService of await project.getExistingLanguageServices()) {
|
||||
const tsLanguageService = languageService.context.inject('typescript/languageService');
|
||||
const program = tsLanguageService?.getProgram();
|
||||
const tsProject = languageService.context.project.typescript;
|
||||
if (program && tsProject) {
|
||||
const { languageServiceHost, configFileName } = tsProject;
|
||||
const projectName = configFileName ?? (languageServiceHost.getCurrentDirectory() + '(inferred)');
|
||||
const sourceFiles = program.getSourceFiles() ?? [];
|
||||
for (const sourceFile of sourceFiles) {
|
||||
if (!sourceFilesData.has(sourceFile)) {
|
||||
let nodes = 0;
|
||||
sourceFile.forEachChild(function walk(node) {
|
||||
nodes++;
|
||||
node.forEachChild(walk);
|
||||
});
|
||||
sourceFilesData.set(sourceFile, {
|
||||
projectNames: [],
|
||||
size: nodes * 128,
|
||||
});
|
||||
}
|
||||
sourceFilesData.get(sourceFile).projectNames.push(projectName);
|
||||
}
|
||||
;
|
||||
}
|
||||
}
|
||||
const result = {
|
||||
inputs: {},
|
||||
outputs: {},
|
||||
};
|
||||
for (const [sourceFile, fileData] of sourceFilesData) {
|
||||
let key = fileData.projectNames.sort().join(', ');
|
||||
if (fileData.projectNames.length >= 2) {
|
||||
key = `Shared in ${fileData.projectNames.length} projects (${key})`;
|
||||
}
|
||||
result.outputs[key] ??= {
|
||||
imports: [],
|
||||
exports: [],
|
||||
entryPoint: '',
|
||||
inputs: {},
|
||||
bytes: 0,
|
||||
};
|
||||
result.outputs[key].inputs[sourceFile.fileName] = { bytesInOutput: fileData.size };
|
||||
}
|
||||
return result;
|
||||
});
|
||||
server.connection.onNotification(protocol_1.UpdateVirtualCodeStateNotification.type, async (params) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.fileUri);
|
||||
const languageService = await project.getLanguageService(uri);
|
||||
const virtualFileUri = languageService.context.encodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(params.fileUri), params.virtualCodeId);
|
||||
if (params.disabled) {
|
||||
languageService.context.disabledEmbeddedDocumentUris.set(virtualFileUri, true);
|
||||
}
|
||||
else {
|
||||
languageService.context.disabledEmbeddedDocumentUris.delete(virtualFileUri);
|
||||
}
|
||||
});
|
||||
server.connection.onNotification(protocol_1.UpdateServicePluginStateNotification.type, async (params) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.uri);
|
||||
const languageService = await project.getLanguageService(uri);
|
||||
const plugin = languageService.context.plugins[params.serviceId][1];
|
||||
if (params.disabled) {
|
||||
languageService.context.disabledServicePlugins.add(plugin);
|
||||
}
|
||||
else {
|
||||
languageService.context.disabledServicePlugins.delete(plugin);
|
||||
}
|
||||
});
|
||||
server.connection.onRequest(protocol_1.GetServicePluginsRequest.type, async (params) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.uri);
|
||||
const languageService = await project.getLanguageService(uri);
|
||||
const result = [];
|
||||
for (let pluginIndex = 0; pluginIndex < languageService.context.plugins.length; pluginIndex++) {
|
||||
const plugin = languageService.context.plugins[pluginIndex];
|
||||
result.push({
|
||||
id: pluginIndex,
|
||||
name: plugin[0].name,
|
||||
disabled: languageService.context.disabledServicePlugins.has(plugin[1]),
|
||||
features: Object.keys(plugin[1]),
|
||||
});
|
||||
}
|
||||
return result;
|
||||
});
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=editorFeatures.js.map
|
||||
8
node_modules/@volar/language-server/lib/features/fileSystem.d.ts
generated
vendored
Normal file
8
node_modules/@volar/language-server/lib/features/fileSystem.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { FileSystem } from '@volar/language-service';
|
||||
import { URI } from 'vscode-uri';
|
||||
export declare function register(documents: ReturnType<typeof import('./textDocuments').register>, fileWatcher: ReturnType<typeof import('./fileWatcher').register>): {
|
||||
readFile(uri: URI): string | Thenable<string | undefined>;
|
||||
stat(uri: URI): import("@volar/language-service").FileStat | Thenable<import("@volar/language-service").FileStat | undefined>;
|
||||
readDirectory(uri: URI): import("@volar/language-service").ProviderResult<[string, import("@volar/language-service").FileType][]>;
|
||||
install(scheme: string, provider: FileSystem): void;
|
||||
};
|
||||
61
node_modules/@volar/language-server/lib/features/fileSystem.js
generated
vendored
Normal file
61
node_modules/@volar/language-server/lib/features/fileSystem.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.register = register;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
const vscode = require("vscode-languageserver");
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
function register(documents, fileWatcher) {
|
||||
const providers = new Map();
|
||||
const readFileCache = (0, language_service_1.createUriMap)();
|
||||
const statCache = (0, language_service_1.createUriMap)();
|
||||
const readDirectoryCache = (0, language_service_1.createUriMap)();
|
||||
documents.onDidSave(({ document }) => {
|
||||
const uri = vscode_uri_1.URI.parse(document.uri);
|
||||
readFileCache.set(uri, document.getText());
|
||||
statCache.delete(uri);
|
||||
});
|
||||
fileWatcher.onDidChangeWatchedFiles(({ changes }) => {
|
||||
for (const change of changes) {
|
||||
const changeUri = vscode_uri_1.URI.parse(change.uri);
|
||||
const dir = vscode_uri_1.URI.parse(change.uri.substring(0, change.uri.lastIndexOf('/')));
|
||||
if (change.type === vscode.FileChangeType.Deleted) {
|
||||
readFileCache.set(changeUri, undefined);
|
||||
statCache.set(changeUri, undefined);
|
||||
readDirectoryCache.delete(dir);
|
||||
}
|
||||
else if (change.type === vscode.FileChangeType.Changed) {
|
||||
readFileCache.delete(changeUri);
|
||||
statCache.delete(changeUri);
|
||||
}
|
||||
else if (change.type === vscode.FileChangeType.Created) {
|
||||
readFileCache.delete(changeUri);
|
||||
statCache.delete(changeUri);
|
||||
readDirectoryCache.delete(dir);
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
readFile(uri) {
|
||||
if (!readFileCache.has(uri)) {
|
||||
readFileCache.set(uri, providers.get(uri.scheme)?.readFile(uri));
|
||||
}
|
||||
return readFileCache.get(uri);
|
||||
},
|
||||
stat(uri) {
|
||||
if (!statCache.has(uri)) {
|
||||
statCache.set(uri, providers.get(uri.scheme)?.stat(uri));
|
||||
}
|
||||
return statCache.get(uri);
|
||||
},
|
||||
readDirectory(uri) {
|
||||
if (!readDirectoryCache.has(uri)) {
|
||||
readDirectoryCache.set(uri, providers.get(uri.scheme)?.readDirectory(uri) ?? []);
|
||||
}
|
||||
return readDirectoryCache.get(uri);
|
||||
},
|
||||
install(scheme, provider) {
|
||||
providers.set(scheme, provider);
|
||||
},
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=fileSystem.js.map
|
||||
9
node_modules/@volar/language-server/lib/features/fileWatcher.d.ts
generated
vendored
Normal file
9
node_modules/@volar/language-server/lib/features/fileWatcher.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Disposable } from '@volar/language-service';
|
||||
import * as vscode from 'vscode-languageserver';
|
||||
import { LanguageServerState } from '../types';
|
||||
export declare function register(server: LanguageServerState): {
|
||||
watchFiles: (patterns: string[]) => Promise<Disposable>;
|
||||
onDidChangeWatchedFiles: (cb: vscode.NotificationHandler<vscode.DidChangeWatchedFilesParams>) => {
|
||||
dispose: () => void;
|
||||
};
|
||||
};
|
||||
63
node_modules/@volar/language-server/lib/features/fileWatcher.js
generated
vendored
Normal file
63
node_modules/@volar/language-server/lib/features/fileWatcher.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.register = register;
|
||||
const vscode = require("vscode-languageserver");
|
||||
function register(server) {
|
||||
let watchFilesDisposableCounter = 0;
|
||||
let watchFilesDisposable;
|
||||
const didChangeWatchedFilesCallbacks = new Set();
|
||||
return {
|
||||
watchFiles,
|
||||
onDidChangeWatchedFiles,
|
||||
};
|
||||
async function watchFiles(patterns) {
|
||||
const disposables = [];
|
||||
const didChangeWatchedFiles = server.initializeParams.capabilities.workspace?.didChangeWatchedFiles;
|
||||
const fileOperations = server.initializeParams.capabilities.workspace?.fileOperations;
|
||||
if (didChangeWatchedFiles) {
|
||||
if (watchFilesDisposableCounter === 0) {
|
||||
watchFilesDisposable = server.connection.onDidChangeWatchedFiles(e => {
|
||||
for (const cb of didChangeWatchedFilesCallbacks) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
watchFilesDisposableCounter++;
|
||||
disposables.push({
|
||||
dispose() {
|
||||
watchFilesDisposableCounter--;
|
||||
if (watchFilesDisposableCounter === 0) {
|
||||
watchFilesDisposable?.dispose();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (didChangeWatchedFiles?.dynamicRegistration) {
|
||||
disposables.push(await server.connection.client.register(vscode.DidChangeWatchedFilesNotification.type, {
|
||||
watchers: patterns.map(pattern => ({ globPattern: pattern })),
|
||||
}));
|
||||
}
|
||||
if (fileOperations?.dynamicRegistration && fileOperations.willRename) {
|
||||
disposables.push(await server.connection.client.register(vscode.WillRenameFilesRequest.type, {
|
||||
filters: patterns.map(pattern => ({ pattern: { glob: pattern } })),
|
||||
}));
|
||||
}
|
||||
return {
|
||||
dispose() {
|
||||
for (const disposable of disposables) {
|
||||
disposable.dispose();
|
||||
}
|
||||
disposables.length = 0;
|
||||
},
|
||||
};
|
||||
}
|
||||
function onDidChangeWatchedFiles(cb) {
|
||||
didChangeWatchedFilesCallbacks.add(cb);
|
||||
return {
|
||||
dispose: () => {
|
||||
didChangeWatchedFilesCallbacks.delete(cb);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=fileWatcher.js.map
|
||||
4
node_modules/@volar/language-server/lib/features/languageFeatures.d.ts
generated
vendored
Normal file
4
node_modules/@volar/language-server/lib/features/languageFeatures.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import type { LanguageServerState } from '../types.js';
|
||||
export declare function register(server: LanguageServerState, documents: ReturnType<typeof import('./textDocuments')['register']>, configurations: ReturnType<typeof import('./configurations')['register']>): {
|
||||
requestRefresh: (clearDiagnostics: boolean) => Promise<void>;
|
||||
};
|
||||
768
node_modules/@volar/language-server/lib/features/languageFeatures.js
generated
vendored
Normal file
768
node_modules/@volar/language-server/lib/features/languageFeatures.js
generated
vendored
Normal file
@@ -0,0 +1,768 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.register = register;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
const vscode = require("vscode-languageserver");
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
const protocol_1 = require("../../protocol");
|
||||
const reportedCapabilities = new Set();
|
||||
function register(server, documents, configurations) {
|
||||
// Diagnostics support
|
||||
let refreshReq = 0;
|
||||
let updateDiagnosticsBatchReq = 0;
|
||||
const refreshHandlers = [];
|
||||
server.onInitialize(serverCapabilities => {
|
||||
let lastCompleteUri;
|
||||
let lastCompleteLs;
|
||||
let lastCodeLensLs;
|
||||
let lastCodeActionLs;
|
||||
let lastCallHierarchyLs;
|
||||
let lastTypeHierarchyLs;
|
||||
let lastDocumentLinkLs;
|
||||
let lastInlayHintLs;
|
||||
let languageServiceToId = new WeakMap();
|
||||
let currentLanguageServiceId = 0;
|
||||
const languageServiceById = new Map();
|
||||
const { languageServicePlugins, project, initializeParams } = server;
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.selectionRangeProvider)) {
|
||||
serverCapabilities.selectionRangeProvider = true;
|
||||
server.connection.onSelectionRanges(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getSelectionRanges(uri, params.positions, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.foldingRangeProvider)) {
|
||||
serverCapabilities.foldingRangeProvider = true;
|
||||
server.connection.onFoldingRanges(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getFoldingRanges(uri, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.linkedEditingRangeProvider)) {
|
||||
serverCapabilities.linkedEditingRangeProvider = true;
|
||||
server.connection.languages.onLinkedEditingRange(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getLinkedEditingRanges(uri, params.position, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.colorProvider)) {
|
||||
serverCapabilities.colorProvider = true;
|
||||
server.connection.onDocumentColor(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getDocumentColors(uri, token);
|
||||
});
|
||||
});
|
||||
server.connection.onColorPresentation(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getColorPresentations(uri, params.color, params.range, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.documentSymbolProvider)) {
|
||||
serverCapabilities.documentSymbolProvider = true;
|
||||
server.connection.onDocumentSymbol(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getDocumentSymbols(uri, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.documentFormattingProvider)) {
|
||||
serverCapabilities.documentFormattingProvider = true;
|
||||
serverCapabilities.documentRangeFormattingProvider = true;
|
||||
server.connection.onDocumentFormatting(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getDocumentFormattingEdits(uri, params.options, undefined, undefined, token);
|
||||
});
|
||||
});
|
||||
server.connection.onDocumentRangeFormatting(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getDocumentFormattingEdits(uri, params.options, params.range, undefined, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.referencesProvider)) {
|
||||
serverCapabilities.referencesProvider = true;
|
||||
server.connection.onReferences(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getReferences(uri, params.position, { includeDeclaration: true }, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.implementationProvider)) {
|
||||
serverCapabilities.implementationProvider = true;
|
||||
server.connection.onImplementation(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
const definitions = await languageService.getImplementations(uri, params.position, token);
|
||||
return handleDefinitions(initializeParams, 'implementation', definitions ?? []);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.declarationProvider)) {
|
||||
serverCapabilities.declarationProvider = true;
|
||||
server.connection.onDeclaration(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
const definitions = await languageService.getDeclaration(uri, params.position, token);
|
||||
return handleDefinitions(initializeParams, 'declaration', definitions ?? []);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.definitionProvider)) {
|
||||
serverCapabilities.definitionProvider = true;
|
||||
server.connection.onDefinition(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
const definitions = await languageService.getDefinition(uri, params.position, token);
|
||||
return handleDefinitions(initializeParams, 'definition', definitions ?? []);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.typeDefinitionProvider)) {
|
||||
serverCapabilities.typeDefinitionProvider = true;
|
||||
server.connection.onTypeDefinition(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
const definitions = await languageService.getTypeDefinition(uri, params.position, token);
|
||||
return handleDefinitions(initializeParams, 'typeDefinition', definitions ?? []);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.callHierarchyProvider)) {
|
||||
serverCapabilities.callHierarchyProvider = true;
|
||||
server.connection.languages.callHierarchy.onPrepare(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
lastCallHierarchyLs = languageService;
|
||||
return languageService.getCallHierarchyItems(uri, params.position, token);
|
||||
}) ?? [];
|
||||
});
|
||||
server.connection.languages.callHierarchy.onIncomingCalls(async (params, token) => {
|
||||
return await lastCallHierarchyLs?.getCallHierarchyIncomingCalls(params.item, token) ?? [];
|
||||
});
|
||||
server.connection.languages.callHierarchy.onOutgoingCalls(async (params, token) => {
|
||||
return await lastCallHierarchyLs?.getCallHierarchyOutgoingCalls(params.item, token) ?? [];
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.typeHierarchyProvider)) {
|
||||
serverCapabilities.typeHierarchyProvider = true;
|
||||
server.connection.languages.typeHierarchy.onPrepare(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
lastTypeHierarchyLs = languageService;
|
||||
return languageService.getTypeHierarchyItems(uri, params.position, token);
|
||||
}) ?? [];
|
||||
});
|
||||
server.connection.languages.typeHierarchy.onSupertypes(async (params, token) => {
|
||||
return await lastTypeHierarchyLs?.getTypeHierarchySupertypes(params.item, token) ?? [];
|
||||
});
|
||||
server.connection.languages.typeHierarchy.onSubtypes(async (params, token) => {
|
||||
return await lastTypeHierarchyLs?.getTypeHierarchySubtypes(params.item, token) ?? [];
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.hoverProvider)) {
|
||||
serverCapabilities.hoverProvider = true;
|
||||
server.connection.onHover(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getHover(uri, params.position, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.documentHighlightProvider)) {
|
||||
serverCapabilities.documentHighlightProvider = true;
|
||||
server.connection.onDocumentHighlight(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getDocumentHighlights(uri, params.position, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.workspaceSymbolProvider)) {
|
||||
serverCapabilities.workspaceSymbolProvider = {};
|
||||
server.connection.onWorkspaceSymbol(async (params, token) => {
|
||||
let languageServices = await project.getExistingLanguageServices();
|
||||
if (!languageServices.length) {
|
||||
for (const document of documents.all()) {
|
||||
await project.getLanguageService(vscode_uri_1.URI.parse(document.uri));
|
||||
}
|
||||
languageServices = await project.getExistingLanguageServices();
|
||||
}
|
||||
const symbols = [];
|
||||
for (const languageService of languageServices) {
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
let languageServiceId = languageServiceToId.get(languageService);
|
||||
if (languageServiceId === undefined) {
|
||||
languageServiceId = currentLanguageServiceId;
|
||||
languageServiceToId.set(languageService, languageServiceId);
|
||||
languageServiceById.set(languageServiceId, new WeakRef(languageService));
|
||||
}
|
||||
const languageServiceResult = await languageService.getWorkspaceSymbols(params.query, token);
|
||||
for (const symbol of languageServiceResult) {
|
||||
symbol.data = {
|
||||
languageServiceId,
|
||||
originalData: symbol.data,
|
||||
};
|
||||
}
|
||||
symbols.push(...await languageService.getWorkspaceSymbols(params.query, token));
|
||||
}
|
||||
return symbols;
|
||||
});
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.workspaceSymbolProvider?.resolveProvider)) {
|
||||
serverCapabilities.workspaceSymbolProvider.resolveProvider = true;
|
||||
server.connection.onWorkspaceSymbolResolve(async (symbol, token) => {
|
||||
const languageServiceId = symbol.data?.languageServiceId;
|
||||
const languageService = languageServiceById.get(languageServiceId)?.deref();
|
||||
if (!languageService) {
|
||||
return symbol;
|
||||
}
|
||||
symbol.data = symbol.data?.originalData;
|
||||
return await languageService.resolveWorkspaceSymbol?.(symbol, token);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.renameProvider)) {
|
||||
serverCapabilities.renameProvider = {};
|
||||
server.connection.onRenameRequest(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getRenameEdits(uri, params.position, params.newName, token);
|
||||
});
|
||||
});
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.renameProvider?.prepareProvider)) {
|
||||
serverCapabilities.renameProvider.prepareProvider = true;
|
||||
server.connection.onPrepareRename(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
const result = await languageService.getRenameRange(uri, params.position, token);
|
||||
if (result && 'message' in result) {
|
||||
return new vscode.ResponseError(0, result.message);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.documentLinkProvider)) {
|
||||
serverCapabilities.documentLinkProvider = {};
|
||||
server.connection.onDocumentLinks(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
lastDocumentLinkLs = languageService;
|
||||
return languageService.getDocumentLinks(uri, token);
|
||||
});
|
||||
});
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.documentLinkProvider?.resolveProvider)) {
|
||||
serverCapabilities.documentLinkProvider.resolveProvider = true;
|
||||
server.connection.onDocumentLinkResolve(async (link, token) => {
|
||||
return await lastDocumentLinkLs?.resolveDocumentLink(link, token);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.codeLensProvider)) {
|
||||
serverCapabilities.codeLensProvider = {};
|
||||
server.connection.onCodeLens(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
lastCodeLensLs = languageService;
|
||||
return languageService.getCodeLenses(uri, token);
|
||||
});
|
||||
});
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.codeLensProvider?.resolveProvider)) {
|
||||
serverCapabilities.codeLensProvider.resolveProvider = true;
|
||||
server.connection.onCodeLensResolve(async (codeLens, token) => {
|
||||
return await lastCodeLensLs?.resolveCodeLens(codeLens, token) ?? codeLens;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.inlayHintProvider)) {
|
||||
serverCapabilities.inlayHintProvider = {};
|
||||
server.connection.languages.inlayHint.on(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
lastInlayHintLs = languageService;
|
||||
return languageService.getInlayHints(uri, params.range, token);
|
||||
});
|
||||
});
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.inlayHintProvider?.resolveProvider)) {
|
||||
serverCapabilities.inlayHintProvider.resolveProvider = true;
|
||||
server.connection.languages.inlayHint.resolve(async (hint, token) => {
|
||||
return await lastInlayHintLs?.resolveInlayHint(hint, token) ?? hint;
|
||||
});
|
||||
}
|
||||
refreshHandlers.push(() => {
|
||||
if (initializeParams.capabilities.workspace?.inlayHint?.refreshSupport) {
|
||||
server.connection.languages.inlayHint.refresh();
|
||||
}
|
||||
else {
|
||||
wranCapabilitiesNotSupported('workspace.inlayHint.refreshSupport');
|
||||
}
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.signatureHelpProvider)) {
|
||||
serverCapabilities.signatureHelpProvider = {
|
||||
triggerCharacters: [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.signatureHelpProvider?.triggerCharacters ?? []).flat())],
|
||||
retriggerCharacters: [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.signatureHelpProvider?.retriggerCharacters ?? []).flat())],
|
||||
};
|
||||
server.connection.onSignatureHelp(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getSignatureHelp(uri, params.position, params.context, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.completionProvider)) {
|
||||
serverCapabilities.completionProvider = {
|
||||
triggerCharacters: [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.completionProvider?.triggerCharacters ?? []).flat())],
|
||||
};
|
||||
server.connection.onCompletion(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
lastCompleteUri = params.textDocument.uri;
|
||||
lastCompleteLs = languageService;
|
||||
const list = await languageService.getCompletionItems(uri, params.position, params.context, token);
|
||||
list.items = list.items.map(item => handleCompletionItem(initializeParams, item));
|
||||
return list;
|
||||
});
|
||||
});
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.completionProvider?.resolveProvider)) {
|
||||
serverCapabilities.completionProvider.resolveProvider = true;
|
||||
server.connection.onCompletionResolve(async (item, token) => {
|
||||
if (lastCompleteUri && lastCompleteLs) {
|
||||
item = await lastCompleteLs.resolveCompletionItem(item, token);
|
||||
item = handleCompletionItem(initializeParams, item);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.semanticTokensProvider)) {
|
||||
serverCapabilities.semanticTokensProvider = {
|
||||
range: true,
|
||||
full: false, // TODO: enable it after testing
|
||||
legend: {
|
||||
tokenTypes: [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.semanticTokensProvider?.legend?.tokenTypes ?? []).flat())],
|
||||
tokenModifiers: [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.semanticTokensProvider?.legend?.tokenModifiers ?? []).flat())],
|
||||
},
|
||||
};
|
||||
server.connection.languages.semanticTokens.on(async (params, token, _, resultProgress) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
return await languageService?.getSemanticTokens(uri, undefined, serverCapabilities.semanticTokensProvider.legend, tokens => resultProgress?.report(tokens), token);
|
||||
}) ?? { data: [] };
|
||||
});
|
||||
server.connection.languages.semanticTokens.onRange(async (params, token, _, resultProgress) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
return await languageService?.getSemanticTokens(uri, params.range, serverCapabilities.semanticTokensProvider.legend, tokens => resultProgress?.report(tokens), token);
|
||||
}) ?? { data: [] };
|
||||
});
|
||||
refreshHandlers.push(() => {
|
||||
if (initializeParams.capabilities.workspace?.semanticTokens?.refreshSupport) {
|
||||
server.connection.languages.semanticTokens.refresh();
|
||||
}
|
||||
else {
|
||||
wranCapabilitiesNotSupported('workspace.semanticTokens.refreshSupport');
|
||||
}
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.codeActionProvider)) {
|
||||
serverCapabilities.codeActionProvider = {
|
||||
codeActionKinds: languageServicePlugins.some(({ capabilities }) => capabilities.codeActionProvider?.codeActionKinds)
|
||||
? [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.codeActionProvider?.codeActionKinds ?? []).flat())]
|
||||
: undefined,
|
||||
};
|
||||
server.connection.onCodeAction(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, async (languageService) => {
|
||||
lastCodeActionLs = languageService;
|
||||
let codeActions = await languageService.getCodeActions(uri, params.range, params.context, token) ?? [];
|
||||
for (const codeAction of codeActions) {
|
||||
if (codeAction.data && typeof codeAction.data === 'object') {
|
||||
codeAction.data.uri = params.textDocument.uri;
|
||||
}
|
||||
else {
|
||||
codeAction.data = { uri: params.textDocument.uri };
|
||||
}
|
||||
}
|
||||
if (!initializeParams.capabilities.textDocument?.codeAction?.disabledSupport
|
||||
&& codeActions.some(codeAction => !codeAction.disabled)) {
|
||||
codeActions = codeActions.filter(codeAction => !codeAction.disabled);
|
||||
wranCapabilitiesNotSupported('textDocument.codeAction.disabledSupport');
|
||||
}
|
||||
return codeActions;
|
||||
});
|
||||
});
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.codeActionProvider?.resolveProvider)) {
|
||||
serverCapabilities.codeActionProvider.resolveProvider = true;
|
||||
server.connection.onCodeActionResolve(async (codeAction, token) => {
|
||||
return await lastCodeActionLs?.resolveCodeAction(codeAction, token) ?? codeAction;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.documentOnTypeFormattingProvider)) {
|
||||
serverCapabilities.documentOnTypeFormattingProvider = {
|
||||
firstTriggerCharacter: [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.documentOnTypeFormattingProvider?.triggerCharacters ?? []).flat())][0],
|
||||
moreTriggerCharacter: [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.documentOnTypeFormattingProvider?.triggerCharacters ?? []).flat())].slice(1),
|
||||
};
|
||||
server.connection.onDocumentOnTypeFormatting(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getDocumentFormattingEdits(uri, params.options, undefined, params, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.executeCommandProvider)) {
|
||||
serverCapabilities.executeCommandProvider = {
|
||||
commands: [...new Set(languageServicePlugins.map(({ capabilities }) => capabilities.executeCommandProvider?.commands ?? []).flat())],
|
||||
};
|
||||
server.connection.onExecuteCommand(async (params, token) => {
|
||||
let languageServices = await project.getExistingLanguageServices();
|
||||
if (!languageServices.length) {
|
||||
for (const document of documents.all()) {
|
||||
await project.getLanguageService(vscode_uri_1.URI.parse(document.uri));
|
||||
}
|
||||
languageServices = await project.getExistingLanguageServices();
|
||||
}
|
||||
for (const languageService of languageServices) {
|
||||
if (languageService.executeCommand && languageService.commands.includes(params.command)) {
|
||||
try {
|
||||
return await languageService.executeCommand(params.command, params.arguments ?? [], token);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.monikerProvider)) {
|
||||
serverCapabilities.monikerProvider = true;
|
||||
server.connection.languages.moniker.on(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getMoniker(uri, params.position, token);
|
||||
}) ?? null;
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.inlineValueProvider)) {
|
||||
serverCapabilities.inlineValueProvider = true;
|
||||
server.connection.languages.inlineValue.on(async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getInlineValue(uri, params.range, params.context, token);
|
||||
});
|
||||
});
|
||||
refreshHandlers.push(() => {
|
||||
if (initializeParams.capabilities.workspace?.inlineValue?.refreshSupport) {
|
||||
server.connection.languages.inlineValue.refresh();
|
||||
}
|
||||
else {
|
||||
wranCapabilitiesNotSupported('workspace.inlineValue.refreshSupport');
|
||||
}
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.autoInsertionProvider)) {
|
||||
const triggerCharacterToConfigurationSections = new Map();
|
||||
const tryAdd = (char, section) => {
|
||||
let sectionSet = triggerCharacterToConfigurationSections.get(char);
|
||||
if (!sectionSet) {
|
||||
triggerCharacterToConfigurationSections.set(char, sectionSet = new Set());
|
||||
}
|
||||
if (section) {
|
||||
sectionSet.add(section);
|
||||
}
|
||||
};
|
||||
for (const { capabilities } of languageServicePlugins) {
|
||||
if (capabilities.autoInsertionProvider) {
|
||||
const { triggerCharacters, configurationSections } = capabilities.autoInsertionProvider;
|
||||
if (configurationSections) {
|
||||
if (configurationSections.length !== triggerCharacters.length) {
|
||||
throw new Error('configurationSections.length !== triggerCharacters.length');
|
||||
}
|
||||
for (let i = 0; i < configurationSections.length; i++) {
|
||||
tryAdd(triggerCharacters[i], configurationSections[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const char of triggerCharacters) {
|
||||
tryAdd(char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
serverCapabilities.experimental ??= {};
|
||||
serverCapabilities.experimental.autoInsertionProvider = {
|
||||
triggerCharacters: [],
|
||||
configurationSections: [],
|
||||
};
|
||||
for (const [char, sections] of triggerCharacterToConfigurationSections) {
|
||||
if (sections.size) {
|
||||
serverCapabilities.experimental.autoInsertionProvider.triggerCharacters.push(char);
|
||||
serverCapabilities.experimental.autoInsertionProvider.configurationSections.push([...sections]);
|
||||
}
|
||||
else {
|
||||
serverCapabilities.experimental.autoInsertionProvider.triggerCharacters.push(char);
|
||||
serverCapabilities.experimental.autoInsertionProvider.configurationSections.push(null);
|
||||
}
|
||||
}
|
||||
server.connection.onRequest(protocol_1.AutoInsertRequest.type, async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getAutoInsertSnippet(uri, params.selection, params.change, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.fileRenameEditsProvider)) {
|
||||
serverCapabilities.experimental ??= {};
|
||||
serverCapabilities.experimental.fileRenameEditsProvider = true;
|
||||
server.connection.workspace.onWillRenameFiles(async (params, token) => {
|
||||
const _edits = await Promise.all(params.files.map(async (file) => {
|
||||
const oldUri = vscode_uri_1.URI.parse(file.oldUri);
|
||||
const newUri = vscode_uri_1.URI.parse(file.newUri);
|
||||
return await worker(oldUri, token, languageService => {
|
||||
return languageService.getFileRenameEdits(oldUri, newUri, token) ?? null;
|
||||
}) ?? null;
|
||||
}));
|
||||
const edits = _edits.filter((edit) => !!edit);
|
||||
if (edits.length) {
|
||||
(0, language_service_1.mergeWorkspaceEdits)(edits[0], ...edits.slice(1));
|
||||
return edits[0];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.fileReferencesProvider)) {
|
||||
serverCapabilities.experimental ??= {};
|
||||
serverCapabilities.experimental.fileReferencesProvider = true;
|
||||
server.connection.onRequest(protocol_1.FindFileReferenceRequest.type, async (params, token) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
return await worker(uri, token, languageService => {
|
||||
return languageService.getFileReferences(uri, token);
|
||||
});
|
||||
});
|
||||
}
|
||||
if (languageServicePlugins.some(({ capabilities }) => capabilities.documentDropEditsProvider)) {
|
||||
serverCapabilities.experimental ??= {};
|
||||
serverCapabilities.experimental.documentDropEditsProvider = true;
|
||||
server.connection.onRequest(protocol_1.DocumentDropRequest.type, async ({ textDocument, position, dataTransfer }, token) => {
|
||||
const dataTransferMap = new Map();
|
||||
for (const item of dataTransfer) {
|
||||
dataTransferMap.set(item.mimeType, {
|
||||
value: item.value,
|
||||
asString() {
|
||||
return server.connection.sendRequest(protocol_1.DocumentDrop_DataTransferItemAsStringRequest.type, { mimeType: item.mimeType });
|
||||
},
|
||||
asFile() {
|
||||
if (item.file) {
|
||||
return {
|
||||
name: item.file.name,
|
||||
uri: item.file.uri,
|
||||
data() {
|
||||
return server.connection.sendRequest(protocol_1.DocumentDrop_DataTransferItemFileDataRequest.type, { mimeType: item.mimeType });
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
const uri = vscode_uri_1.URI.parse(textDocument.uri);
|
||||
const languageService = (await project.getLanguageService(uri));
|
||||
return languageService.getDocumentDropEdits(uri, position, dataTransferMap, token);
|
||||
});
|
||||
}
|
||||
// Diagnostic support
|
||||
const supportsDiagnosticPull = !!initializeParams.capabilities.workspace?.diagnostics;
|
||||
const diagnosticProvider = languageServicePlugins.some(({ capabilities }) => !!capabilities.diagnosticProvider);
|
||||
const interFileDependencies = languageServicePlugins.some(({ capabilities }) => capabilities.diagnosticProvider?.interFileDependencies);
|
||||
const workspaceDiagnostics = languageServicePlugins.some(({ capabilities }) => capabilities.diagnosticProvider?.workspaceDiagnostics);
|
||||
if (diagnosticProvider) {
|
||||
if (supportsDiagnosticPull && !interFileDependencies) {
|
||||
serverCapabilities.diagnosticProvider = {
|
||||
// Unreliable, see https://github.com/microsoft/vscode-languageserver-node/issues/848#issuecomment-2189521060
|
||||
interFileDependencies: false,
|
||||
workspaceDiagnostics,
|
||||
};
|
||||
refreshHandlers.push(() => {
|
||||
if (initializeParams.capabilities.workspace?.diagnostics?.refreshSupport) {
|
||||
server.connection.languages.diagnostics.refresh();
|
||||
}
|
||||
else {
|
||||
wranCapabilitiesNotSupported('workspace.diagnostics.refreshSupport');
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
documents.onDidChangeContent(({ document }) => {
|
||||
const changedDocument = documents.get(vscode_uri_1.URI.parse(document.uri));
|
||||
if (!changedDocument) {
|
||||
return;
|
||||
}
|
||||
if (interFileDependencies) {
|
||||
const remainingDocuments = [...documents.all()].filter(doc => doc !== changedDocument);
|
||||
updateDiagnosticsBatch(project, [changedDocument, ...remainingDocuments]);
|
||||
}
|
||||
else {
|
||||
updateDiagnosticsBatch(project, [changedDocument]);
|
||||
}
|
||||
});
|
||||
documents.onDidClose(({ document }) => {
|
||||
server.connection.sendDiagnostics({ uri: document.uri, diagnostics: [] });
|
||||
});
|
||||
configurations.onDidChange(() => requestRefresh(false));
|
||||
refreshHandlers.push(async (clearDiagnostics) => {
|
||||
if (clearDiagnostics) {
|
||||
for (const document of documents.all()) {
|
||||
server.connection.sendDiagnostics({ uri: document.uri, diagnostics: [] });
|
||||
}
|
||||
}
|
||||
await updateDiagnosticsBatch(project, [...documents.all()]);
|
||||
});
|
||||
}
|
||||
server.connection.languages.diagnostics.on(async (params, token, _workDoneProgressReporter, resultProgressReporter) => {
|
||||
const uri = vscode_uri_1.URI.parse(params.textDocument.uri);
|
||||
const result = await worker(uri, token, languageService => {
|
||||
return languageService.getDiagnostics(uri, errors => {
|
||||
// resultProgressReporter is undefined in vscode
|
||||
resultProgressReporter?.report({
|
||||
relatedDocuments: {
|
||||
[params.textDocument.uri]: {
|
||||
kind: vscode.DocumentDiagnosticReportKind.Full,
|
||||
items: errors,
|
||||
},
|
||||
},
|
||||
});
|
||||
}, token);
|
||||
});
|
||||
return {
|
||||
kind: vscode.DocumentDiagnosticReportKind.Full,
|
||||
items: result ?? [],
|
||||
};
|
||||
});
|
||||
}
|
||||
if (workspaceDiagnostics) {
|
||||
server.connection.languages.diagnostics.onWorkspace(async (_params, token) => {
|
||||
let languageServices = await project.getExistingLanguageServices();
|
||||
if (!languageServices.length) {
|
||||
for (const document of documents.all()) {
|
||||
await project.getLanguageService(vscode_uri_1.URI.parse(document.uri));
|
||||
}
|
||||
languageServices = await project.getExistingLanguageServices();
|
||||
}
|
||||
const items = [];
|
||||
for (const languageService of languageServices) {
|
||||
if (token.isCancellationRequested) {
|
||||
break;
|
||||
}
|
||||
const result = await languageService.getWorkspaceDiagnostics(token);
|
||||
items.push(...result);
|
||||
}
|
||||
return { items };
|
||||
});
|
||||
}
|
||||
});
|
||||
return { requestRefresh };
|
||||
async function requestRefresh(clearDiagnostics) {
|
||||
const req = ++refreshReq;
|
||||
const delay = 250;
|
||||
await sleep(delay);
|
||||
if (req !== refreshReq) {
|
||||
return;
|
||||
}
|
||||
for (const handler of refreshHandlers) {
|
||||
handler(clearDiagnostics);
|
||||
}
|
||||
}
|
||||
async function updateDiagnosticsBatch(project, documents) {
|
||||
const req = ++updateDiagnosticsBatchReq;
|
||||
const delay = 250;
|
||||
const token = {
|
||||
get isCancellationRequested() {
|
||||
return req !== updateDiagnosticsBatchReq;
|
||||
},
|
||||
onCancellationRequested: vscode.Event.None,
|
||||
};
|
||||
for (const doc of documents) {
|
||||
await sleep(delay);
|
||||
if (token.isCancellationRequested) {
|
||||
break;
|
||||
}
|
||||
await updateDiagnostics(project, vscode_uri_1.URI.parse(doc.uri), doc.version, token);
|
||||
}
|
||||
}
|
||||
async function updateDiagnostics(project, uri, version, token) {
|
||||
const languageService = await project.getLanguageService(uri);
|
||||
const diagnostics = await languageService.getDiagnostics(uri, diagnostics => server.connection.sendDiagnostics({ uri: uri.toString(), diagnostics, version }), token);
|
||||
if (!token.isCancellationRequested) {
|
||||
server.connection.sendDiagnostics({ uri: uri.toString(), diagnostics, version });
|
||||
}
|
||||
}
|
||||
function worker(uri, token, cb) {
|
||||
return new Promise(resolve => {
|
||||
server.env.timer.setImmediate(async () => {
|
||||
if (token.isCancellationRequested) {
|
||||
resolve(undefined);
|
||||
return;
|
||||
}
|
||||
const languageService = (await server.project.getLanguageService((0, language_service_1.decodeEmbeddedDocumentUri)(uri)?.[0] ?? uri));
|
||||
const result = await cb(languageService);
|
||||
if (token.isCancellationRequested) {
|
||||
resolve(undefined);
|
||||
return;
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
function handleCompletionItem(initializeParams, item) {
|
||||
const snippetSupport = initializeParams.capabilities.textDocument?.completion?.completionItem?.snippetSupport ?? false;
|
||||
const insertReplaceSupport = initializeParams.capabilities.textDocument?.completion?.completionItem?.insertReplaceSupport ?? false;
|
||||
if (!snippetSupport && item.insertTextFormat === vscode.InsertTextFormat.Snippet) {
|
||||
item.insertTextFormat = vscode.InsertTextFormat.PlainText;
|
||||
if (item.insertText) {
|
||||
item.insertText = item.insertText.replace(/\$\d+/g, '');
|
||||
item.insertText = item.insertText.replace(/\${\d+:([^}]*)}/g, '');
|
||||
}
|
||||
wranCapabilitiesNotSupported('textDocument.completion.completionItem.snippetSupport');
|
||||
}
|
||||
if (!insertReplaceSupport && item.textEdit && vscode.InsertReplaceEdit.is(item.textEdit)) {
|
||||
item.textEdit = vscode.TextEdit.replace(item.textEdit.insert, item.textEdit.newText);
|
||||
wranCapabilitiesNotSupported('textDocument.completion.completionItem.insertReplaceSupport');
|
||||
}
|
||||
return item;
|
||||
}
|
||||
function handleDefinitions(initializeParams, type, items) {
|
||||
const linkSupport = initializeParams.capabilities.textDocument?.[type]?.linkSupport ?? false;
|
||||
if (!linkSupport) {
|
||||
wranCapabilitiesNotSupported(`textDocument.${type}.linkSupport`);
|
||||
return items.map(item => ({
|
||||
uri: item.targetUri,
|
||||
range: item.targetRange,
|
||||
}));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
function wranCapabilitiesNotSupported(path) {
|
||||
if (reportedCapabilities.has(path)) {
|
||||
return;
|
||||
}
|
||||
reportedCapabilities.add(path);
|
||||
console.warn(`${path} is not supported by the client but could be used by the server.`);
|
||||
}
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
//# sourceMappingURL=languageFeatures.js.map
|
||||
12
node_modules/@volar/language-server/lib/features/textDocuments.d.ts
generated
vendored
Normal file
12
node_modules/@volar/language-server/lib/features/textDocuments.d.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import * as vscode from 'vscode-languageserver';
|
||||
import { URI } from 'vscode-uri';
|
||||
import { LanguageServerState } from '../types';
|
||||
import { SnapshotDocument } from '../utils/snapshotDocument';
|
||||
export declare function register(server: LanguageServerState): {
|
||||
all: () => SnapshotDocument[];
|
||||
onDidChangeContent: vscode.Event<vscode.TextDocumentChangeEvent<SnapshotDocument>>;
|
||||
onDidOpen: vscode.Event<vscode.TextDocumentChangeEvent<SnapshotDocument>>;
|
||||
onDidClose: vscode.Event<vscode.TextDocumentChangeEvent<SnapshotDocument>>;
|
||||
onDidSave: vscode.Event<vscode.TextDocumentChangeEvent<SnapshotDocument>>;
|
||||
get(uri: URI): SnapshotDocument | undefined;
|
||||
};
|
||||
54
node_modules/@volar/language-server/lib/features/textDocuments.js
generated
vendored
Normal file
54
node_modules/@volar/language-server/lib/features/textDocuments.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.register = register;
|
||||
const vscode = require("vscode-languageserver");
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
const snapshotDocument_1 = require("../utils/snapshotDocument");
|
||||
function register(server) {
|
||||
const syncedDocumentParsedUriToUri = new Map();
|
||||
const documentsCache = new Map();
|
||||
const documents = new vscode.TextDocuments({
|
||||
create(uri, languageId, version, text) {
|
||||
const cache = documentsCache.get(uri)?.deref();
|
||||
if (cache && cache.languageId === languageId && cache.version === version && cache.getText() === text) {
|
||||
return cache;
|
||||
}
|
||||
const document = new snapshotDocument_1.SnapshotDocument(uri, languageId, version, text);
|
||||
documentsCache.set(uri, new WeakRef(document));
|
||||
return document;
|
||||
},
|
||||
update(snapshot, contentChanges, version) {
|
||||
snapshot.update(contentChanges, version);
|
||||
return snapshot;
|
||||
},
|
||||
});
|
||||
documents.listen(server.connection);
|
||||
documents.onDidOpen(({ document }) => {
|
||||
const parsedUri = vscode_uri_1.URI.parse(document.uri);
|
||||
syncedDocumentParsedUriToUri.set(parsedUri.toString(), document.uri);
|
||||
});
|
||||
documents.onDidClose(({ document }) => {
|
||||
const parsedUri = vscode_uri_1.URI.parse(document.uri);
|
||||
syncedDocumentParsedUriToUri.delete(parsedUri.toString());
|
||||
});
|
||||
server.onInitialize(serverCapabilities => {
|
||||
serverCapabilities.textDocumentSync = vscode.TextDocumentSyncKind.Incremental;
|
||||
});
|
||||
return {
|
||||
all: documents.all.bind(documents),
|
||||
onDidChangeContent: documents.onDidChangeContent.bind(documents),
|
||||
onDidOpen: documents.onDidOpen.bind(documents),
|
||||
onDidClose: documents.onDidClose.bind(documents),
|
||||
onDidSave: documents.onDidSave.bind(documents),
|
||||
get(uri) {
|
||||
return documents.get(getSyncedDocumentKey(uri) ?? uri.toString());
|
||||
},
|
||||
};
|
||||
function getSyncedDocumentKey(uri) {
|
||||
const originalUri = syncedDocumentParsedUriToUri.get(uri.toString());
|
||||
if (originalUri) {
|
||||
return originalUri;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=textDocuments.js.map
|
||||
10
node_modules/@volar/language-server/lib/features/workspaceFolders.d.ts
generated
vendored
Normal file
10
node_modules/@volar/language-server/lib/features/workspaceFolders.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import * as vscode from 'vscode-languageserver';
|
||||
import { URI } from 'vscode-uri';
|
||||
import { LanguageServerState } from '../types';
|
||||
export declare function register(server: LanguageServerState): {
|
||||
readonly all: URI[];
|
||||
has(uri: URI): boolean;
|
||||
onDidChange: (cb: vscode.NotificationHandler<vscode.WorkspaceFoldersChangeEvent>) => {
|
||||
dispose(): void;
|
||||
};
|
||||
};
|
||||
67
node_modules/@volar/language-server/lib/features/workspaceFolders.js
generated
vendored
Normal file
67
node_modules/@volar/language-server/lib/features/workspaceFolders.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.register = register;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
function register(server) {
|
||||
const folders = (0, language_service_1.createUriMap)();
|
||||
const didChangeCallbacks = new Set();
|
||||
server.onInitialize(serverCapabilities => {
|
||||
const { initializeParams } = server;
|
||||
if (initializeParams.workspaceFolders?.length) {
|
||||
for (const folder of initializeParams.workspaceFolders) {
|
||||
folders.set(vscode_uri_1.URI.parse(folder.uri), true);
|
||||
}
|
||||
}
|
||||
else if (initializeParams.rootUri) {
|
||||
folders.set(vscode_uri_1.URI.parse(initializeParams.rootUri), true);
|
||||
}
|
||||
else if (initializeParams.rootPath) {
|
||||
folders.set(vscode_uri_1.URI.file(initializeParams.rootPath), true);
|
||||
}
|
||||
// #18
|
||||
serverCapabilities.workspace ??= {};
|
||||
serverCapabilities.workspace.workspaceFolders = {
|
||||
supported: true,
|
||||
changeNotifications: true,
|
||||
};
|
||||
});
|
||||
server.onInitialized(() => {
|
||||
if (server.initializeParams.capabilities.workspace?.workspaceFolders) {
|
||||
server.connection.workspace.onDidChangeWorkspaceFolders(e => {
|
||||
e.added = e.added.filter(folder => !folders.has(vscode_uri_1.URI.parse(folder.uri)));
|
||||
e.removed = e.removed.filter(folder => folders.has(vscode_uri_1.URI.parse(folder.uri)));
|
||||
if (e.added.length || e.removed.length) {
|
||||
for (const folder of e.added) {
|
||||
folders.set(vscode_uri_1.URI.parse(folder.uri), true);
|
||||
}
|
||||
for (const folder of e.removed) {
|
||||
folders.delete(vscode_uri_1.URI.parse(folder.uri));
|
||||
}
|
||||
server.project.reload();
|
||||
for (const cb of didChangeCallbacks) {
|
||||
cb(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return {
|
||||
get all() {
|
||||
return [...folders.keys()];
|
||||
},
|
||||
has(uri) {
|
||||
return folders.has(uri);
|
||||
},
|
||||
onDidChange,
|
||||
};
|
||||
function onDidChange(cb) {
|
||||
didChangeCallbacks.add(cb);
|
||||
return {
|
||||
dispose() {
|
||||
didChangeCallbacks.delete(cb);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=workspaceFolders.js.map
|
||||
6
node_modules/@volar/language-server/lib/fileSystemProviders/http.d.ts
generated
vendored
Normal file
6
node_modules/@volar/language-server/lib/fileSystemProviders/http.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { FileSystem } from '@volar/language-service';
|
||||
import type { URI } from 'vscode-uri';
|
||||
import { LanguageServer } from '../types';
|
||||
export declare const provider: FileSystem;
|
||||
export declare function listenEditorSettings(server: LanguageServer): void;
|
||||
export declare function handler(uri: URI): Promise<string | undefined>;
|
||||
46
node_modules/@volar/language-server/lib/fileSystemProviders/http.js
generated
vendored
Normal file
46
node_modules/@volar/language-server/lib/fileSystemProviders/http.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.provider = void 0;
|
||||
exports.listenEditorSettings = listenEditorSettings;
|
||||
exports.handler = handler;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
const request_light_1 = require("request-light");
|
||||
exports.provider = {
|
||||
async stat(uri) {
|
||||
const text = await this.readFile(uri);
|
||||
if (text !== undefined) {
|
||||
return {
|
||||
type: language_service_1.FileType.File,
|
||||
size: text.length,
|
||||
ctime: 0,
|
||||
mtime: 0,
|
||||
};
|
||||
}
|
||||
},
|
||||
readFile(uri) {
|
||||
return handler(uri);
|
||||
},
|
||||
readDirectory() {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
function listenEditorSettings(server) {
|
||||
server.configurations.onDidChange(updateHttpSettings);
|
||||
updateHttpSettings();
|
||||
async function updateHttpSettings() {
|
||||
const httpSettings = await server.configurations.get('http');
|
||||
(0, request_light_1.configure)(httpSettings?.proxy, httpSettings?.proxyStrictSSL ?? false);
|
||||
}
|
||||
}
|
||||
function handler(uri) {
|
||||
const headers = { 'Accept-Encoding': 'gzip, deflate' };
|
||||
return (0, request_light_1.xhr)({ url: uri.toString(true), followRedirects: 5, headers }).then(response => {
|
||||
if (response.status !== 200) {
|
||||
return;
|
||||
}
|
||||
return response.responseText;
|
||||
}, (error) => {
|
||||
return Promise.reject(error.responseText || (0, request_light_1.getErrorStatusDescription)(error.status) || error.toString());
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=http.js.map
|
||||
2
node_modules/@volar/language-server/lib/fileSystemProviders/node.d.ts
generated
vendored
Normal file
2
node_modules/@volar/language-server/lib/fileSystemProviders/node.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { FileSystem } from '@volar/language-service';
|
||||
export declare const provider: FileSystem;
|
||||
49
node_modules/@volar/language-server/lib/fileSystemProviders/node.js
generated
vendored
Normal file
49
node_modules/@volar/language-server/lib/fileSystemProviders/node.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.provider = void 0;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
const fs = require("fs");
|
||||
exports.provider = {
|
||||
stat(uri) {
|
||||
try {
|
||||
const stats = fs.statSync(uri.fsPath, { throwIfNoEntry: false });
|
||||
if (stats) {
|
||||
return {
|
||||
type: stats.isFile() ? language_service_1.FileType.File
|
||||
: stats.isDirectory() ? language_service_1.FileType.Directory
|
||||
: stats.isSymbolicLink() ? language_service_1.FileType.SymbolicLink
|
||||
: language_service_1.FileType.Unknown,
|
||||
ctime: stats.ctimeMs,
|
||||
mtime: stats.mtimeMs,
|
||||
size: stats.size,
|
||||
};
|
||||
}
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
readFile(uri, encoding) {
|
||||
try {
|
||||
return fs.readFileSync(uri.fsPath, { encoding: encoding ?? 'utf-8' });
|
||||
}
|
||||
catch {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
readDirectory(uri) {
|
||||
try {
|
||||
const files = fs.readdirSync(uri.fsPath, { withFileTypes: true });
|
||||
return files.map(file => {
|
||||
return [file.name, file.isFile() ? language_service_1.FileType.File
|
||||
: file.isDirectory() ? language_service_1.FileType.Directory
|
||||
: file.isSymbolicLink() ? language_service_1.FileType.SymbolicLink
|
||||
: language_service_1.FileType.Unknown];
|
||||
});
|
||||
}
|
||||
catch {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=node.js.map
|
||||
3
node_modules/@volar/language-server/lib/project/inferredCompilerOptions.d.ts
generated
vendored
Normal file
3
node_modules/@volar/language-server/lib/project/inferredCompilerOptions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import type * as ts from 'typescript';
|
||||
import type { LanguageServer } from '../types';
|
||||
export declare function getInferredCompilerOptions(server: LanguageServer): Promise<ts.CompilerOptions>;
|
||||
65
node_modules/@volar/language-server/lib/project/inferredCompilerOptions.js
generated
vendored
Normal file
65
node_modules/@volar/language-server/lib/project/inferredCompilerOptions.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getInferredCompilerOptions = getInferredCompilerOptions;
|
||||
async function getInferredCompilerOptions(server) {
|
||||
const [implicitProjectConfig_1 = {}, implicitProjectConfig_2 = {},] = await Promise.all([
|
||||
server.configurations.get('js/ts.implicitProjectConfig'),
|
||||
server.configurations.get('javascript.implicitProjectConfig'),
|
||||
]);
|
||||
const checkJs = readCheckJs();
|
||||
const experimentalDecorators = readExperimentalDecorators();
|
||||
const strictNullChecks = readImplicitStrictNullChecks();
|
||||
const strictFunctionTypes = readImplicitStrictFunctionTypes();
|
||||
const options = {
|
||||
...inferredProjectCompilerOptions('typescript'),
|
||||
allowJs: true,
|
||||
allowSyntheticDefaultImports: true,
|
||||
allowNonTsExtensions: true,
|
||||
resolveJsonModule: true,
|
||||
jsx: 1,
|
||||
};
|
||||
return options;
|
||||
function readCheckJs() {
|
||||
return implicitProjectConfig_1['checkJs']
|
||||
?? implicitProjectConfig_2['checkJs']
|
||||
?? false;
|
||||
}
|
||||
function readExperimentalDecorators() {
|
||||
return implicitProjectConfig_1['experimentalDecorators']
|
||||
?? implicitProjectConfig_2['experimentalDecorators']
|
||||
?? false;
|
||||
}
|
||||
function readImplicitStrictNullChecks() {
|
||||
return implicitProjectConfig_1['strictNullChecks'] ?? false;
|
||||
}
|
||||
function readImplicitStrictFunctionTypes() {
|
||||
return implicitProjectConfig_1['strictFunctionTypes'] ?? true;
|
||||
}
|
||||
function inferredProjectCompilerOptions(projectType) {
|
||||
const projectConfig = {
|
||||
module: 1,
|
||||
target: 7,
|
||||
jsx: 1,
|
||||
};
|
||||
if (checkJs) {
|
||||
projectConfig.checkJs = true;
|
||||
if (projectType === 'typescript') {
|
||||
projectConfig.allowJs = true;
|
||||
}
|
||||
}
|
||||
if (experimentalDecorators) {
|
||||
projectConfig.experimentalDecorators = true;
|
||||
}
|
||||
if (strictNullChecks) {
|
||||
projectConfig.strictNullChecks = true;
|
||||
}
|
||||
if (strictFunctionTypes) {
|
||||
projectConfig.strictFunctionTypes = true;
|
||||
}
|
||||
if (projectType === 'typescript') {
|
||||
projectConfig.sourceMap = true;
|
||||
}
|
||||
return projectConfig;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=inferredCompilerOptions.js.map
|
||||
5
node_modules/@volar/language-server/lib/project/simpleProject.d.ts
generated
vendored
Normal file
5
node_modules/@volar/language-server/lib/project/simpleProject.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { LanguagePlugin, LanguageServiceEnvironment } from '@volar/language-service';
|
||||
import type { URI } from 'vscode-uri';
|
||||
import type { LanguageServer, LanguageServerProject } from '../types';
|
||||
export declare function createSimpleProject(languagePlugins: LanguagePlugin<URI>[]): LanguageServerProject;
|
||||
export declare function createLanguageServiceEnvironment(server: LanguageServer, workspaceFolders: URI[]): LanguageServiceEnvironment;
|
||||
49
node_modules/@volar/language-server/lib/project/simpleProject.js
generated
vendored
Normal file
49
node_modules/@volar/language-server/lib/project/simpleProject.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createSimpleProject = createSimpleProject;
|
||||
exports.createLanguageServiceEnvironment = createLanguageServiceEnvironment;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
function createSimpleProject(languagePlugins) {
|
||||
let server;
|
||||
let languageService;
|
||||
return {
|
||||
setup(_server) {
|
||||
server = _server;
|
||||
const language = (0, language_service_1.createLanguage)([
|
||||
{ getLanguageId: uri => server.documents.get(uri)?.languageId },
|
||||
...languagePlugins,
|
||||
], (0, language_service_1.createUriMap)(false), uri => {
|
||||
const document = server.documents.get(uri);
|
||||
if (document) {
|
||||
language.scripts.set(uri, document.getSnapshot(), document.languageId);
|
||||
}
|
||||
else {
|
||||
language.scripts.delete(uri);
|
||||
}
|
||||
});
|
||||
languageService = (0, language_service_1.createLanguageService)(language, server.languageServicePlugins, createLanguageServiceEnvironment(server, server.workspaceFolders.all), {});
|
||||
},
|
||||
getLanguageService() {
|
||||
return languageService;
|
||||
},
|
||||
getExistingLanguageServices() {
|
||||
return [languageService];
|
||||
},
|
||||
reload() {
|
||||
languageService.dispose();
|
||||
this.setup(server);
|
||||
},
|
||||
};
|
||||
}
|
||||
function createLanguageServiceEnvironment(server, workspaceFolders) {
|
||||
return {
|
||||
workspaceFolders,
|
||||
fs: server.fileSystem,
|
||||
locale: server.initializeParams?.locale,
|
||||
clientCapabilities: server.initializeParams?.capabilities,
|
||||
getConfiguration: server.configurations.get,
|
||||
onDidChangeConfiguration: server.configurations.onDidChange,
|
||||
onDidChangeWatchedFiles: server.fileWatcher.onDidChangeWatchedFiles,
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=simpleProject.js.map
|
||||
22
node_modules/@volar/language-server/lib/project/typescriptProject.d.ts
generated
vendored
Normal file
22
node_modules/@volar/language-server/lib/project/typescriptProject.d.ts
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Language, LanguagePlugin, ProjectContext, ProviderResult } from '@volar/language-service';
|
||||
import type * as ts from 'typescript';
|
||||
import { URI } from 'vscode-uri';
|
||||
import type { LanguageServerProject } from '../types';
|
||||
import { ProjectExposeContext } from './typescriptProjectLs';
|
||||
export declare function createTypeScriptProject(ts: typeof import('typescript'), tsLocalized: ts.MapLike<string> | undefined, create: (projectContext: ProjectExposeContext) => ProviderResult<{
|
||||
languagePlugins: LanguagePlugin<URI>[];
|
||||
setup?(options: {
|
||||
language: Language;
|
||||
project: ProjectContext;
|
||||
}): void;
|
||||
}>): LanguageServerProject;
|
||||
export declare function createUriConverter(rootFolders: URI[]): {
|
||||
asFileName: (parsed: URI) => string;
|
||||
asUri: (fileName: string) => URI;
|
||||
};
|
||||
export declare function sortTSConfigs(file: string, a: string, b: string): number;
|
||||
export declare function isFileInDir(fileName: string, dir: string): boolean;
|
||||
export declare function getWorkspaceFolder(uri: URI, workspaceFolders: {
|
||||
has(uri: URI): boolean;
|
||||
all: URI[];
|
||||
}): URI;
|
||||
306
node_modules/@volar/language-server/lib/project/typescriptProject.js
generated
vendored
Normal file
306
node_modules/@volar/language-server/lib/project/typescriptProject.js
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createTypeScriptProject = createTypeScriptProject;
|
||||
exports.createUriConverter = createUriConverter;
|
||||
exports.sortTSConfigs = sortTSConfigs;
|
||||
exports.isFileInDir = isFileInDir;
|
||||
exports.getWorkspaceFolder = getWorkspaceFolder;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
const path = require("path-browserify");
|
||||
const vscode = require("vscode-languageserver");
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
const inferredCompilerOptions_1 = require("./inferredCompilerOptions");
|
||||
const simpleProject_1 = require("./simpleProject");
|
||||
const typescriptProjectLs_1 = require("./typescriptProjectLs");
|
||||
const rootTsConfigNames = ['tsconfig.json', 'jsconfig.json'];
|
||||
function createTypeScriptProject(ts, tsLocalized, create) {
|
||||
let server;
|
||||
let uriConverter;
|
||||
const configProjects = (0, language_service_1.createUriMap)();
|
||||
const inferredProjects = (0, language_service_1.createUriMap)();
|
||||
const rootTsConfigs = new Set();
|
||||
const searchedDirs = new Set();
|
||||
return {
|
||||
setup(_server) {
|
||||
uriConverter = createUriConverter(_server.workspaceFolders.all);
|
||||
server = _server;
|
||||
server.fileWatcher.onDidChangeWatchedFiles(({ changes }) => {
|
||||
const tsConfigChanges = changes.filter(change => rootTsConfigNames.includes(change.uri.substring(change.uri.lastIndexOf('/') + 1)));
|
||||
for (const change of tsConfigChanges) {
|
||||
const changeUri = vscode_uri_1.URI.parse(change.uri);
|
||||
const changeFileName = uriConverter.asFileName(changeUri);
|
||||
if (change.type === vscode.FileChangeType.Created) {
|
||||
rootTsConfigs.add(changeFileName);
|
||||
}
|
||||
else if ((change.type === vscode.FileChangeType.Changed || change.type === vscode.FileChangeType.Deleted) && configProjects.has(changeUri)) {
|
||||
if (change.type === vscode.FileChangeType.Deleted) {
|
||||
rootTsConfigs.delete(changeFileName);
|
||||
}
|
||||
const project = configProjects.get(changeUri);
|
||||
configProjects.delete(changeUri);
|
||||
project?.then(project => project.dispose());
|
||||
}
|
||||
}
|
||||
server.languageFeatures.requestRefresh(!!tsConfigChanges.length);
|
||||
});
|
||||
},
|
||||
async getLanguageService(uri) {
|
||||
const tsconfig = await findMatchTSConfig(server, uri);
|
||||
if (tsconfig) {
|
||||
const project = await getOrCreateConfiguredProject(server, tsconfig);
|
||||
return project.languageService;
|
||||
}
|
||||
const workspaceFolder = getWorkspaceFolder(uri, server.workspaceFolders);
|
||||
const project = await getOrCreateInferredProject(server, uri, workspaceFolder);
|
||||
return project.languageService;
|
||||
},
|
||||
async getExistingLanguageServices() {
|
||||
const projects = await Promise.all([
|
||||
...configProjects.values() ?? [],
|
||||
...inferredProjects.values() ?? [],
|
||||
]);
|
||||
return projects.map(project => project.languageService);
|
||||
},
|
||||
reload() {
|
||||
for (const project of [
|
||||
...configProjects.values() ?? [],
|
||||
...inferredProjects.values() ?? [],
|
||||
]) {
|
||||
project.then(p => p.dispose());
|
||||
}
|
||||
configProjects.clear();
|
||||
inferredProjects.clear();
|
||||
},
|
||||
};
|
||||
async function findMatchTSConfig(server, uri) {
|
||||
const fileName = uriConverter.asFileName(uri);
|
||||
let dir = path.dirname(fileName);
|
||||
while (true) {
|
||||
if (searchedDirs.has(dir)) {
|
||||
break;
|
||||
}
|
||||
searchedDirs.add(dir);
|
||||
for (const tsConfigName of rootTsConfigNames) {
|
||||
const tsconfigPath = path.join(dir, tsConfigName);
|
||||
if ((await server.fileSystem.stat?.(uriConverter.asUri(tsconfigPath)))?.type === language_service_1.FileType.File) {
|
||||
rootTsConfigs.add(tsconfigPath);
|
||||
}
|
||||
}
|
||||
dir = path.dirname(dir);
|
||||
}
|
||||
await prepareClosestootCommandLine();
|
||||
return await findDirectIncludeTsconfig() ?? await findIndirectReferenceTsconfig();
|
||||
async function prepareClosestootCommandLine() {
|
||||
let matches = [];
|
||||
for (const rootTsConfig of rootTsConfigs) {
|
||||
if (isFileInDir(fileName, path.dirname(rootTsConfig))) {
|
||||
matches.push(rootTsConfig);
|
||||
}
|
||||
}
|
||||
matches = matches.sort((a, b) => sortTSConfigs(fileName, a, b));
|
||||
if (matches.length) {
|
||||
await getCommandLine(matches[0]);
|
||||
}
|
||||
}
|
||||
function findIndirectReferenceTsconfig() {
|
||||
return findTSConfig(async (tsconfig) => {
|
||||
const tsconfigUri = uriConverter.asUri(tsconfig);
|
||||
const project = await configProjects.get(tsconfigUri);
|
||||
const languageService = project?.languageService.context.inject('typescript/languageService');
|
||||
return !!languageService?.getProgram()?.getSourceFile(fileName);
|
||||
});
|
||||
}
|
||||
function findDirectIncludeTsconfig() {
|
||||
return findTSConfig(async (tsconfig) => {
|
||||
const map = (0, language_service_1.createUriMap)();
|
||||
const commandLine = await getCommandLine(tsconfig);
|
||||
for (const fileName of commandLine?.fileNames ?? []) {
|
||||
const uri = uriConverter.asUri(fileName);
|
||||
map.set(uri, true);
|
||||
}
|
||||
return map.has(uri);
|
||||
});
|
||||
}
|
||||
async function findTSConfig(match) {
|
||||
const checked = new Set();
|
||||
for (const rootTsConfig of [...rootTsConfigs].sort((a, b) => sortTSConfigs(fileName, a, b))) {
|
||||
const tsconfigUri = uriConverter.asUri(rootTsConfig);
|
||||
const project = await configProjects.get(tsconfigUri);
|
||||
if (project) {
|
||||
let chains = await getReferencesChains(project.getCommandLine(), rootTsConfig, []);
|
||||
// This is to be consistent with tsserver behavior
|
||||
chains = chains.reverse();
|
||||
for (const chain of chains) {
|
||||
for (let i = chain.length - 1; i >= 0; i--) {
|
||||
const tsconfig = chain[i];
|
||||
if (checked.has(tsconfig)) {
|
||||
continue;
|
||||
}
|
||||
checked.add(tsconfig);
|
||||
if (await match(tsconfig)) {
|
||||
return tsconfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async function getReferencesChains(commandLine, tsConfig, before) {
|
||||
if (commandLine.projectReferences?.length) {
|
||||
const newChains = [];
|
||||
for (const projectReference of commandLine.projectReferences) {
|
||||
let tsConfigPath = projectReference.path.replace(/\\/g, '/');
|
||||
// fix https://github.com/johnsoncodehk/volar/issues/712
|
||||
if ((await server.fileSystem.stat?.(uriConverter.asUri(tsConfigPath)))?.type === language_service_1.FileType.File) {
|
||||
const newTsConfigPath = path.join(tsConfigPath, 'tsconfig.json');
|
||||
const newJsConfigPath = path.join(tsConfigPath, 'jsconfig.json');
|
||||
if ((await server.fileSystem.stat?.(uriConverter.asUri(newTsConfigPath)))?.type === language_service_1.FileType.File) {
|
||||
tsConfigPath = newTsConfigPath;
|
||||
}
|
||||
else if ((await server.fileSystem.stat?.(uriConverter.asUri(newJsConfigPath)))?.type === language_service_1.FileType.File) {
|
||||
tsConfigPath = newJsConfigPath;
|
||||
}
|
||||
}
|
||||
const beforeIndex = before.indexOf(tsConfigPath); // cycle
|
||||
if (beforeIndex >= 0) {
|
||||
newChains.push(before.slice(0, Math.max(beforeIndex, 1)));
|
||||
}
|
||||
else {
|
||||
const referenceCommandLine = await getCommandLine(tsConfigPath);
|
||||
if (referenceCommandLine) {
|
||||
for (const chain of await getReferencesChains(referenceCommandLine, tsConfigPath, [...before, tsConfig])) {
|
||||
newChains.push(chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return newChains;
|
||||
}
|
||||
else {
|
||||
return [[...before, tsConfig]];
|
||||
}
|
||||
}
|
||||
async function getCommandLine(tsConfig) {
|
||||
const project = await getOrCreateConfiguredProject(server, tsConfig);
|
||||
return project?.getCommandLine();
|
||||
}
|
||||
}
|
||||
function getOrCreateConfiguredProject(server, tsconfig) {
|
||||
tsconfig = tsconfig.replace(/\\/g, '/');
|
||||
const tsconfigUri = uriConverter.asUri(tsconfig);
|
||||
let projectPromise = configProjects.get(tsconfigUri);
|
||||
if (!projectPromise) {
|
||||
const workspaceFolder = getWorkspaceFolder(tsconfigUri, server.workspaceFolders);
|
||||
const serviceEnv = (0, simpleProject_1.createLanguageServiceEnvironment)(server, [workspaceFolder]);
|
||||
projectPromise = (0, typescriptProjectLs_1.createTypeScriptLS)(ts, tsLocalized, tsconfig, server, serviceEnv, workspaceFolder, uriConverter, create);
|
||||
configProjects.set(tsconfigUri, projectPromise);
|
||||
}
|
||||
return projectPromise;
|
||||
}
|
||||
async function getOrCreateInferredProject(server, uri, workspaceFolder) {
|
||||
if (!inferredProjects.has(workspaceFolder)) {
|
||||
inferredProjects.set(workspaceFolder, (async () => {
|
||||
const inferOptions = await (0, inferredCompilerOptions_1.getInferredCompilerOptions)(server);
|
||||
const serviceEnv = (0, simpleProject_1.createLanguageServiceEnvironment)(server, [workspaceFolder]);
|
||||
return (0, typescriptProjectLs_1.createTypeScriptLS)(ts, tsLocalized, inferOptions, server, serviceEnv, workspaceFolder, uriConverter, create);
|
||||
})());
|
||||
}
|
||||
const project = await inferredProjects.get(workspaceFolder);
|
||||
project.tryAddFile(uriConverter.asFileName(uri));
|
||||
return project;
|
||||
}
|
||||
}
|
||||
function createUriConverter(rootFolders) {
|
||||
const encodeds = new Map();
|
||||
const isFileScheme = rootFolders.every(folder => folder.scheme === 'file');
|
||||
return {
|
||||
asFileName,
|
||||
asUri,
|
||||
};
|
||||
function asFileName(parsed) {
|
||||
if (rootFolders.every(folder => folder.scheme === parsed.scheme && folder.authority === parsed.authority)) {
|
||||
if (isFileScheme) {
|
||||
return parsed.fsPath.replace(/\\/g, '/');
|
||||
}
|
||||
else {
|
||||
return parsed.path;
|
||||
}
|
||||
}
|
||||
const encoded = encodeURIComponent(`${parsed.scheme}://${parsed.authority}`);
|
||||
encodeds.set(encoded, parsed);
|
||||
return `/${encoded}${parsed.path}`;
|
||||
}
|
||||
function asUri(fileName) {
|
||||
for (const [encoded, uri] of encodeds) {
|
||||
const prefix = `/${encoded}`;
|
||||
if (fileName === prefix) {
|
||||
return vscode_uri_1.URI.from({
|
||||
scheme: uri.scheme,
|
||||
authority: uri.authority,
|
||||
});
|
||||
}
|
||||
if (uri.authority) {
|
||||
if (fileName.startsWith(prefix + '/')) {
|
||||
return vscode_uri_1.URI.from({
|
||||
scheme: uri.scheme,
|
||||
authority: uri.authority,
|
||||
path: fileName.substring(prefix.length),
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fileName.startsWith(prefix)) {
|
||||
return vscode_uri_1.URI.from({
|
||||
scheme: uri.scheme,
|
||||
authority: uri.authority,
|
||||
path: fileName.substring(prefix.length),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isFileScheme) {
|
||||
for (const folder of rootFolders) {
|
||||
return vscode_uri_1.URI.parse(`${folder.scheme}://${folder.authority}${fileName}`);
|
||||
}
|
||||
}
|
||||
return vscode_uri_1.URI.file(fileName);
|
||||
}
|
||||
}
|
||||
function sortTSConfigs(file, a, b) {
|
||||
const inA = isFileInDir(file, path.dirname(a));
|
||||
const inB = isFileInDir(file, path.dirname(b));
|
||||
if (inA !== inB) {
|
||||
const aWeight = inA ? 1 : 0;
|
||||
const bWeight = inB ? 1 : 0;
|
||||
return bWeight - aWeight;
|
||||
}
|
||||
const aLength = a.split('/').length;
|
||||
const bLength = b.split('/').length;
|
||||
if (aLength === bLength) {
|
||||
const aWeight = path.basename(a) === 'tsconfig.json' ? 1 : 0;
|
||||
const bWeight = path.basename(b) === 'tsconfig.json' ? 1 : 0;
|
||||
return bWeight - aWeight;
|
||||
}
|
||||
return bLength - aLength;
|
||||
}
|
||||
function isFileInDir(fileName, dir) {
|
||||
const relative = path.relative(dir, fileName);
|
||||
return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
||||
}
|
||||
function getWorkspaceFolder(uri, workspaceFolders) {
|
||||
while (true) {
|
||||
if (workspaceFolders.has(uri)) {
|
||||
return uri;
|
||||
}
|
||||
const next = uri.with({ path: uri.path.substring(0, uri.path.lastIndexOf('/')) });
|
||||
if (next.path === uri.path) {
|
||||
break;
|
||||
}
|
||||
uri = next;
|
||||
}
|
||||
for (const folder of workspaceFolders.all) {
|
||||
return folder;
|
||||
}
|
||||
return uri.with({ path: '/' });
|
||||
}
|
||||
//# sourceMappingURL=typescriptProject.js.map
|
||||
31
node_modules/@volar/language-server/lib/project/typescriptProjectLs.d.ts
generated
vendored
Normal file
31
node_modules/@volar/language-server/lib/project/typescriptProjectLs.d.ts
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Language, LanguagePlugin, LanguageService, LanguageServiceEnvironment, ProjectContext, ProviderResult } from '@volar/language-service';
|
||||
import { TypeScriptProjectHost, createSys } from '@volar/typescript';
|
||||
import type * as ts from 'typescript';
|
||||
import { URI } from 'vscode-uri';
|
||||
import type { LanguageServer } from '../types';
|
||||
export interface TypeScriptProjectLS {
|
||||
tryAddFile(fileName: string): void;
|
||||
getCommandLine(): ts.ParsedCommandLine;
|
||||
languageService: LanguageService;
|
||||
dispose(): void;
|
||||
}
|
||||
export interface ProjectExposeContext {
|
||||
env: LanguageServiceEnvironment;
|
||||
configFileName: string | undefined;
|
||||
projectHost: TypeScriptProjectHost;
|
||||
sys: ReturnType<typeof createSys>;
|
||||
uriConverter: {
|
||||
asUri(fileName: string): URI;
|
||||
asFileName(uri: URI): string;
|
||||
};
|
||||
}
|
||||
export declare function createTypeScriptLS(ts: typeof import('typescript'), tsLocalized: ts.MapLike<string> | undefined, tsconfig: string | ts.CompilerOptions, server: LanguageServer, serviceEnv: LanguageServiceEnvironment, workspaceFolder: URI, uriConverter: {
|
||||
asUri(fileName: string): URI;
|
||||
asFileName(uri: URI): string;
|
||||
}, create: (projectContext: ProjectExposeContext) => ProviderResult<{
|
||||
languagePlugins: LanguagePlugin<URI>[];
|
||||
setup?(options: {
|
||||
language: Language;
|
||||
project: ProjectContext;
|
||||
}): void;
|
||||
}>): Promise<TypeScriptProjectLS>;
|
||||
232
node_modules/@volar/language-server/lib/project/typescriptProjectLs.js
generated
vendored
Normal file
232
node_modules/@volar/language-server/lib/project/typescriptProjectLs.js
generated
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createTypeScriptLS = createTypeScriptLS;
|
||||
const language_service_1 = require("@volar/language-service");
|
||||
const typescript_1 = require("@volar/typescript");
|
||||
const utilities_1 = require("@volar/typescript/lib/typescript/utilities");
|
||||
const path = require("path-browserify");
|
||||
const vscode = require("vscode-languageserver");
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
const fsFileSnapshots = (0, language_service_1.createUriMap)();
|
||||
async function createTypeScriptLS(ts, tsLocalized, tsconfig, server, serviceEnv, workspaceFolder, uriConverter, create) {
|
||||
let commandLine;
|
||||
let projectVersion = 0;
|
||||
const getCurrentDirectory = () => uriConverter.asFileName(workspaceFolder);
|
||||
const sys = (0, typescript_1.createSys)(ts.sys, serviceEnv, getCurrentDirectory, uriConverter);
|
||||
const projectHost = {
|
||||
getCurrentDirectory,
|
||||
getProjectVersion() {
|
||||
return projectVersion.toString();
|
||||
},
|
||||
getScriptFileNames() {
|
||||
return commandLine.fileNames;
|
||||
},
|
||||
getCompilationSettings() {
|
||||
return commandLine.options;
|
||||
},
|
||||
getLocalizedDiagnosticMessages: tsLocalized ? () => tsLocalized : undefined,
|
||||
getProjectReferences() {
|
||||
return commandLine.projectReferences;
|
||||
},
|
||||
};
|
||||
const { languagePlugins, setup } = await create({
|
||||
env: serviceEnv,
|
||||
configFileName: typeof tsconfig === 'string' ? tsconfig : undefined,
|
||||
projectHost,
|
||||
sys,
|
||||
uriConverter,
|
||||
});
|
||||
const unsavedRootFileUris = (0, language_service_1.createUriMap)();
|
||||
const disposables = [
|
||||
server.documents.onDidOpen(({ document }) => updateFsCacheFromSyncedDocument(document)),
|
||||
server.documents.onDidSave(({ document }) => updateFsCacheFromSyncedDocument(document)),
|
||||
server.documents.onDidChangeContent(() => projectVersion++),
|
||||
serviceEnv.onDidChangeWatchedFiles?.(async ({ changes }) => {
|
||||
const createdOrDeleted = changes.some(change => change.type !== vscode.FileChangeType.Changed);
|
||||
if (createdOrDeleted) {
|
||||
await updateCommandLine();
|
||||
}
|
||||
projectVersion++;
|
||||
}),
|
||||
server.documents.onDidOpen(async ({ document }) => {
|
||||
const uri = vscode_uri_1.URI.parse(document.uri);
|
||||
const isWorkspaceFile = workspaceFolder.scheme === uri.scheme;
|
||||
if (!isWorkspaceFile) {
|
||||
return;
|
||||
}
|
||||
const stat = await serviceEnv.fs?.stat(uri);
|
||||
const isUnsaved = stat?.type !== 1;
|
||||
if (isUnsaved) {
|
||||
const lastProjectVersion = projectVersion;
|
||||
await updateCommandLine();
|
||||
if (lastProjectVersion !== projectVersion) {
|
||||
unsavedRootFileUris.set(uri, true);
|
||||
}
|
||||
}
|
||||
}),
|
||||
server.documents.onDidClose(async ({ document }) => {
|
||||
const uri = vscode_uri_1.URI.parse(document.uri);
|
||||
if (unsavedRootFileUris.has(uri)) {
|
||||
unsavedRootFileUris.delete(uri);
|
||||
await updateCommandLine();
|
||||
}
|
||||
}),
|
||||
].filter(d => !!d);
|
||||
await updateCommandLine();
|
||||
const language = (0, language_service_1.createLanguage)([
|
||||
{ getLanguageId: uri => server.documents.get(uri)?.languageId },
|
||||
...languagePlugins,
|
||||
{ getLanguageId: uri => (0, typescript_1.resolveFileLanguageId)(uri.path) },
|
||||
], (0, language_service_1.createUriMap)(sys.useCaseSensitiveFileNames), (uri, includeFsFiles) => {
|
||||
const syncedDocument = server.documents.get(uri);
|
||||
let snapshot;
|
||||
if (syncedDocument) {
|
||||
snapshot = syncedDocument.getSnapshot();
|
||||
}
|
||||
else if (includeFsFiles) {
|
||||
const cache = fsFileSnapshots.get(uri);
|
||||
const fileName = uriConverter.asFileName(uri);
|
||||
const modifiedTime = sys.getModifiedTime?.(fileName)?.valueOf();
|
||||
if (!cache || cache[0] !== modifiedTime) {
|
||||
if (sys.fileExists(fileName)) {
|
||||
const text = sys.readFile(fileName);
|
||||
const snapshot = text !== undefined ? ts.ScriptSnapshot.fromString(text) : undefined;
|
||||
fsFileSnapshots.set(uri, [modifiedTime, snapshot]);
|
||||
}
|
||||
else {
|
||||
fsFileSnapshots.set(uri, [modifiedTime, undefined]);
|
||||
}
|
||||
}
|
||||
snapshot = fsFileSnapshots.get(uri)?.[1];
|
||||
}
|
||||
if (snapshot) {
|
||||
language.scripts.set(uri, snapshot);
|
||||
}
|
||||
else {
|
||||
language.scripts.delete(uri);
|
||||
}
|
||||
});
|
||||
const project = {
|
||||
typescript: {
|
||||
configFileName: typeof tsconfig === 'string' ? tsconfig : undefined,
|
||||
sys,
|
||||
uriConverter,
|
||||
...(0, typescript_1.createLanguageServiceHost)(ts, sys, language, s => uriConverter.asUri(s), projectHost),
|
||||
},
|
||||
};
|
||||
setup?.({ language, project });
|
||||
const languageService = (0, language_service_1.createLanguageService)(language, server.languageServicePlugins, serviceEnv, project);
|
||||
return {
|
||||
languageService,
|
||||
tryAddFile(fileName) {
|
||||
if (!commandLine.fileNames.includes(fileName)) {
|
||||
commandLine.fileNames.push(fileName);
|
||||
projectVersion++;
|
||||
}
|
||||
},
|
||||
dispose: () => {
|
||||
sys.dispose();
|
||||
languageService?.dispose();
|
||||
disposables.forEach(({ dispose }) => dispose());
|
||||
disposables.length = 0;
|
||||
},
|
||||
getCommandLine: () => commandLine,
|
||||
};
|
||||
function updateFsCacheFromSyncedDocument(document) {
|
||||
const uri = vscode_uri_1.URI.parse(document.uri);
|
||||
const fileName = uriConverter.asFileName(uri);
|
||||
if (fsFileSnapshots.has(uri) || sys.fileExists(fileName)) {
|
||||
const modifiedTime = sys.getModifiedTime?.(fileName);
|
||||
fsFileSnapshots.set(uri, [modifiedTime?.valueOf(), document.getSnapshot()]);
|
||||
}
|
||||
}
|
||||
async function updateCommandLine() {
|
||||
const oldFileNames = new Set(commandLine?.fileNames ?? []);
|
||||
commandLine = await parseConfig(ts, sys, uriConverter.asFileName(workspaceFolder), tsconfig, languagePlugins.map(plugin => plugin.typescript?.extraFileExtensions ?? []).flat());
|
||||
const newFileNames = new Set(commandLine.fileNames);
|
||||
if (oldFileNames.size !== newFileNames.size || [...oldFileNames].some(fileName => !newFileNames.has(fileName))) {
|
||||
projectVersion++;
|
||||
}
|
||||
}
|
||||
async function parseConfig(ts, sys, workspacePath, tsconfig, extraFileExtensions) {
|
||||
let commandLine = {
|
||||
errors: [],
|
||||
fileNames: [],
|
||||
options: {},
|
||||
};
|
||||
let sysVersion;
|
||||
let newSysVersion = await sys.sync();
|
||||
while (sysVersion !== newSysVersion) {
|
||||
sysVersion = newSysVersion;
|
||||
try {
|
||||
commandLine = await parseConfigWorker(ts, sys, workspacePath, tsconfig, extraFileExtensions);
|
||||
}
|
||||
catch {
|
||||
// will be failed if web fs host first result not ready
|
||||
}
|
||||
newSysVersion = await sys.sync();
|
||||
}
|
||||
return commandLine;
|
||||
}
|
||||
function parseConfigWorker(ts, _host, workspacePath, tsconfig, extraFileExtensions) {
|
||||
let content = {
|
||||
errors: [],
|
||||
fileNames: [],
|
||||
options: {},
|
||||
};
|
||||
const maybeUnsavedFileNames = server.documents.all()
|
||||
.map(document => vscode_uri_1.URI.parse(document.uri))
|
||||
.filter(uri => uri.scheme === workspaceFolder.scheme)
|
||||
.map(uri => uriConverter.asFileName(uri));
|
||||
const host = {
|
||||
..._host,
|
||||
readDirectory(rootDir, extensions, excludes, includes, depth) {
|
||||
const fsFiles = _host.readDirectory(rootDir, extensions, excludes, includes, depth);
|
||||
const unsavedFiles = (0, utilities_1.matchFiles)(rootDir, extensions, excludes, includes, sys.useCaseSensitiveFileNames, getCurrentDirectory(), depth, dirPath => {
|
||||
dirPath = dirPath.replace(/\\/g, '/');
|
||||
const files = [];
|
||||
const dirs = [];
|
||||
for (const fileName of maybeUnsavedFileNames) {
|
||||
const match = sys.useCaseSensitiveFileNames
|
||||
? fileName.startsWith(dirPath + '/')
|
||||
: fileName.toLowerCase().startsWith(dirPath.toLowerCase() + '/');
|
||||
if (match) {
|
||||
const name = fileName.slice(dirPath.length + 1);
|
||||
if (name.includes('/')) {
|
||||
const dir = name.split('/')[0];
|
||||
if (!dirs.includes(dir)) {
|
||||
dirs.push(dir);
|
||||
}
|
||||
}
|
||||
else {
|
||||
files.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
files,
|
||||
directories: dirs,
|
||||
};
|
||||
}, path => path);
|
||||
if (!unsavedFiles.length) {
|
||||
return fsFiles;
|
||||
}
|
||||
return [...new Set([...fsFiles, ...unsavedFiles])];
|
||||
},
|
||||
};
|
||||
if (typeof tsconfig === 'string') {
|
||||
const config = ts.readJsonConfigFile(tsconfig, host.readFile);
|
||||
content = ts.parseJsonSourceFileConfigFileContent(config, host, path.dirname(tsconfig), {}, tsconfig, undefined, extraFileExtensions);
|
||||
}
|
||||
else {
|
||||
content = ts.parseJsonConfigFileContent({ files: [] }, host, workspacePath, tsconfig, workspacePath + '/jsconfig.json', undefined, extraFileExtensions);
|
||||
}
|
||||
// fix https://github.com/johnsoncodehk/volar/issues/1786
|
||||
// https://github.com/microsoft/TypeScript/issues/30457
|
||||
// patching ts server broke with outDir + rootDir + composite/incremental
|
||||
content.options.outDir = undefined;
|
||||
content.fileNames = content.fileNames.map(fileName => fileName.replace(/\\/g, '/'));
|
||||
return content;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=typescriptProjectLs.js.map
|
||||
52
node_modules/@volar/language-server/lib/server.d.ts
generated
vendored
Normal file
52
node_modules/@volar/language-server/lib/server.d.ts
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import { LanguageServicePlugin } from '@volar/language-service';
|
||||
import * as vscode from 'vscode-languageserver';
|
||||
import type { ExperimentalFeatures, LanguageServerEnvironment, LanguageServerProject } from './types.js';
|
||||
export declare function createServerBase(connection: vscode.Connection, env: LanguageServerEnvironment): {
|
||||
initializeParams: vscode.InitializeParams;
|
||||
project: LanguageServerProject;
|
||||
languageServicePlugins: LanguageServicePlugin<any>[];
|
||||
initialize(params: vscode.InitializeParams, project: LanguageServerProject, languageServicePlugins: LanguageServicePlugin[]): vscode.InitializeResult<ExperimentalFeatures>;
|
||||
initialized(): void;
|
||||
shutdown(): void;
|
||||
configurations: {
|
||||
get: <T>(section: string, scopeUri?: string) => Promise<T | undefined>;
|
||||
onDidChange: (cb: vscode.NotificationHandler<vscode.DidChangeConfigurationParams>) => {
|
||||
dispose(): void;
|
||||
};
|
||||
};
|
||||
editorFeatures: void;
|
||||
documents: {
|
||||
all: () => import("./utils/snapshotDocument.js").SnapshotDocument[];
|
||||
onDidChangeContent: vscode.Event<vscode.TextDocumentChangeEvent<import("./utils/snapshotDocument.js").SnapshotDocument>>;
|
||||
onDidOpen: vscode.Event<vscode.TextDocumentChangeEvent<import("./utils/snapshotDocument.js").SnapshotDocument>>;
|
||||
onDidClose: vscode.Event<vscode.TextDocumentChangeEvent<import("./utils/snapshotDocument.js").SnapshotDocument>>;
|
||||
onDidSave: vscode.Event<vscode.TextDocumentChangeEvent<import("./utils/snapshotDocument.js").SnapshotDocument>>;
|
||||
get(uri: import("vscode-uri").URI): import("./utils/snapshotDocument.js").SnapshotDocument | undefined;
|
||||
};
|
||||
workspaceFolders: {
|
||||
readonly all: import("vscode-uri").URI[];
|
||||
has(uri: import("vscode-uri").URI): boolean;
|
||||
onDidChange: (cb: vscode.NotificationHandler<vscode.WorkspaceFoldersChangeEvent>) => {
|
||||
dispose(): void;
|
||||
};
|
||||
};
|
||||
fileWatcher: {
|
||||
watchFiles: (patterns: string[]) => Promise<vscode.Disposable>;
|
||||
onDidChangeWatchedFiles: (cb: vscode.NotificationHandler<vscode.DidChangeWatchedFilesParams>) => {
|
||||
dispose: () => void;
|
||||
};
|
||||
};
|
||||
languageFeatures: {
|
||||
requestRefresh: (clearDiagnostics: boolean) => Promise<void>;
|
||||
};
|
||||
fileSystem: {
|
||||
readFile(uri: import("vscode-uri").URI): string | Thenable<string | undefined>;
|
||||
stat(uri: import("vscode-uri").URI): import("@volar/language-service").FileStat | Thenable<import("@volar/language-service").FileStat | undefined>;
|
||||
readDirectory(uri: import("vscode-uri").URI): import("@volar/language-service").ProviderResult<[string, import("@volar/language-service").FileType][]>;
|
||||
install(scheme: string, provider: import("@volar/language-service").FileSystem): void;
|
||||
};
|
||||
env: LanguageServerEnvironment;
|
||||
connection: vscode.Connection;
|
||||
onInitialize(callback: (serverCapabilities: vscode.ServerCapabilities<ExperimentalFeatures>) => void): void;
|
||||
onInitialized(callback: () => void): void;
|
||||
};
|
||||
70
node_modules/@volar/language-server/lib/server.js
generated
vendored
Normal file
70
node_modules/@volar/language-server/lib/server.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createServerBase = createServerBase;
|
||||
const configurations_js_1 = require("./features/configurations.js");
|
||||
const editorFeatures_js_1 = require("./features/editorFeatures.js");
|
||||
const fileSystem_js_1 = require("./features/fileSystem.js");
|
||||
const fileWatcher_js_1 = require("./features/fileWatcher.js");
|
||||
const languageFeatures_js_1 = require("./features/languageFeatures.js");
|
||||
const textDocuments_js_1 = require("./features/textDocuments.js");
|
||||
const workspaceFolders_js_1 = require("./features/workspaceFolders.js");
|
||||
function createServerBase(connection, env) {
|
||||
const onInitializeCallbacks = [];
|
||||
const onInitializedCallbacks = [];
|
||||
const state = {
|
||||
env,
|
||||
connection,
|
||||
initializeParams: undefined,
|
||||
project: undefined,
|
||||
languageServicePlugins: undefined,
|
||||
onInitialize(callback) {
|
||||
onInitializeCallbacks.push(callback);
|
||||
},
|
||||
onInitialized(callback) {
|
||||
onInitializedCallbacks.push(callback);
|
||||
},
|
||||
};
|
||||
const configurations = (0, configurations_js_1.register)(state);
|
||||
const editorFeatures = (0, editorFeatures_js_1.register)(state);
|
||||
const documents = (0, textDocuments_js_1.register)(state);
|
||||
const workspaceFolders = (0, workspaceFolders_js_1.register)(state);
|
||||
const fileWatcher = (0, fileWatcher_js_1.register)(state);
|
||||
const languageFeatures = (0, languageFeatures_js_1.register)(state, documents, configurations);
|
||||
const fileSystem = (0, fileSystem_js_1.register)(documents, fileWatcher);
|
||||
const server = {
|
||||
...state,
|
||||
get initializeParams() {
|
||||
return state.initializeParams;
|
||||
},
|
||||
get project() {
|
||||
return state.project;
|
||||
},
|
||||
get languageServicePlugins() {
|
||||
return state.languageServicePlugins;
|
||||
},
|
||||
initialize(params, project, languageServicePlugins) {
|
||||
state.initializeParams = params;
|
||||
state.project = project;
|
||||
state.languageServicePlugins = languageServicePlugins;
|
||||
const serverCapabilities = {};
|
||||
onInitializeCallbacks.forEach(cb => cb(serverCapabilities));
|
||||
return { capabilities: serverCapabilities };
|
||||
},
|
||||
initialized() {
|
||||
onInitializedCallbacks.forEach(cb => cb());
|
||||
state.project.setup(server);
|
||||
},
|
||||
shutdown() {
|
||||
state.project.reload();
|
||||
},
|
||||
configurations,
|
||||
editorFeatures,
|
||||
documents,
|
||||
workspaceFolders,
|
||||
fileWatcher,
|
||||
languageFeatures,
|
||||
fileSystem,
|
||||
};
|
||||
return server;
|
||||
}
|
||||
//# sourceMappingURL=server.js.map
|
||||
34
node_modules/@volar/language-server/lib/types.d.ts
generated
vendored
Normal file
34
node_modules/@volar/language-server/lib/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { InitializeParams, LanguageService, LanguageServicePlugin, ProviderResult, ServerCapabilities } from '@volar/language-service';
|
||||
import { Connection } from 'vscode-languageserver';
|
||||
import type { URI } from 'vscode-uri';
|
||||
import { createServerBase } from './server';
|
||||
export interface LanguageServerEnvironment {
|
||||
timer: {
|
||||
setImmediate: (callback: (...args: any[]) => void, ...args: any[]) => void;
|
||||
};
|
||||
}
|
||||
export interface LanguageServerProject {
|
||||
setup(server: LanguageServer): void;
|
||||
getLanguageService(uri: URI): ProviderResult<LanguageService>;
|
||||
getExistingLanguageServices(): ProviderResult<LanguageService[]>;
|
||||
reload(): void;
|
||||
}
|
||||
export interface LanguageServerState {
|
||||
env: LanguageServerEnvironment;
|
||||
connection: Connection;
|
||||
initializeParams: InitializeParams;
|
||||
project: LanguageServerProject;
|
||||
languageServicePlugins: LanguageServicePlugin[];
|
||||
onInitialize(callback: (serverCapabilities: ServerCapabilities<ExperimentalFeatures>) => void): void;
|
||||
onInitialized(callback: () => void): void;
|
||||
}
|
||||
export type LanguageServer = ReturnType<typeof createServerBase>;
|
||||
export interface ExperimentalFeatures {
|
||||
fileReferencesProvider?: boolean;
|
||||
fileRenameEditsProvider?: boolean;
|
||||
documentDropEditsProvider?: boolean;
|
||||
autoInsertionProvider?: {
|
||||
triggerCharacters: string[];
|
||||
configurationSections?: (string[] | null)[];
|
||||
};
|
||||
}
|
||||
3
node_modules/@volar/language-server/lib/types.js
generated
vendored
Normal file
3
node_modules/@volar/language-server/lib/types.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=types.js.map
|
||||
2
node_modules/@volar/language-server/lib/utils/combineChangeRanges.d.ts
generated
vendored
Normal file
2
node_modules/@volar/language-server/lib/utils/combineChangeRanges.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import type * as ts from 'typescript';
|
||||
export declare function combineChangeRanges(...changeRanges: ts.TextChangeRange[]): ts.TextChangeRange;
|
||||
28
node_modules/@volar/language-server/lib/utils/combineChangeRanges.js
generated
vendored
Normal file
28
node_modules/@volar/language-server/lib/utils/combineChangeRanges.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.combineChangeRanges = combineChangeRanges;
|
||||
function combineChangeRanges(...changeRanges) {
|
||||
let changeRange = changeRanges[0];
|
||||
for (let i = 1; i < changeRanges.length; i++) {
|
||||
const nextChangeRange = changeRanges[i];
|
||||
changeRange = combineTwoChanges(changeRange, nextChangeRange);
|
||||
}
|
||||
return changeRange;
|
||||
}
|
||||
// https://tsplay.dev/mMldVN - @browsnet
|
||||
function combineTwoChanges(a, b) {
|
||||
const aStart = a.span.start;
|
||||
const aEnd = a.span.start + a.span.length;
|
||||
const aDiff = a.newLength - a.span.length;
|
||||
const changeBegin = aStart + Math.min(a.span.length, a.newLength);
|
||||
const rollback = (start) => start > changeBegin ? Math.max(aStart, start - aDiff) : start;
|
||||
const bStart = rollback(b.span.start);
|
||||
const bEnd = rollback(b.span.start + b.span.length);
|
||||
const bDiff = b.newLength - b.span.length;
|
||||
const start = Math.min(aStart, bStart);
|
||||
const end = Math.max(aEnd, bEnd);
|
||||
const length = end - start;
|
||||
const newLength = aDiff + bDiff + length;
|
||||
return { span: { start, length }, newLength };
|
||||
}
|
||||
//# sourceMappingURL=combineChangeRanges.js.map
|
||||
24
node_modules/@volar/language-server/lib/utils/snapshotDocument.d.ts
generated
vendored
Normal file
24
node_modules/@volar/language-server/lib/utils/snapshotDocument.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import type * as ts from 'typescript';
|
||||
import type * as vscode from 'vscode-languageserver-protocol';
|
||||
import { Range, TextDocument } from 'vscode-languageserver-textdocument';
|
||||
export declare class SnapshotDocument implements TextDocument {
|
||||
private document;
|
||||
private snapshots;
|
||||
constructor(uri: string, languageId: string, version: number, text: string);
|
||||
get uri(): string;
|
||||
get languageId(): string;
|
||||
get version(): number;
|
||||
get lineCount(): number;
|
||||
getText(range?: Range): string;
|
||||
positionAt(offset: number): import("vscode-languageserver-textdocument").Position;
|
||||
offsetAt(position: vscode.Position): number;
|
||||
/**
|
||||
* Update the document with the given content changes and version.
|
||||
* If all changes is incremental, calculate the change range and add a new snapshot.
|
||||
* Otherwise, reset the changes.
|
||||
*/
|
||||
update(contentChanges: vscode.TextDocumentContentChangeEvent[], version: number): void;
|
||||
getSnapshot(): ts.IScriptSnapshot;
|
||||
private resetChanges;
|
||||
private clearUnreferencedVersions;
|
||||
}
|
||||
120
node_modules/@volar/language-server/lib/utils/snapshotDocument.js
generated
vendored
Normal file
120
node_modules/@volar/language-server/lib/utils/snapshotDocument.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SnapshotDocument = void 0;
|
||||
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
|
||||
const combineChangeRanges_1 = require("./combineChangeRanges");
|
||||
class SnapshotDocument {
|
||||
constructor(uri, languageId, version, text) {
|
||||
this.snapshots = [];
|
||||
this.document = vscode_languageserver_textdocument_1.TextDocument.create(uri, languageId, version, text);
|
||||
this.resetChanges();
|
||||
}
|
||||
get uri() {
|
||||
return this.document.uri;
|
||||
}
|
||||
get languageId() {
|
||||
return this.document.languageId;
|
||||
}
|
||||
get version() {
|
||||
return this.document.version;
|
||||
}
|
||||
get lineCount() {
|
||||
return this.document.lineCount;
|
||||
}
|
||||
getText(range) {
|
||||
return this.document.getText(range);
|
||||
}
|
||||
positionAt(offset) {
|
||||
return this.document.positionAt(offset);
|
||||
}
|
||||
offsetAt(position) {
|
||||
return this.document.offsetAt(position);
|
||||
}
|
||||
/**
|
||||
* Update the document with the given content changes and version.
|
||||
* If all changes is incremental, calculate the change range and add a new snapshot.
|
||||
* Otherwise, reset the changes.
|
||||
*/
|
||||
update(contentChanges, version) {
|
||||
if (contentChanges.every(change => 'range' in change)) {
|
||||
let changeRanges = [];
|
||||
for (const contentChange of contentChanges) {
|
||||
if (!('range' in contentChange)) {
|
||||
continue;
|
||||
}
|
||||
const start = this.offsetAt(contentChange.range.start);
|
||||
const length = contentChange.rangeLength ?? this.offsetAt(contentChange.range.end) - start;
|
||||
changeRanges.push({
|
||||
span: { start, length },
|
||||
newLength: contentChange.text.length
|
||||
});
|
||||
vscode_languageserver_textdocument_1.TextDocument.update(this.document, [contentChange], version);
|
||||
}
|
||||
this.snapshots.push({
|
||||
changeRange: (0, combineChangeRanges_1.combineChangeRanges)(...changeRanges),
|
||||
version,
|
||||
ref: undefined,
|
||||
});
|
||||
}
|
||||
else {
|
||||
vscode_languageserver_textdocument_1.TextDocument.update(this.document, contentChanges, version);
|
||||
this.resetChanges();
|
||||
}
|
||||
}
|
||||
getSnapshot() {
|
||||
this.clearUnreferencedVersions();
|
||||
const lastChange = this.snapshots[this.snapshots.length - 1];
|
||||
if (!lastChange.ref) {
|
||||
const text = this.document.getText();
|
||||
const changeRangeCache = new WeakMap();
|
||||
const snapshot = {
|
||||
getText: (start, end) => text.substring(start, end),
|
||||
getLength: () => text.length,
|
||||
getChangeRange: oldSnapshot => {
|
||||
if (!changeRangeCache.has(oldSnapshot)) {
|
||||
const oldIndex = this.snapshots.findIndex(change => change.ref?.deref() === oldSnapshot);
|
||||
if (oldIndex >= 0) {
|
||||
const start = oldIndex + 1;
|
||||
const end = this.snapshots.indexOf(lastChange) + 1;
|
||||
const changeRanges = this.snapshots
|
||||
.slice(start, end)
|
||||
.map(change => change.changeRange);
|
||||
const changeRange = (0, combineChangeRanges_1.combineChangeRanges)(...changeRanges);
|
||||
changeRangeCache.set(oldSnapshot, changeRange);
|
||||
}
|
||||
else {
|
||||
changeRangeCache.set(oldSnapshot, undefined);
|
||||
}
|
||||
}
|
||||
return changeRangeCache.get(oldSnapshot);
|
||||
},
|
||||
};
|
||||
lastChange.ref = new WeakRef(snapshot);
|
||||
}
|
||||
return lastChange.ref.deref();
|
||||
}
|
||||
resetChanges() {
|
||||
this.snapshots = [
|
||||
{
|
||||
changeRange: {
|
||||
span: {
|
||||
start: 0,
|
||||
length: 0,
|
||||
},
|
||||
newLength: this.document.getText().length,
|
||||
},
|
||||
version: this.document.version,
|
||||
ref: undefined,
|
||||
}
|
||||
];
|
||||
}
|
||||
clearUnreferencedVersions() {
|
||||
let firstReferencedIndex = 0;
|
||||
while (firstReferencedIndex < this.snapshots.length - 1 && !this.snapshots[firstReferencedIndex].ref?.deref()) {
|
||||
firstReferencedIndex++;
|
||||
}
|
||||
this.snapshots = this.snapshots.slice(firstReferencedIndex);
|
||||
}
|
||||
}
|
||||
exports.SnapshotDocument = SnapshotDocument;
|
||||
//# sourceMappingURL=snapshotDocument.js.map
|
||||
Reference in New Issue
Block a user