@codingame/monaco-vscode-extensions-service-override
Version:
VSCode public API plugged on the monaco editor - extensions service-override
316 lines (313 loc) • 17 kB
JavaScript
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js';
import { DisposableStore, DisposableMap } from 'vscode/vscode/vs/base/common/lifecycle';
import { FileOperation } from 'vscode/vscode/vs/platform/files/common/files';
import { IFileService } from 'vscode/vscode/vs/platform/files/common/files.service';
import { extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js';
import { ExtHostContext, MainContext } from 'vscode/vscode/vs/workbench/api/common/extHost.protocol';
import { localize } from 'vscode/vscode/vs/nls';
import { IWorkingCopyFileService } from 'vscode/vscode/vs/workbench/services/workingCopy/common/workingCopyFileService.service';
import { IBulkEditService } from 'vscode/vscode/vs/editor/browser/services/bulkEditService';
import { ProgressLocation } from 'vscode/vscode/vs/platform/progress/common/progress';
import { IProgressService } from 'vscode/vscode/vs/platform/progress/common/progress.service';
import { raceCancellation } from 'vscode/vscode/vs/base/common/async';
import { CancellationTokenSource } from 'vscode/vscode/vs/base/common/cancellation';
import { IDialogService } from 'vscode/vscode/vs/platform/dialogs/common/dialogs.service';
import Severity$1 from 'vscode/vscode/vs/base/common/severity';
import { StorageScope, StorageTarget } from 'vscode/vscode/vs/platform/storage/common/storage';
import { IStorageService } from 'vscode/vscode/vs/platform/storage/common/storage.service';
import { registerAction2, Action2 } from 'vscode/vscode/vs/platform/actions/common/actions';
import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service';
import { IEnvironmentService } from 'vscode/vscode/vs/platform/environment/common/environment.service';
import { IUriIdentityService } from 'vscode/vscode/vs/platform/uriIdentity/common/uriIdentity.service';
import { reviveWorkspaceEditDto } from './mainThreadBulkEdits.js';
import { GLOBSTAR } from 'vscode/vscode/vs/base/common/glob';
import { rtrim } from 'vscode/vscode/vs/base/common/strings';
import { URI } from 'vscode/vscode/vs/base/common/uri';
import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service';
import { normalizeWatcherPattern } from 'vscode/vscode/vs/platform/files/common/watcher';
import { IWorkspaceContextService } from 'vscode/vscode/vs/platform/workspace/common/workspace.service';
var MainThreadFileSystemEventService_1;
let MainThreadFileSystemEventService = class MainThreadFileSystemEventService {
static { MainThreadFileSystemEventService_1 = this; }
static { this.MementoKeyAdditionalEdits = `file.particpants.additionalEdits`; }
constructor(extHostContext, _fileService, workingCopyFileService, bulkEditService, progressService, dialogService, storageService, logService, envService, uriIdentService, _contextService, _logService, _configurationService) {
this._fileService = _fileService;
this._contextService = _contextService;
this._logService = _logService;
this._configurationService = _configurationService;
this._listener = ( (new DisposableStore()));
this._watches = ( (new DisposableMap()));
this._proxy = ( (extHostContext.getProxy(ExtHostContext.ExtHostFileSystemEventService)));
this._listener.add(_fileService.onDidFilesChange(event => {
this._proxy.$onFileEvent({
created: event.rawAdded,
changed: event.rawUpdated,
deleted: event.rawDeleted
});
}));
const that = this;
const fileOperationParticipant = new (class {
async participate(files, operation, undoInfo, timeout, token) {
if (undoInfo?.isUndoing) {
return;
}
const cts = ( (new CancellationTokenSource(token)));
const timer = setTimeout(() => cts.cancel(), timeout);
const data = await progressService.withProgress({
location: ProgressLocation.Notification,
title: this._progressLabel(operation),
cancellable: true,
delay: Math.min(timeout / 2, 3000)
}, () => {
const onWillEvent = that._proxy.$onWillRunFileOperation(operation, files, timeout, cts.token);
return raceCancellation(onWillEvent, cts.token);
}, () => {
cts.cancel();
}).finally(() => {
cts.dispose();
clearTimeout(timer);
});
if (!data || data.edit.edits.length === 0) {
return;
}
const needsConfirmation = ( (data.edit.edits.some(edit => edit.metadata?.needsConfirmation)));
let showPreview = storageService.getBoolean(MainThreadFileSystemEventService_1.MementoKeyAdditionalEdits, StorageScope.PROFILE);
if (envService.extensionTestsLocationURI) {
showPreview = false;
}
if (showPreview === undefined) {
let message;
if (data.extensionNames.length === 1) {
if (operation === FileOperation.CREATE) {
message = ( localize(
4841,
"Extension '{0}' wants to make refactoring changes with this file creation",
data.extensionNames[0]
));
}
else if (operation === FileOperation.COPY) {
message = ( localize(
4842,
"Extension '{0}' wants to make refactoring changes with this file copy",
data.extensionNames[0]
));
}
else if (operation === FileOperation.MOVE) {
message = ( localize(
4843,
"Extension '{0}' wants to make refactoring changes with this file move",
data.extensionNames[0]
));
}
else {
message = ( localize(
4844,
"Extension '{0}' wants to make refactoring changes with this file deletion",
data.extensionNames[0]
));
}
}
else {
if (operation === FileOperation.CREATE) {
message = ( localize(
4845,
"{0} extensions want to make refactoring changes with this file creation",
data.extensionNames.length
));
}
else if (operation === FileOperation.COPY) {
message = ( localize(
4846,
"{0} extensions want to make refactoring changes with this file copy",
data.extensionNames.length
));
}
else if (operation === FileOperation.MOVE) {
message = ( localize(
4847,
"{0} extensions want to make refactoring changes with this file move",
data.extensionNames.length
));
}
else {
message = ( localize(
4848,
"{0} extensions want to make refactoring changes with this file deletion",
data.extensionNames.length
));
}
}
if (needsConfirmation) {
const { confirmed } = await dialogService.confirm({
type: Severity$1.Info,
message,
primaryButton: ( localize(4849, "Show &&Preview")),
cancelButton: ( localize(4850, "Skip Changes"))
});
showPreview = true;
if (!confirmed) {
return;
}
}
else {
let Choice;
( ((function(Choice) {
Choice[Choice["OK"] = 0] = "OK";
Choice[Choice["Preview"] = 1] = "Preview";
Choice[Choice["Cancel"] = 2] = "Cancel";
})(Choice || (Choice = {}))));
const { result, checkboxChecked } = await dialogService.prompt({
type: Severity$1.Info,
message,
buttons: [
{
label: ( localize(4851, "&&OK")),
run: () => Choice.OK
},
{
label: ( localize(4849, "Show &&Preview")),
run: () => Choice.Preview
}
],
cancelButton: {
label: ( localize(4850, "Skip Changes")),
run: () => Choice.Cancel
},
checkbox: { label: ( localize(4852, "Do not ask me again")) }
});
if (result === Choice.Cancel) {
return;
}
showPreview = result === Choice.Preview;
if (checkboxChecked) {
storageService.store(MainThreadFileSystemEventService_1.MementoKeyAdditionalEdits, showPreview, StorageScope.PROFILE, StorageTarget.USER);
}
}
}
logService.info('[onWill-handler] applying additional workspace edit from extensions', data.extensionNames);
await bulkEditService.apply(reviveWorkspaceEditDto(data.edit, uriIdentService), { undoRedoGroupId: undoInfo?.undoRedoGroupId, showPreview });
}
_progressLabel(operation) {
switch (operation) {
case FileOperation.CREATE:
return ( localize(4853, "Running 'File Create' participants..."));
case FileOperation.MOVE:
return ( localize(4854, "Running 'File Rename' participants..."));
case FileOperation.COPY:
return ( localize(4855, "Running 'File Copy' participants..."));
case FileOperation.DELETE:
return ( localize(4856, "Running 'File Delete' participants..."));
case FileOperation.WRITE:
return ( localize(4857, "Running 'File Write' participants..."));
}
}
});
this._listener.add(workingCopyFileService.addFileOperationParticipant(fileOperationParticipant));
this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => this._proxy.$onDidRunFileOperation(e.operation, e.files)));
}
async $watch(extensionId, session, resource, unvalidatedOpts, correlate) {
const uri = URI.revive(resource);
const opts = {
...unvalidatedOpts
};
if (opts.recursive) {
try {
const stat = await this._fileService.stat(uri);
if (!stat.isDirectory) {
opts.recursive = false;
}
}
catch (error) {
}
}
if (correlate) {
this._logService.trace(`MainThreadFileSystemEventService#$watch(): request to start watching correlated (extension: ${extensionId}, path: ${( (uri.toString(true)))}, recursive: ${opts.recursive}, session: ${session})`);
const watcherDisposables = ( (new DisposableStore()));
const subscription = watcherDisposables.add(this._fileService.createWatcher(uri, opts));
watcherDisposables.add(subscription.onDidChange(event => {
this._proxy.$onFileEvent({
session,
created: event.rawAdded,
changed: event.rawUpdated,
deleted: event.rawDeleted
});
}));
this._watches.set(session, watcherDisposables);
}
else {
this._logService.trace(`MainThreadFileSystemEventService#$watch(): request to start watching uncorrelated (extension: ${extensionId}, path: ${( (uri.toString(true)))}, recursive: ${opts.recursive}, session: ${session})`);
const workspaceFolder = this._contextService.getWorkspaceFolder(uri);
if (opts.recursive && opts.excludes.length === 0) {
const config = this._configurationService.getValue();
if (config.files?.watcherExclude) {
for (const key in config.files.watcherExclude) {
if (key && config.files.watcherExclude[key] === true) {
opts.excludes.push(key);
}
}
}
}
else if (!opts.recursive && workspaceFolder) {
const config = this._configurationService.getValue();
if (config.files?.watcherExclude) {
for (const key in config.files.watcherExclude) {
if (key && config.files.watcherExclude[key] === true) {
if (!opts.includes) {
opts.includes = [];
}
const includePattern = `${rtrim(key, '/')}/${GLOBSTAR}`;
opts.includes.push(normalizeWatcherPattern(workspaceFolder.uri.fsPath, includePattern));
}
}
}
if (!opts.includes || opts.includes.length === 0) {
this._logService.trace(`MainThreadFileSystemEventService#$watch(): ignoring request to start watching because path is inside workspace and no excludes are configured (extension: ${extensionId}, path: ${( (uri.toString(true)))}, recursive: ${opts.recursive}, session: ${session})`);
return;
}
}
const subscription = this._fileService.watch(uri, opts);
this._watches.set(session, subscription);
}
}
$unwatch(session) {
if (( (this._watches.has(session)))) {
this._logService.trace(`MainThreadFileSystemEventService#$unwatch(): request to stop watching (session: ${session})`);
this._watches.deleteAndDispose(session);
}
}
dispose() {
this._listener.dispose();
this._watches.dispose();
}
};
MainThreadFileSystemEventService = MainThreadFileSystemEventService_1 = __decorate([
extHostNamedCustomer(MainContext.MainThreadFileSystemEventService),
( (__param(1, IFileService))),
( (__param(2, IWorkingCopyFileService))),
( (__param(3, IBulkEditService))),
( (__param(4, IProgressService))),
( (__param(5, IDialogService))),
( (__param(6, IStorageService))),
( (__param(7, ILogService))),
( (__param(8, IEnvironmentService))),
( (__param(9, IUriIdentityService))),
( (__param(10, IWorkspaceContextService))),
( (__param(11, ILogService))),
( (__param(12, IConfigurationService)))
], MainThreadFileSystemEventService);
registerAction2(class ResetMemento extends Action2 {
constructor() {
super({
id: 'files.participants.resetChoice',
title: {
value: ( localize(4858, "Reset choice for 'File operation needs preview'")),
original: `Reset choice for 'File operation needs preview'`
},
f1: true
});
}
run(accessor) {
accessor.get(IStorageService).remove(MainThreadFileSystemEventService.MementoKeyAdditionalEdits, StorageScope.PROFILE);
}
});
export { MainThreadFileSystemEventService };