Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement WorkspaceEditMetadata and add new preference for autosave on refactoring #12193

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/editor/src/browser/editor-preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ const fileContributionSchema: PreferenceSchema['properties'] = {
'minimum': 0,
'markdownDescription': nls.localizeByDefault('Controls the delay in milliseconds after which an editor with unsaved changes is saved automatically. Only applies when `#files.autoSave#` is set to `{0}`.', 'afterDelay')
},
'files.refactoring.autoSave': {
'type': 'boolean',
'default': true,
'markdownDescription': nls.localize('theia/editor/files.refactoring.autoSave', 'Controls if files that were part of a refactoring are saved automaticly.')
msujew marked this conversation as resolved.
Show resolved Hide resolved
}
};

interface FileContributionEditorPreferences {
Expand All @@ -131,6 +136,7 @@ interface FileContributionEditorPreferences {
'files.eol': '\n' | '\r\n' | 'auto';
'files.autoSave': 'off' | 'afterDelay' | 'onFocusChange' | 'onWindowChange';
'files.autoSaveDelay': number;
'files.refactoring.autoSave': boolean
}
// #endregion

Expand Down
2 changes: 1 addition & 1 deletion packages/monaco/src/browser/monaco-bulk-edit-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class MonacoBulkEditService implements IBulkEditService {
editsIn = await this._previewHandler(edits, options);
return { ariaSummary: '', success: true };
} else {
return this.workspace.applyBulkEdit(edits);
return this.workspace.applyBulkEdit(edits, options);
}
}

Expand Down
22 changes: 20 additions & 2 deletions packages/monaco/src/browser/monaco-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { injectable, inject, postConstruct } from '@theia/core/shared/inversify'
import URI from '@theia/core/lib/common/uri';
import { Emitter } from '@theia/core/lib/common/event';
import { FileSystemPreferences } from '@theia/filesystem/lib/browser';
import { EditorManager } from '@theia/editor/lib/browser';
import { EditorManager, EditorPreferences } from '@theia/editor/lib/browser';
import { MonacoTextModelService } from './monaco-text-model-service';
import { WillSaveMonacoModelEvent, MonacoEditorModel, MonacoModelContentChangedEvent } from './monaco-editor-model';
import { MonacoEditor } from './monaco-editor';
Expand All @@ -31,6 +31,7 @@ import { FileService } from '@theia/filesystem/lib/browser/file-service';
import { FileSystemProviderCapabilities } from '@theia/filesystem/lib/common/files';
import * as monaco from '@theia/monaco-editor-core';
import {
IBulkEditOptions,
IBulkEditResult, ResourceEdit, ResourceFileEdit as MonacoResourceFileEdit,
ResourceTextEdit as MonacoResourceTextEdit
} from '@theia/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService';
Expand Down Expand Up @@ -111,6 +112,9 @@ export class MonacoWorkspace {
@inject(FileSystemPreferences)
protected readonly filePreferences: FileSystemPreferences;

@inject(EditorPreferences)
protected readonly editorPreferences: EditorPreferences;

@inject(MonacoTextModelService)
protected readonly textModelService: MonacoTextModelService;

Expand Down Expand Up @@ -226,7 +230,7 @@ export class MonacoWorkspace {
});
}

async applyBulkEdit(edits: ResourceEdit[]): Promise<IBulkEditResult & { success: boolean }> {
async applyBulkEdit(edits: ResourceEdit[], options?: IBulkEditOptions): Promise<IBulkEditResult & { success: boolean }> {
try {
let totalEdits = 0;
let totalFiles = 0;
Expand All @@ -248,6 +252,13 @@ export class MonacoWorkspace {
await this.performSnippetEdits(<MonacoResourceTextEdit[]>snippetEdits);
}

// when enabled (option AND setting) loop over all dirty working copies and trigger save
// for those that were involved in this bulk edit operation.
const resources = new Set<string>(edits.filter(edit => edit instanceof MonacoResourceTextEdit).map(edit => (edit as MonacoResourceTextEdit).resource.toString()));
if (options?.respectAutoSaveConfig && this.editorPreferences.get('files.refactoring.autoSave') === true && resources.size > 0) {
this.saveAll(resources);
}
msujew marked this conversation as resolved.
Show resolved Hide resolved

const ariaSummary = this.getAriaSummary(totalEdits, totalFiles);
return { ariaSummary, success: true };
} catch (e) {
Expand All @@ -259,6 +270,13 @@ export class MonacoWorkspace {
}
}

protected saveAll(resources: Set<string>): void {
for (const uri of resources.values()) {
this.textModelService.get(uri)?.save();
}

}
msujew marked this conversation as resolved.
Show resolved Hide resolved

protected getAriaSummary(totalEdits: number, totalFiles: number): string {
if (totalEdits === 0) {
return 'Made no edits';
Expand Down
11 changes: 7 additions & 4 deletions packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,7 @@ export interface TextEditorsMain {
$tryRevealRange(id: string, range: Range, revealType: TextEditorRevealType): Promise<void>;
$trySetSelections(id: string, selections: Selection[]): Promise<void>;
$tryApplyEdits(id: string, modelVersionId: number, edits: SingleEditOperation[], opts: ApplyEditsOptions): Promise<boolean>;
$tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto): Promise<boolean>;
$tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto, metadata?: WorkspaceEditMetdataDto): Promise<boolean>;
$tryInsertSnippet(id: string, template: string, selections: Range[], opts: UndoStopOptions): Promise<boolean>;
$saveAll(includeUntitled?: boolean): Promise<boolean>;
// $getDiffInformation(id: string): Promise<editorCommon.ILineChange[]>;
Expand Down Expand Up @@ -1418,7 +1418,7 @@ export interface CodeActionDto {
disabled?: string;
}

export interface WorkspaceEditMetadataDto {
export interface WorkspaceEditEntryMetadataDto {
needsConfirmation: boolean;
label: string;
description?: string;
Expand All @@ -1434,14 +1434,14 @@ export interface WorkspaceFileEditDto {
oldResource?: UriComponents;
newResource?: UriComponents;
options?: FileOperationOptions;
metadata?: WorkspaceEditMetadataDto;
metadata?: WorkspaceEditEntryMetadataDto;
}

export interface WorkspaceTextEditDto {
resource: UriComponents;
modelVersionId?: number;
textEdit: TextEdit & { insertAsSnippet?: boolean };
metadata?: WorkspaceEditMetadataDto;
metadata?: WorkspaceEditEntryMetadataDto;
}
export namespace WorkspaceTextEditDto {
export function is(arg: WorkspaceTextEditDto | WorkspaceFileEditDto): arg is WorkspaceTextEditDto {
Expand All @@ -1452,6 +1452,9 @@ export namespace WorkspaceTextEditDto {
&& typeof arg.textEdit === 'object';
}
}
export interface WorkspaceEditMetdataDto {
msujew marked this conversation as resolved.
Show resolved Hide resolved
isRefactoring?: boolean;
}

export interface WorkspaceEditDto {
edits: Array<WorkspaceTextEditDto | WorkspaceFileEditDto>;
Expand Down
5 changes: 3 additions & 2 deletions packages/plugin-ext/src/main/browser/text-editors-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
DecorationOptions,
WorkspaceEditDto,
DocumentsMain,
WorkspaceEditMetdataDto,
} from '../../common/plugin-api-rpc';
import { Range, TextDocumentShowOptions } from '../../common/plugin-api-rpc-model';
import { EditorsAndDocumentsMain } from './editors-and-documents-main';
Expand Down Expand Up @@ -126,11 +127,11 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
return Promise.resolve(this.editorsAndDocuments.getEditor(id)!.applyEdits(modelVersionId, edits, opts));
}

async $tryApplyWorkspaceEdit(dto: WorkspaceEditDto): Promise<boolean> {
async $tryApplyWorkspaceEdit(dto: WorkspaceEditDto, metadata?: WorkspaceEditMetdataDto): Promise<boolean> {
const workspaceEdit = toMonacoWorkspaceEdit(dto);
try {
const edits = ResourceEdit.convert(workspaceEdit);
const { success } = await this.bulkEditService.apply(edits);
const { success } = await this.bulkEditService.apply(edits, { respectAutoSaveConfig: metadata?.isRefactoring });
return success;
} catch {
return false;
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -670,8 +670,8 @@ export function createAPIFactory(
saveAll(includeUntitled?: boolean): PromiseLike<boolean> {
return editors.saveAll(includeUntitled);
},
applyEdit(edit: theia.WorkspaceEdit): PromiseLike<boolean> {
return editors.applyWorkspaceEdit(edit);
applyEdit(edit: theia.WorkspaceEdit, metadata?: theia.WorkspaceEditMetadata): PromiseLike<boolean> {
return editors.applyWorkspaceEdit(edit, metadata);
},
registerTextDocumentContentProvider(scheme: string, provider: theia.TextDocumentContentProvider): theia.Disposable {
return workspaceExt.registerTextDocumentContentProvider(scheme, provider);
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-ext/src/plugin/text-editors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ export class TextEditorsExtImpl implements TextEditorsExt {
return new TextEditorDecorationType(this.proxy, options);
}

applyWorkspaceEdit(edit: theia.WorkspaceEdit): Promise<boolean> {
applyWorkspaceEdit(edit: theia.WorkspaceEdit, metadata?: theia.WorkspaceEditMetadata): Promise<boolean> {
const dto = Converters.fromWorkspaceEdit(edit, this.editorsAndDocuments);
return this.proxy.$tryApplyWorkspaceEdit(dto);
return this.proxy.$tryApplyWorkspaceEdit(dto, metadata);
}

saveAll(includeUntitled?: boolean): PromiseLike<boolean> {
Expand Down
13 changes: 12 additions & 1 deletion packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7205,9 +7205,10 @@ export module '@theia/plugin' {
* not be attempted, when a single edit fails.
*
* @param edit A workspace edit.
* @param metadata Optional {@link WorkspaceEditMetadata metadata} for the edit.
* @return A thenable that resolves when the edit could be applied.
*/
export function applyEdit(edit: WorkspaceEdit): Thenable<boolean>;
export function applyEdit(edit: WorkspaceEdit, metadata?: WorkspaceEditMetadata): Thenable<boolean>;

/**
* Register a filesystem provider for a given scheme, e.g. `ftp`.
Expand Down Expand Up @@ -9749,6 +9750,16 @@ export module '@theia/plugin' {
iconPath?: Uri | { light: Uri; dark: Uri } | ThemeIcon;
}

/**
* Additional data about a workspace edit.
*/
export interface WorkspaceEditMetadata {
/**
* Signal to the editor that this edit is a refactoring.
*/
isRefactoring?: boolean;
}

/**
* A workspace edit is a collection of textual and files changes for
* multiple resources and documents.
Expand Down