mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
Merge remote-tracking branch 'origin/master' into alex/node-modules-types
This commit is contained in:
commit
b0af35c810
59
.github/workflows/ci.yml
vendored
59
.github/workflows/ci.yml
vendored
|
@ -28,8 +28,8 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
@ -71,8 +71,8 @@ jobs:
|
|||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: '**/node_modules'
|
||||
# key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
# key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
# - name: Get yarn cache directory path
|
||||
# id: yarnCacheDirPath
|
||||
# if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
@ -125,8 +125,8 @@ jobs:
|
|||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: '**/node_modules'
|
||||
# key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
# key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
# - name: Get yarn cache directory path
|
||||
# id: yarnCacheDirPath
|
||||
# if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
@ -184,8 +184,8 @@ jobs:
|
|||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: '**/node_modules'
|
||||
# key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
# key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
|
||||
# - name: Restore compiled core code
|
||||
# id: cacheCompiledCoreCode
|
||||
|
@ -246,8 +246,8 @@ jobs:
|
|||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: '**/node_modules'
|
||||
# key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
# key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
|
||||
# - name: Restore compiled core code
|
||||
# id: cacheCompiledCoreCode
|
||||
|
@ -291,8 +291,8 @@ jobs:
|
|||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: '**/node_modules'
|
||||
# key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
# key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
# - name: Get yarn cache directory path
|
||||
# id: yarnCacheDirPath
|
||||
# if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
@ -329,8 +329,8 @@ jobs:
|
|||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: '**/node_modules'
|
||||
# key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
# key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
|
||||
# - name: Restore compiled core code
|
||||
# id: cacheCompiledCoreCode
|
||||
|
@ -381,8 +381,8 @@ jobs:
|
|||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: '**/node_modules'
|
||||
# key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
# key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
|
||||
# - name: Restore compiled core code
|
||||
# id: cacheCompiledCoreCode
|
||||
|
@ -427,8 +427,8 @@ jobs:
|
|||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: '**/node_modules'
|
||||
# key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
# key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
|
||||
# - name: Restore compiled core code
|
||||
# id: cacheCompiledCoreCode
|
||||
|
@ -484,8 +484,8 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
@ -542,11 +542,12 @@ jobs:
|
|||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
!**/Release/*.pdb
|
||||
!**/Release/*.ilk
|
||||
!**/Release/obj/**
|
||||
key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
!**/Release/**/*.pdb
|
||||
!**/Release/**/*.ilk
|
||||
!**/Release/**/*.obj
|
||||
!**/Release/**/*.tlog
|
||||
key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
@ -594,8 +595,8 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
- name: Get yarn cache directory path
|
||||
id: yarnCacheDirPath
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
|
@ -643,8 +644,8 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-cacheNodeModules4-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules4-
|
||||
key: ${{ runner.os }}-cacheNodeModules5-${{ hashFiles('.yarnrc', 'remote/.yarnrc', '**/yarn.lock', '!**/node_modules/**/yarn.lock', '!**/.*/**/yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cacheNodeModules5-
|
||||
- name: Execute yarn
|
||||
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
|
||||
env:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.53.0",
|
||||
"distro": "c89ced323fffc6ffd5caa6e9bb6662b8e26b5fb4",
|
||||
"distro": "252d98105e15a5ba22421ff5aef8d1aa7c3b69fa",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
|
|
@ -1014,12 +1014,11 @@ export class MouseTargetFactory {
|
|||
}
|
||||
|
||||
private static _snapToSoftTabBoundary(position: Position, viewModel: IViewModel): Position {
|
||||
const minColumn = viewModel.getLineMinColumn(position.lineNumber);
|
||||
const lineContent = viewModel.getLineContent(position.lineNumber);
|
||||
const { tabSize } = viewModel.getTextModelOptions();
|
||||
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - minColumn, tabSize, Direction.Nearest);
|
||||
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, position.column - 1, tabSize, Direction.Nearest);
|
||||
if (newPosition !== -1) {
|
||||
return new Position(position.lineNumber, newPosition + minColumn);
|
||||
return new Position(position.lineNumber, newPosition + 1);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
|
|
@ -39,11 +39,11 @@ export class MoveOperations {
|
|||
public static leftPositionAtomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number): Position {
|
||||
const minColumn = model.getLineMinColumn(lineNumber);
|
||||
const lineContent = model.getLineContent(lineNumber);
|
||||
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Left);
|
||||
if (newPosition === -1) {
|
||||
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - 1, tabSize, Direction.Left);
|
||||
if (newPosition === -1 || newPosition + 1 < minColumn) {
|
||||
return this.leftPosition(model, lineNumber, column);
|
||||
}
|
||||
return new Position(lineNumber, minColumn + newPosition);
|
||||
return new Position(lineNumber, newPosition + 1);
|
||||
}
|
||||
|
||||
public static left(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition {
|
||||
|
@ -81,13 +81,12 @@ export class MoveOperations {
|
|||
}
|
||||
|
||||
public static rightPositionAtomicSoftTabs(model: ICursorSimpleModel, lineNumber: number, column: number, tabSize: number, indentSize: number): Position {
|
||||
const minColumn = model.getLineMinColumn(lineNumber);
|
||||
const lineContent = model.getLineContent(lineNumber);
|
||||
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - minColumn, tabSize, Direction.Right);
|
||||
const newPosition = AtomicTabMoveOperations.atomicPosition(lineContent, column - 1, tabSize, Direction.Right);
|
||||
if (newPosition === -1) {
|
||||
return this.rightPosition(model, lineNumber, column);
|
||||
}
|
||||
return new Position(lineNumber, minColumn + newPosition);
|
||||
return new Position(lineNumber, newPosition + 1);
|
||||
}
|
||||
|
||||
public static right(config: CursorConfiguration, model: ICursorSimpleModel, lineNumber: number, column: number): CursorPosition {
|
||||
|
|
|
@ -2349,6 +2349,37 @@ suite('Editor Controller - Regression tests', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('issue #112301: new stickyTabStops feature interferes with word wrap', () => {
|
||||
withTestCodeEditor([
|
||||
[
|
||||
'function hello() {',
|
||||
' console.log(`this is a long console message`)',
|
||||
'}',
|
||||
].join('\n')
|
||||
], { wordWrap: 'wordWrapColumn', wordWrapColumn: 32, stickyTabStops: true }, (editor, viewModel) => {
|
||||
viewModel.setSelections('test', [
|
||||
new Selection(2, 31, 2, 31)
|
||||
]);
|
||||
moveRight(editor, viewModel, false);
|
||||
assertCursor(viewModel, new Position(2, 32));
|
||||
|
||||
moveRight(editor, viewModel, false);
|
||||
assertCursor(viewModel, new Position(2, 33));
|
||||
|
||||
moveRight(editor, viewModel, false);
|
||||
assertCursor(viewModel, new Position(2, 34));
|
||||
|
||||
moveLeft(editor, viewModel, false);
|
||||
assertCursor(viewModel, new Position(2, 33));
|
||||
|
||||
moveLeft(editor, viewModel, false);
|
||||
assertCursor(viewModel, new Position(2, 32));
|
||||
|
||||
moveLeft(editor, viewModel, false);
|
||||
assertCursor(viewModel, new Position(2, 31));
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #44805: Should not be able to undo in readonly editor', () => {
|
||||
let model = createTextModel(
|
||||
[
|
||||
|
|
|
@ -10,7 +10,7 @@ import { ExtHostContext, FileSystemEvents, IExtHostContext } from '../common/ext
|
|||
import { localize } from 'vs/nls';
|
||||
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IWorkingCopyFileOperationParticipant, IWorkingCopyFileService, SourceTargetPair } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { IWorkingCopyFileOperationParticipant, IWorkingCopyFileService, SourceTargetPair, IFileOperationUndoRedoInfo } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { reviveWorkspaceEditDto2 } from 'vs/workbench/api/browser/mainThreadEditors';
|
||||
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
|
@ -74,8 +74,8 @@ export class MainThreadFileSystemEventService {
|
|||
|
||||
|
||||
const fileOperationParticipant = new class implements IWorkingCopyFileOperationParticipant {
|
||||
async participate(files: SourceTargetPair[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined, timeout: number, token: CancellationToken) {
|
||||
if (isUndoing) {
|
||||
async participate(files: SourceTargetPair[], operation: FileOperation, undoInfo: IFileOperationUndoRedoInfo | undefined, timeout: number, token: CancellationToken) {
|
||||
if (undoInfo?.isUndoing) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ export class MainThreadFileSystemEventService {
|
|||
|
||||
await bulkEditService.apply(
|
||||
reviveWorkspaceEditDto2(data.edit),
|
||||
{ undoRedoGroupId, showPreview }
|
||||
{ undoRedoGroupId: undoInfo?.undoRedoGroupId, showPreview }
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import { WorkspaceFileEditOptions } from 'vs/editor/common/modes';
|
|||
import { IFileService, FileSystemProviderCapabilities, IFileContent } from 'vs/platform/files/common/files';
|
||||
import { IProgress } from 'vs/platform/progress/common/progress';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { IWorkingCopyFileService, IFileOperationUndoRedoInfo } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { IWorkspaceUndoRedoElement, UndoRedoElementType, IUndoRedoService, UndoRedoGroup, UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -18,11 +18,6 @@ import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService';
|
|||
import * as resources from 'vs/base/common/resources';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
interface IFileOperationUndoRedoInfo {
|
||||
undoRedoGroupId?: number;
|
||||
isUndoing?: boolean;
|
||||
}
|
||||
|
||||
interface IFileOperation {
|
||||
uris: URI[];
|
||||
perform(token: CancellationToken): Promise<IFileOperation>;
|
||||
|
@ -57,7 +52,7 @@ class RenameOperation implements IFileOperation {
|
|||
return new Noop(); // not overwriting, but ignoring, and the target file exists
|
||||
}
|
||||
|
||||
await this._workingCopyFileService.move([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }, token);
|
||||
await this._workingCopyFileService.move([{ file: { source: this.oldUri, target: this.newUri }, overwrite: this.options.overwrite }], this.undoRedoInfo, token);
|
||||
return new RenameOperation(this.oldUri, this.newUri, this.options, { isUndoing: true }, this._workingCopyFileService, this._fileService);
|
||||
}
|
||||
|
||||
|
@ -93,7 +88,7 @@ class CopyOperation implements IFileOperation {
|
|||
return new Noop(); // not overwriting, but ignoring, and the target file exists
|
||||
}
|
||||
|
||||
const stat = await this._workingCopyFileService.copy([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo }, token);
|
||||
const stat = await this._workingCopyFileService.copy([{ file: { source: this.oldUri, target: this.newUri }, overwrite: this.options.overwrite }], this.undoRedoInfo, token);
|
||||
const folder = this.options.folder || (stat.length === 1 && stat[0].isDirectory);
|
||||
return this._instaService.createInstance(DeleteOperation, this.newUri, { recursive: true, folder, ...this.options }, { isUndoing: true }, false);
|
||||
}
|
||||
|
@ -125,9 +120,9 @@ class CreateOperation implements IFileOperation {
|
|||
return new Noop(); // not overwriting, but ignoring, and the target file exists
|
||||
}
|
||||
if (this.options.folder) {
|
||||
await this._workingCopyFileService.createFolder(this.newUri, { ...this.undoRedoInfo }, token);
|
||||
await this._workingCopyFileService.createFolder({ resource: this.newUri }, this.undoRedoInfo, token);
|
||||
} else {
|
||||
await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite, ...this.undoRedoInfo }, token);
|
||||
await this._workingCopyFileService.create({ resource: this.newUri, contents: this.contents, overwrite: this.options.overwrite }, this.undoRedoInfo, token);
|
||||
}
|
||||
return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, !this.options.folder && !this.contents);
|
||||
}
|
||||
|
@ -175,7 +170,7 @@ class DeleteOperation implements IFileOperation {
|
|||
}
|
||||
|
||||
const useTrash = !this.options.skipTrashBin && this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue<boolean>('files.enableTrash');
|
||||
await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo }, token);
|
||||
await this._workingCopyFileService.delete([{ resource: this.oldUri, useTrash, recursive: this.options.recursive }], this.undoRedoInfo, token);
|
||||
|
||||
if (typeof this.options.maxSize === 'number' && fileContent && (fileContent?.size > this.options.maxSize)) {
|
||||
return new Noop();
|
||||
|
|
|
@ -151,7 +151,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
|
|||
async create(resource: URI, value?: string | ITextSnapshot, options?: ICreateFileOptions): Promise<IFileStatWithMetadata> {
|
||||
const readable = await this.getEncodedReadable(resource, value);
|
||||
|
||||
return this.workingCopyFileService.create(resource, readable, options);
|
||||
return await this.workingCopyFileService.create({ resource, contents: readable, overwrite: options?.overwrite });
|
||||
}
|
||||
|
||||
async write(resource: URI, value: string | ITextSnapshot, options?: IWriteTextFileOptions): Promise<IFileStatWithMetadata> {
|
||||
|
@ -243,7 +243,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
|
|||
// However, this will only work if the source exists
|
||||
// and is not orphaned, so we need to check that too.
|
||||
if (this.fileService.canHandleResource(source) && this.uriIdentityService.extUri.isEqual(source, target) && (await this.fileService.exists(source))) {
|
||||
await this.workingCopyFileService.move([{ source, target }]);
|
||||
await this.workingCopyFileService.move([{ file: { source, target } }]);
|
||||
|
||||
return this.save(target, options);
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IWorkingCopyFileOperationParticipant } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IWorkingCopyFileOperationParticipant, SourceTargetPair, IFileOperationUndoRedoInfo } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { FileOperation } from 'vs/platform/files/common/files';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
|
@ -28,7 +27,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable {
|
|||
return toDisposable(() => remove());
|
||||
}
|
||||
|
||||
async participate(files: { source?: URI, target: URI }[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined, token: CancellationToken | undefined): Promise<void> {
|
||||
async participate(files: SourceTargetPair[], operation: FileOperation, undoInfo: IFileOperationUndoRedoInfo | undefined, token: CancellationToken | undefined): Promise<void> {
|
||||
const timeout = this.configurationService.getValue<number>('files.participants.timeout');
|
||||
if (timeout <= 0) {
|
||||
return; // disabled
|
||||
|
@ -37,7 +36,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable {
|
|||
// For each participant
|
||||
for (const participant of this.participants) {
|
||||
try {
|
||||
await participant.participate(files, operation, undoRedoGroupId, isUndoing, timeout, token ?? CancellationToken.None);
|
||||
await participant.participate(files, operation, undoInfo, timeout, token ?? CancellationToken.None);
|
||||
} catch (err) {
|
||||
this.logService.warn(err);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,19 @@ export interface SourceTargetPair {
|
|||
readonly target: URI
|
||||
}
|
||||
|
||||
export interface IFileOperationUndoRedoInfo {
|
||||
|
||||
/**
|
||||
* Id of the undo group that the file operation belongs to.
|
||||
*/
|
||||
undoRedoGroupId?: number;
|
||||
|
||||
/**
|
||||
* Flag indicates if the operation is an undo.
|
||||
*/
|
||||
isUndoing?: boolean
|
||||
}
|
||||
|
||||
export interface WorkingCopyFileEvent extends IWaitUntil {
|
||||
|
||||
/**
|
||||
|
@ -59,13 +72,34 @@ export interface IWorkingCopyFileOperationParticipant {
|
|||
participate(
|
||||
files: SourceTargetPair[],
|
||||
operation: FileOperation,
|
||||
undoRedoGroupId: number | undefined,
|
||||
isUndoing: boolean | undefined,
|
||||
undoInfo: IFileOperationUndoRedoInfo | undefined,
|
||||
timeout: number,
|
||||
token: CancellationToken
|
||||
): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ICreateOperation {
|
||||
resource: URI;
|
||||
overwrite?: boolean;
|
||||
}
|
||||
|
||||
export interface ICreateFileOperation extends ICreateOperation {
|
||||
contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream,
|
||||
}
|
||||
|
||||
export interface IDeleteOperation {
|
||||
resource: URI;
|
||||
useTrash?: boolean;
|
||||
recursive?: boolean;
|
||||
}
|
||||
|
||||
export interface IMoveOperation {
|
||||
file: Required<SourceTargetPair>;
|
||||
overwrite?: boolean;
|
||||
}
|
||||
|
||||
export interface ICopyOperation extends IMoveOperation { }
|
||||
|
||||
/**
|
||||
* Returns the working copies for a given resource.
|
||||
*/
|
||||
|
@ -130,7 +164,7 @@ export interface IWorkingCopyFileService {
|
|||
* Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
|
||||
* `onDidRunWorkingCopyFileOperation` events to participate.
|
||||
*/
|
||||
create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata>;
|
||||
create(operation: ICreateFileOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata>;
|
||||
|
||||
/**
|
||||
* Will create a folder and any parent folder that needs to be created.
|
||||
|
@ -141,7 +175,7 @@ export interface IWorkingCopyFileService {
|
|||
* Note: events will only be emitted for the provided resource, but not any
|
||||
* parent folders that are being created as part of the operation.
|
||||
*/
|
||||
createFolder(resource: URI, options?: { undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata>;
|
||||
createFolder(operation: ICreateOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata>;
|
||||
|
||||
/**
|
||||
* Will move working copies matching the provided resources and corresponding children
|
||||
|
@ -150,7 +184,7 @@ export interface IWorkingCopyFileService {
|
|||
* Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
|
||||
* `onDidRunWorkingCopyFileOperation` events to participate.
|
||||
*/
|
||||
move(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata[]>;
|
||||
move(operations: IMoveOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata[]>;
|
||||
|
||||
/**
|
||||
* Will copy working copies matching the provided resources and corresponding children
|
||||
|
@ -159,7 +193,7 @@ export interface IWorkingCopyFileService {
|
|||
* Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
|
||||
* `onDidRunWorkingCopyFileOperation` events to participate.
|
||||
*/
|
||||
copy(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata[]>;
|
||||
copy(operations: ICopyOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata[]>;
|
||||
|
||||
/**
|
||||
* Will delete working copies matching the provided resources and children
|
||||
|
@ -168,7 +202,7 @@ export interface IWorkingCopyFileService {
|
|||
* Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
|
||||
* `onDidRunWorkingCopyFileOperation` events to participate.
|
||||
*/
|
||||
delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<void>;
|
||||
delete(operations: IDeleteOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<void>;
|
||||
|
||||
//#endregion
|
||||
|
||||
|
@ -237,38 +271,38 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
|
|||
|
||||
//#region File operations
|
||||
|
||||
create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata> {
|
||||
return this.doCreateFileOrFolder(resource, true, contents, options, token);
|
||||
create(operation: ICreateFileOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata> {
|
||||
return this.doCreateFileOrFolder(operation, true, undoInfo, token);
|
||||
}
|
||||
|
||||
createFolder(resource: URI, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata> {
|
||||
return this.doCreateFileOrFolder(resource, false, undefined, options, token);
|
||||
createFolder(operation: ICreateOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata> {
|
||||
return this.doCreateFileOrFolder(operation, false, undoInfo, token);
|
||||
}
|
||||
|
||||
async doCreateFileOrFolder(resource: URI, isFile: boolean, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata> {
|
||||
async doCreateFileOrFolder(operation: ICreateFileOperation | ICreateOperation, isFile: boolean, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata> {
|
||||
|
||||
// validate create operation before starting
|
||||
if (isFile) {
|
||||
const validateCreate = await this.fileService.canCreateFile(resource, options);
|
||||
const validateCreate = await this.fileService.canCreateFile(operation.resource, { overwrite: operation.overwrite });
|
||||
if (validateCreate instanceof Error) {
|
||||
throw validateCreate;
|
||||
}
|
||||
}
|
||||
|
||||
// file operation participant
|
||||
await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE, options?.undoRedoGroupId, options?.isUndoing, token);
|
||||
await this.runFileOperationParticipants([{ target: operation.resource }], FileOperation.CREATE, undoInfo, token);
|
||||
|
||||
// before events
|
||||
const event = { correlationId: this.correlationIds++, operation: FileOperation.CREATE, files: [{ target: resource }] };
|
||||
const event = { correlationId: this.correlationIds++, operation: FileOperation.CREATE, files: [{ target: operation.resource }] };
|
||||
await this._onWillRunWorkingCopyFileOperation.fireAsync(event, CancellationToken.None);
|
||||
|
||||
// now actually create on disk
|
||||
let stat: IFileStatWithMetadata;
|
||||
try {
|
||||
if (isFile) {
|
||||
stat = await this.fileService.createFile(resource, contents, { overwrite: options?.overwrite });
|
||||
stat = await this.fileService.createFile(operation.resource, (operation as ICreateFileOperation).contents, { overwrite: operation.overwrite });
|
||||
} else {
|
||||
stat = await this.fileService.createFolder(resource);
|
||||
stat = await this.fileService.createFolder(operation.resource);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
|
@ -284,20 +318,19 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
|
|||
return stat;
|
||||
}
|
||||
|
||||
async move(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata[]> {
|
||||
return this.doMoveOrCopy(files, true, options, token);
|
||||
async move(operations: IMoveOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata[]> {
|
||||
return this.doMoveOrCopy(operations, true, undoInfo, token);
|
||||
}
|
||||
|
||||
async copy(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata[]> {
|
||||
return this.doMoveOrCopy(files, false, options, token);
|
||||
async copy(operations: ICopyOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata[]> {
|
||||
return this.doMoveOrCopy(operations, false, undoInfo, token);
|
||||
}
|
||||
|
||||
private async doMoveOrCopy(files: Required<SourceTargetPair>[], move: boolean, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<IFileStatWithMetadata[]> {
|
||||
const overwrite = options?.overwrite;
|
||||
private async doMoveOrCopy(operations: IMoveOperation[] | ICopyOperation[], move: boolean, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata[]> {
|
||||
const stats: IFileStatWithMetadata[] = [];
|
||||
|
||||
// validate move/copy operation before starting
|
||||
for (const { source, target } of files) {
|
||||
for (const { file: { source, target }, overwrite } of operations) {
|
||||
const validateMoveOrCopy = await (move ? this.fileService.canMove(source, target, overwrite) : this.fileService.canCopy(source, target, overwrite));
|
||||
if (validateMoveOrCopy instanceof Error) {
|
||||
throw validateMoveOrCopy;
|
||||
|
@ -305,15 +338,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
|
|||
}
|
||||
|
||||
// file operation participant
|
||||
await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY, options?.undoRedoGroupId, options?.isUndoing, token);
|
||||
const files = operations.map(o => o.file);
|
||||
await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY, undoInfo, token);
|
||||
|
||||
// before event
|
||||
const event = { correlationId: this.correlationIds++, operation: move ? FileOperation.MOVE : FileOperation.COPY, files };
|
||||
await this._onWillRunWorkingCopyFileOperation.fireAsync(event, CancellationToken.None);
|
||||
|
||||
try {
|
||||
for (const { source, target } of files) {
|
||||
|
||||
for (const { file: { source, target }, overwrite } of operations) {
|
||||
// if source and target are not equal, handle dirty working copies
|
||||
// depending on the operation:
|
||||
// - move: revert both source and target (if any)
|
||||
|
@ -344,19 +377,19 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
|
|||
return stats;
|
||||
}
|
||||
|
||||
async delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }, token?: CancellationToken): Promise<void> {
|
||||
async delete(operations: IDeleteOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<void> {
|
||||
|
||||
// validate delete operation before starting
|
||||
for (const resource of resources) {
|
||||
const validateDelete = await this.fileService.canDelete(resource, options);
|
||||
for (const operation of operations) {
|
||||
const validateDelete = await this.fileService.canDelete(operation.resource, { recursive: operation.recursive, useTrash: operation.useTrash });
|
||||
if (validateDelete instanceof Error) {
|
||||
throw validateDelete;
|
||||
}
|
||||
}
|
||||
|
||||
// file operation participant
|
||||
const files = resources.map(target => ({ target }));
|
||||
await this.runFileOperationParticipants(files, FileOperation.DELETE, options?.undoRedoGroupId, options?.isUndoing, token);
|
||||
const files = operations.map(operation => ({ target: operation.resource }));
|
||||
await this.runFileOperationParticipants(files, FileOperation.DELETE, undoInfo, token);
|
||||
|
||||
// before events
|
||||
const event = { correlationId: this.correlationIds++, operation: FileOperation.DELETE, files };
|
||||
|
@ -365,15 +398,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
|
|||
// check for any existing dirty working copies for the resource
|
||||
// and do a soft revert before deleting to be able to close
|
||||
// any opened editor with these working copies
|
||||
for (const resource of resources) {
|
||||
const dirtyWorkingCopies = this.getDirty(resource);
|
||||
for (const operation of operations) {
|
||||
const dirtyWorkingCopies = this.getDirty(operation.resource);
|
||||
await Promise.all(dirtyWorkingCopies.map(dirtyWorkingCopy => dirtyWorkingCopy.revert({ soft: true })));
|
||||
}
|
||||
|
||||
// now actually delete from disk
|
||||
try {
|
||||
for (const resource of resources) {
|
||||
await this.fileService.del(resource, options);
|
||||
for (const operation of operations) {
|
||||
await this.fileService.del(operation.resource, { recursive: operation.recursive, useTrash: operation.useTrash });
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
|
@ -398,8 +431,8 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
|
|||
return this.fileOperationParticipants.addFileOperationParticipant(participant);
|
||||
}
|
||||
|
||||
private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined, token: CancellationToken | undefined): Promise<void> {
|
||||
return this.fileOperationParticipants.participate(files, operation, undoRedoGroupId, isUndoing, token);
|
||||
private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation, undoInfo: IFileOperationUndoRedoInfo | undefined, token: CancellationToken | undefined): Promise<void> {
|
||||
return this.fileOperationParticipants.participate(files, operation, undoInfo, token);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
|
|
@ -13,6 +13,7 @@ import { URI } from 'vs/base/common/uri';
|
|||
import { FileOperation } from 'vs/platform/files/common/files';
|
||||
import { TestWorkingCopy } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { ICopyOperation } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
|
||||
suite('WorkingCopyFileService', () => {
|
||||
|
||||
|
@ -52,7 +53,7 @@ suite('WorkingCopyFileService', () => {
|
|||
let sourceModel: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8', undefined);
|
||||
(<TestTextFileEditorModelManager>accessor.textFileService.files).add(sourceModel.resource, sourceModel);
|
||||
|
||||
const eventCounter = await testEventsMoveOrCopy([{ source: sourceModel.resource, target: sourceModel.resource }], true);
|
||||
const eventCounter = await testEventsMoveOrCopy([{ file: { source: sourceModel.resource, target: sourceModel.resource }, overwrite: true }], true);
|
||||
|
||||
sourceModel.dispose();
|
||||
assert.equal(eventCounter, 3);
|
||||
|
@ -67,8 +68,8 @@ suite('WorkingCopyFileService', () => {
|
|||
(<TestTextFileEditorModelManager>accessor.textFileService.files).add(targetModel2.resource, targetModel2);
|
||||
|
||||
const eventCounter = await testEventsMoveOrCopy([
|
||||
{ source: sourceModel1.resource, target: sourceModel1.resource },
|
||||
{ source: sourceModel2.resource, target: targetModel2.resource }
|
||||
{ file: { source: sourceModel1.resource, target: sourceModel1.resource }, overwrite: true },
|
||||
{ file: { source: sourceModel2.resource, target: targetModel2.resource }, overwrite: true }
|
||||
], true);
|
||||
|
||||
sourceModel1.dispose();
|
||||
|
@ -96,7 +97,7 @@ suite('WorkingCopyFileService', () => {
|
|||
let sourceModel: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/file.txt'), 'utf8', undefined);
|
||||
(<TestTextFileEditorModelManager>accessor.textFileService.files).add(sourceModel.resource, sourceModel);
|
||||
|
||||
const eventCounter = await testEventsMoveOrCopy([{ source: sourceModel.resource, target: sourceModel.resource }]);
|
||||
const eventCounter = await testEventsMoveOrCopy([{ file: { source: sourceModel.resource, target: sourceModel.resource }, overwrite: true }]);
|
||||
|
||||
sourceModel.dispose();
|
||||
assert.equal(eventCounter, 3);
|
||||
|
@ -111,8 +112,8 @@ suite('WorkingCopyFileService', () => {
|
|||
(<TestTextFileEditorModelManager>accessor.textFileService.files).add(targetModel2.resource, targetModel2);
|
||||
|
||||
const eventCounter = await testEventsMoveOrCopy([
|
||||
{ source: sourceModel1.resource, target: sourceModel1.resource },
|
||||
{ source: sourceModel2.resource, target: targetModel2.resource }
|
||||
{ file: { source: sourceModel1.resource, target: sourceModel1.resource }, overwrite: true },
|
||||
{ file: { source: sourceModel2.resource, target: targetModel2.resource }, overwrite: true }
|
||||
]);
|
||||
|
||||
sourceModel1.dispose();
|
||||
|
@ -223,7 +224,7 @@ suite('WorkingCopyFileService', () => {
|
|||
eventCounter++;
|
||||
});
|
||||
|
||||
await accessor.workingCopyFileService.createFolder(resource);
|
||||
await accessor.workingCopyFileService.createFolder({ resource });
|
||||
|
||||
assert.equal(eventCounter, 3);
|
||||
|
||||
|
@ -232,7 +233,7 @@ suite('WorkingCopyFileService', () => {
|
|||
listener2.dispose();
|
||||
});
|
||||
|
||||
async function testEventsMoveOrCopy(files: { source: URI, target: URI }[], move?: boolean): Promise<number> {
|
||||
async function testEventsMoveOrCopy(files: ICopyOperation[], move?: boolean): Promise<number> {
|
||||
let eventCounter = 0;
|
||||
|
||||
const participant = accessor.workingCopyFileService.addFileOperationParticipant({
|
||||
|
@ -250,9 +251,9 @@ suite('WorkingCopyFileService', () => {
|
|||
});
|
||||
|
||||
if (move) {
|
||||
await accessor.workingCopyFileService.move(files, { overwrite: true });
|
||||
await accessor.workingCopyFileService.move(files);
|
||||
} else {
|
||||
await accessor.workingCopyFileService.copy(files, { overwrite: true });
|
||||
await accessor.workingCopyFileService.copy(files);
|
||||
}
|
||||
|
||||
participant.dispose();
|
||||
|
@ -330,9 +331,9 @@ suite('WorkingCopyFileService', () => {
|
|||
});
|
||||
|
||||
if (move) {
|
||||
await accessor.workingCopyFileService.move(models.map(model => ({ source: model.sourceModel.resource, target: model.targetModel.resource })), { overwrite: true });
|
||||
await accessor.workingCopyFileService.move(models.map(model => ({ file: { source: model.sourceModel.resource, target: model.targetModel.resource }, options: { overwrite: true } })));
|
||||
} else {
|
||||
await accessor.workingCopyFileService.copy(models.map(model => ({ source: model.sourceModel.resource, target: model.targetModel.resource })), { overwrite: true });
|
||||
await accessor.workingCopyFileService.copy(models.map(model => ({ file: { source: model.sourceModel.resource, target: model.targetModel.resource }, options: { overwrite: true } })));
|
||||
}
|
||||
|
||||
for (let i = 0; i < models.length; i++) {
|
||||
|
@ -406,7 +407,7 @@ suite('WorkingCopyFileService', () => {
|
|||
eventCounter++;
|
||||
});
|
||||
|
||||
await accessor.workingCopyFileService.delete(models.map(m => m.resource));
|
||||
await accessor.workingCopyFileService.delete(models.map(m => ({ resource: m.resource })));
|
||||
for (const model of models) {
|
||||
assert.ok(!accessor.workingCopyService.isDirty(model.resource));
|
||||
model.dispose();
|
||||
|
@ -458,7 +459,7 @@ suite('WorkingCopyFileService', () => {
|
|||
eventCounter++;
|
||||
});
|
||||
|
||||
await accessor.workingCopyFileService.create(resource, contents);
|
||||
await accessor.workingCopyFileService.create({ resource, contents });
|
||||
assert.ok(!accessor.workingCopyService.isDirty(model.resource));
|
||||
model.dispose();
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
|||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { IWorkingCopyFileService, IMoveOperation, IDeleteOperation, ICopyOperation, ICreateFileOperation } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
|
||||
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
|
@ -103,23 +103,23 @@ suite('MainThreadEditors', () => {
|
|||
});
|
||||
services.set(IWorkingCopyFileService, new class extends mock<IWorkingCopyFileService>() {
|
||||
onDidRunWorkingCopyFileOperation = Event.None;
|
||||
create(resource: URI) {
|
||||
createdResources.add(resource);
|
||||
create(operation: ICreateFileOperation) {
|
||||
createdResources.add(operation.resource);
|
||||
return Promise.resolve(Object.create(null));
|
||||
}
|
||||
move(files: { source: URI, target: URI }[]) {
|
||||
const { source, target } = files[0];
|
||||
move(operations: IMoveOperation[]) {
|
||||
const { source, target } = operations[0].file;
|
||||
movedResources.set(source, target);
|
||||
return Promise.resolve(Object.create(null));
|
||||
}
|
||||
copy(files: { source: URI, target: URI }[]) {
|
||||
const { source, target } = files[0];
|
||||
copy(operations: ICopyOperation[]) {
|
||||
const { source, target } = operations[0].file;
|
||||
copiedResources.set(source, target);
|
||||
return Promise.resolve(Object.create(null));
|
||||
}
|
||||
delete(resources: URI[]) {
|
||||
for (const resource of resources) {
|
||||
deletedResources.add(resource);
|
||||
delete(operations: IDeleteOperation[]) {
|
||||
for (const operation of operations) {
|
||||
deletedResources.add(operation.resource);
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,9 @@ import { isLinux, isMacintosh } from 'vs/base/common/platform';
|
|||
import { InMemoryStorageService, WillSaveStateReason } from 'vs/platform/storage/common/storage';
|
||||
import { WorkingCopyService, IWorkingCopy, IWorkingCopyBackup, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { NullExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent, IDeleteOperation, ICopyOperation, IMoveOperation, IFileOperationUndoRedoInfo, ICreateFileOperation, ICreateOperation } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IFileStatWithMetadata } from 'vs/platform/files/common/files';
|
||||
import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer';
|
||||
import { ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
|
@ -196,18 +195,18 @@ export class TestWorkingCopyFileService implements IWorkingCopyFileService {
|
|||
|
||||
addFileOperationParticipant(participant: IWorkingCopyFileOperationParticipant): IDisposable { return Disposable.None; }
|
||||
|
||||
async delete(resources: URI[], options?: { useTrash?: boolean | undefined; recursive?: boolean | undefined; } | undefined): Promise<void> { }
|
||||
async delete(operations: IDeleteOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<void> { }
|
||||
|
||||
registerWorkingCopyProvider(provider: (resourceOrFolder: URI) => IWorkingCopy[]): IDisposable { return Disposable.None; }
|
||||
|
||||
getDirty(resource: URI): IWorkingCopy[] { return []; }
|
||||
|
||||
create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean | undefined; } | undefined): Promise<IFileStatWithMetadata> { throw new Error('Method not implemented.'); }
|
||||
createFolder(resource: URI): Promise<IFileStatWithMetadata> { throw new Error('Method not implemented.'); }
|
||||
create(operation: ICreateFileOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata> { throw new Error('Method not implemented.'); }
|
||||
createFolder(operation: ICreateOperation, undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata> { throw new Error('Method not implemented.'); }
|
||||
|
||||
move(files: { source: URI; target: URI; }[], options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }
|
||||
move(operations: IMoveOperation[], undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }
|
||||
|
||||
copy(files: { source: URI; target: URI; }[], options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }
|
||||
copy(operations: ICopyOperation[], undoInfo?: IFileOperationUndoRedoInfo, token?: CancellationToken): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }
|
||||
}
|
||||
|
||||
export function mock<T>(): Ctor<T> {
|
||||
|
|
Loading…
Reference in a new issue