Files
discord-clone/node_modules/vscode-languageclient/lib/common/fileOperations.js
2023-01-03 09:29:04 -06:00

264 lines
12 KiB
JavaScript

"use strict";
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
Object.defineProperty(exports, "__esModule", { value: true });
exports.WillDeleteFilesFeature = exports.WillRenameFilesFeature = exports.WillCreateFilesFeature = exports.DidDeleteFilesFeature = exports.DidRenameFilesFeature = exports.DidCreateFilesFeature = void 0;
const code = require("vscode");
const minimatch = require("minimatch");
const proto = require("vscode-languageserver-protocol");
const UUID = require("./utils/uuid");
function ensure(target, key) {
if (target[key] === void 0) {
target[key] = {};
}
return target[key];
}
function access(target, key) {
return target[key];
}
function assign(target, key, value) {
target[key] = value;
}
class FileOperationFeature {
constructor(client, event, registrationType, clientCapability, serverCapability) {
this._filters = new Map();
this._client = client;
this._event = event;
this._registrationType = registrationType;
this._clientCapability = clientCapability;
this._serverCapability = serverCapability;
}
get registrationType() {
return this._registrationType;
}
fillClientCapabilities(capabilities) {
const value = ensure(ensure(capabilities, 'workspace'), 'fileOperations');
// this happens n times but it is the same value so we tolerate this.
assign(value, 'dynamicRegistration', true);
assign(value, this._clientCapability, true);
}
initialize(capabilities) {
var _a;
const options = (_a = capabilities.workspace) === null || _a === void 0 ? void 0 : _a.fileOperations;
const capability = options !== undefined ? access(options, this._serverCapability) : undefined;
if ((capability === null || capability === void 0 ? void 0 : capability.filters) !== undefined) {
try {
this.register({
id: UUID.generateUuid(),
registerOptions: { filters: capability.filters }
});
}
catch (e) {
this._client.warn(`Ignoring invalid glob pattern for ${this._serverCapability} registration: ${e}`);
}
}
}
register(data) {
if (!this._listener) {
this._listener = this._event(this.send, this);
}
const minimatchFilter = data.registerOptions.filters.map((filter) => {
const matcher = new minimatch.Minimatch(filter.pattern.glob, FileOperationFeature.asMinimatchOptions(filter.pattern.options));
if (!matcher.makeRe()) {
throw new Error(`Invalid pattern ${filter.pattern.glob}!`);
}
return { scheme: filter.scheme, matcher, kind: filter.pattern.matches };
});
this._filters.set(data.id, minimatchFilter);
}
unregister(id) {
this._filters.delete(id);
if (this._filters.size === 0 && this._listener) {
this._listener.dispose();
this._listener = undefined;
}
}
dispose() {
this._filters.clear();
if (this._listener) {
this._listener.dispose();
this._listener = undefined;
}
}
async filter(event, prop) {
// (Asynchronously) map each file onto a boolean of whether it matches
// any of the globs.
const fileMatches = await Promise.all(event.files.map(async (item) => {
const uri = prop(item);
// Use fsPath to make this consistent with file system watchers but help
// minimatch to use '/' instead of `\\` if present.
const path = uri.fsPath.replace(/\\/g, '/');
for (const filters of this._filters.values()) {
for (const filter of filters) {
if (filter.scheme !== undefined && filter.scheme !== uri.scheme) {
continue;
}
if (filter.matcher.match(path)) {
// The pattern matches. If kind is undefined then everything is ok
if (filter.kind === undefined) {
return true;
}
const fileType = await FileOperationFeature.getFileType(uri);
// If we can't determine the file type than we treat it as a match.
// Dropping it would be another alternative.
if (fileType === undefined) {
this._client.error(`Failed to determine file type for ${uri.toString()}.`);
return true;
}
if ((fileType === code.FileType.File && filter.kind === proto.FileOperationPatternKind.file) || (fileType === code.FileType.Directory && filter.kind === proto.FileOperationPatternKind.folder)) {
return true;
}
}
else if (filter.kind === proto.FileOperationPatternKind.folder) {
const fileType = await FileOperationFeature.getFileType(uri);
if (fileType === code.FileType.Directory && filter.matcher.match(`${path}/`)) {
return true;
}
}
}
}
return false;
}));
// Filter the files to those that matched.
const files = event.files.filter((_, index) => fileMatches[index]);
return Object.assign(Object.assign({}, event), { files });
}
static async getFileType(uri) {
try {
return (await code.workspace.fs.stat(uri)).type;
}
catch (e) {
return undefined;
}
}
static asMinimatchOptions(options) {
if (options === undefined) {
return undefined;
}
if (options.ignoreCase === true) {
return { nocase: true };
}
return undefined;
}
}
class NotificationFileOperationFeature extends FileOperationFeature {
constructor(client, event, notificationType, clientCapability, serverCapability, accessUri, createParams) {
super(client, event, notificationType, clientCapability, serverCapability);
this._notificationType = notificationType;
this._accessUri = accessUri;
this._createParams = createParams;
}
async send(originalEvent) {
// Create a copy of the event that has the files filtered to match what the
// server wants.
const filteredEvent = await this.filter(originalEvent, this._accessUri);
if (filteredEvent.files.length) {
const next = async (event) => {
this._client.sendNotification(this._notificationType, this._createParams(event));
};
this.doSend(filteredEvent, next);
}
}
}
class DidCreateFilesFeature extends NotificationFileOperationFeature {
constructor(client) {
super(client, code.workspace.onDidCreateFiles, proto.DidCreateFilesNotification.type, 'didCreate', 'didCreate', (i) => i, client.code2ProtocolConverter.asDidCreateFilesParams);
}
doSend(event, next) {
var _a;
const middleware = (_a = this._client.clientOptions.middleware) === null || _a === void 0 ? void 0 : _a.workspace;
return (middleware === null || middleware === void 0 ? void 0 : middleware.didCreateFiles) ? middleware.didCreateFiles(event, next)
: next(event);
}
}
exports.DidCreateFilesFeature = DidCreateFilesFeature;
class DidRenameFilesFeature extends NotificationFileOperationFeature {
constructor(client) {
super(client, code.workspace.onDidRenameFiles, proto.DidRenameFilesNotification.type, 'didRename', 'didRename', (i) => i.oldUri, client.code2ProtocolConverter.asDidRenameFilesParams);
}
doSend(event, next) {
var _a;
const middleware = (_a = this._client.clientOptions.middleware) === null || _a === void 0 ? void 0 : _a.workspace;
return (middleware === null || middleware === void 0 ? void 0 : middleware.didRenameFiles) ? middleware.didRenameFiles(event, next)
: next(event);
}
}
exports.DidRenameFilesFeature = DidRenameFilesFeature;
class DidDeleteFilesFeature extends NotificationFileOperationFeature {
constructor(client) {
super(client, code.workspace.onDidDeleteFiles, proto.DidDeleteFilesNotification.type, 'didDelete', 'didDelete', (i) => i, client.code2ProtocolConverter.asDidDeleteFilesParams);
}
doSend(event, next) {
var _a;
const middleware = (_a = this._client.clientOptions.middleware) === null || _a === void 0 ? void 0 : _a.workspace;
return (middleware === null || middleware === void 0 ? void 0 : middleware.didDeleteFiles) ? middleware.didDeleteFiles(event, next)
: next(event);
}
}
exports.DidDeleteFilesFeature = DidDeleteFilesFeature;
class RequestFileOperationFeature extends FileOperationFeature {
constructor(client, event, requestType, clientCapability, serverCapability, accessUri, createParams) {
super(client, event, requestType, clientCapability, serverCapability);
this._requestType = requestType;
this._accessUri = accessUri;
this._createParams = createParams;
}
async send(originalEvent) {
const waitUntil = this.waitUntil(originalEvent);
originalEvent.waitUntil(waitUntil);
}
async waitUntil(originalEvent) {
// Create a copy of the event that has the files filtered to match what the
// server wants.
const filteredEvent = await this.filter(originalEvent, this._accessUri);
if (filteredEvent.files.length) {
const next = (event) => {
return this._client.sendRequest(this._requestType, this._createParams(event))
.then(this._client.protocol2CodeConverter.asWorkspaceEdit);
};
return this.doSend(filteredEvent, next);
}
else {
return undefined;
}
}
}
class WillCreateFilesFeature extends RequestFileOperationFeature {
constructor(client) {
super(client, code.workspace.onWillCreateFiles, proto.WillCreateFilesRequest.type, 'willCreate', 'willCreate', (i) => i, client.code2ProtocolConverter.asWillCreateFilesParams);
}
doSend(event, next) {
var _a;
const middleware = (_a = this._client.clientOptions.middleware) === null || _a === void 0 ? void 0 : _a.workspace;
return (middleware === null || middleware === void 0 ? void 0 : middleware.willCreateFiles) ? middleware.willCreateFiles(event, next)
: next(event);
}
}
exports.WillCreateFilesFeature = WillCreateFilesFeature;
class WillRenameFilesFeature extends RequestFileOperationFeature {
constructor(client) {
super(client, code.workspace.onWillRenameFiles, proto.WillRenameFilesRequest.type, 'willRename', 'willRename', (i) => i.oldUri, client.code2ProtocolConverter.asWillRenameFilesParams);
}
doSend(event, next) {
var _a;
const middleware = (_a = this._client.clientOptions.middleware) === null || _a === void 0 ? void 0 : _a.workspace;
return (middleware === null || middleware === void 0 ? void 0 : middleware.willRenameFiles) ? middleware.willRenameFiles(event, next)
: next(event);
}
}
exports.WillRenameFilesFeature = WillRenameFilesFeature;
class WillDeleteFilesFeature extends RequestFileOperationFeature {
constructor(client) {
super(client, code.workspace.onWillDeleteFiles, proto.WillDeleteFilesRequest.type, 'willDelete', 'willDelete', (i) => i, client.code2ProtocolConverter.asWillDeleteFilesParams);
}
doSend(event, next) {
var _a;
const middleware = (_a = this._client.clientOptions.middleware) === null || _a === void 0 ? void 0 : _a.workspace;
return (middleware === null || middleware === void 0 ? void 0 : middleware.willDeleteFiles) ? middleware.willDeleteFiles(event, next)
: next(event);
}
}
exports.WillDeleteFilesFeature = WillDeleteFilesFeature;
//# sourceMappingURL=fileOperations.js.map