@codingame/monaco-vscode-extensions-service-override
Version:
VSCode public API plugged on the monaco editor - extensions service-override
325 lines (321 loc) • 16.1 kB
JavaScript
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
import { DisposableStore, DisposableMap } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
import { FileOperation } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files';
import { IFileService } from '@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service';
import { extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js';
import { ExtHostContext, MainContext } from '@codingame/monaco-vscode-api/vscode/vs/workbench/api/common/extHost.protocol';
import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
import { IWorkingCopyFileService } from '@codingame/monaco-vscode-api/vscode/vs/workbench/services/workingCopy/common/workingCopyFileService.service';
import { IBulkEditService } from '@codingame/monaco-vscode-api/vscode/vs/editor/browser/services/bulkEditService.service';
import { ProgressLocation } from '@codingame/monaco-vscode-api/vscode/vs/platform/progress/common/progress';
import { IProgressService } from '@codingame/monaco-vscode-api/vscode/vs/platform/progress/common/progress.service';
import { raceCancellation } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
import { CancellationTokenSource } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
import { IDialogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/dialogs/common/dialogs.service';
import Severity from '@codingame/monaco-vscode-api/vscode/vs/base/common/severity';
import { StorageScope, StorageTarget } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage';
import { IStorageService } from '@codingame/monaco-vscode-api/vscode/vs/platform/storage/common/storage.service';
import { registerAction2, Action2 } from '@codingame/monaco-vscode-api/vscode/vs/platform/actions/common/actions';
import { ILogService } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service';
import { IEnvironmentService } from '@codingame/monaco-vscode-api/vscode/vs/platform/environment/common/environment.service';
import { IUriIdentityService } from '@codingame/monaco-vscode-api/vscode/vs/platform/uriIdentity/common/uriIdentity.service';
import { reviveWorkspaceEditDto } from './mainThreadBulkEdits.js';
import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
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,
_logService
) {
this._fileService = _fileService;
this._logService = _logService;
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(
2605,
"Extension '{0}' wants to make refactoring changes with this file creation",
data.extensionNames[0]
));
} else if (operation === FileOperation.COPY) {
message = ( localize(
2606,
"Extension '{0}' wants to make refactoring changes with this file copy",
data.extensionNames[0]
));
} else if (operation === FileOperation.MOVE) {
message = ( localize(
2607,
"Extension '{0}' wants to make refactoring changes with this file move",
data.extensionNames[0]
));
} else {
message = ( localize(
2608,
"Extension '{0}' wants to make refactoring changes with this file deletion",
data.extensionNames[0]
));
}
} else {
if (operation === FileOperation.CREATE) {
message = ( localize(
2609,
"{0} extensions want to make refactoring changes with this file creation",
data.extensionNames.length
));
} else if (operation === FileOperation.COPY) {
message = ( localize(
2610,
"{0} extensions want to make refactoring changes with this file copy",
data.extensionNames.length
));
} else if (operation === FileOperation.MOVE) {
message = ( localize(
2611,
"{0} extensions want to make refactoring changes with this file move",
data.extensionNames.length
));
} else {
message = ( localize(
2612,
"{0} extensions want to make refactoring changes with this file deletion",
data.extensionNames.length
));
}
}
if (needsConfirmation) {
const {
confirmed
} = await dialogService.confirm({
type: Severity.Info,
message,
primaryButton: ( localize(2613, "Show &&Preview")),
cancelButton: ( localize(2614, "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.Info,
message,
buttons: [{
label: ( localize(2615, "&&OK")),
run: () => Choice.OK
}, {
label: ( localize(2613, "Show &&Preview")),
run: () => Choice.Preview
}],
cancelButton: {
label: ( localize(2614, "Skip Changes")),
run: () => Choice.Cancel
},
checkbox: {
label: ( localize(2616, "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(2617, "Running 'File Create' participants...");
case FileOperation.MOVE:
return localize(2618, "Running 'File Rename' participants...");
case FileOperation.COPY:
return localize(2619, "Running 'File Copy' participants...");
case FileOperation.DELETE:
return localize(2620, "Running 'File Delete' participants...");
case FileOperation.WRITE:
return localize(2621, "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 canHandleWatcher = await this._fileService.canHandleResource(uri);
if (!canHandleWatcher) {
this._logService.warn(
`MainThreadFileSystemEventService#$watch(): cannot watch resource as its scheme is not handled by the file service (extension: ${extensionId}, path: ${( uri.toString(true))})`
);
}
const opts = {
...unvalidatedOpts
};
if (opts.recursive) {
try {
const stat = await this._fileService.stat(uri);
if (!stat.isDirectory) {
opts.recursive = false;
}
} catch (error) {}
}
if (correlate && !opts.recursive) {
this._logService.trace(
`MainThreadFileSystemEventService#$watch(): request to start watching correlated (extension: ${extensionId}, path: ${( uri.toString(true))}, recursive: ${opts.recursive}, session: ${session}, excludes: ${JSON.stringify(opts.excludes)}, includes: ${JSON.stringify(opts.includes)})`
);
const watcherDisposables = ( new DisposableStore());
const subscription = watcherDisposables.add(this._fileService.createWatcher(uri, {
...opts,
recursive: false
}));
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}, excludes: ${JSON.stringify(opts.excludes)}, includes: ${JSON.stringify(opts.includes)})`
);
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, ILogService))
], MainThreadFileSystemEventService);
registerAction2(class ResetMemento extends Action2 {
constructor() {
super({
id: "files.participants.resetChoice",
title: {
value: ( localize(2622, "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 };