@opensumi/ide-workspace-edit 2.21.5-rc-1669016550.0 → 2.21.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -13
- package/src/browser/bulk-edit.service.ts +0 -145
- package/src/browser/index.ts +0 -126
- package/src/browser/refactor-preview.service.tsx +0 -151
- package/src/browser/refactor-preview.tsx +0 -194
- package/src/browser/refactor_preview.module.less +0 -49
- package/src/browser/utils.ts +0 -16
- package/src/browser/workspace-edit.service.ts +0 -354
- package/src/browser/workspace-file.service.ts +0 -206
- package/src/common/index.ts +0 -151
- package/src/index.ts +0 -2
package/package.json
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensumi/ide-workspace-edit",
|
|
3
|
-
"version": "2.21.5
|
|
3
|
+
"version": "2.21.5",
|
|
4
4
|
"files": [
|
|
5
|
-
"lib"
|
|
6
|
-
"src"
|
|
5
|
+
"lib"
|
|
7
6
|
],
|
|
8
7
|
"license": "MIT",
|
|
9
8
|
"main": "lib/index.js",
|
|
10
9
|
"typings": "lib/index.d.ts",
|
|
11
10
|
"scripts": {
|
|
12
|
-
"prepublishOnly": "
|
|
11
|
+
"prepublishOnly": "npm run build",
|
|
13
12
|
"build": "tsc --build ../../configs/ts/references/tsconfig.workspace-edit.json"
|
|
14
13
|
},
|
|
15
14
|
"repository": {
|
|
@@ -17,17 +16,17 @@
|
|
|
17
16
|
"url": "git@github.com:opensumi/core.git"
|
|
18
17
|
},
|
|
19
18
|
"dependencies": {
|
|
20
|
-
"@opensumi/ide-core-common": "2.21.5
|
|
19
|
+
"@opensumi/ide-core-common": "2.21.5"
|
|
21
20
|
},
|
|
22
21
|
"devDependencies": {
|
|
23
|
-
"@opensumi/ide-components": "2.21.5
|
|
24
|
-
"@opensumi/ide-core-browser": "2.21.5
|
|
22
|
+
"@opensumi/ide-components": "2.21.5",
|
|
23
|
+
"@opensumi/ide-core-browser": "2.21.5",
|
|
25
24
|
"@opensumi/ide-dev-tool": "^1.3.1",
|
|
26
|
-
"@opensumi/ide-editor": "2.21.5
|
|
27
|
-
"@opensumi/ide-file-service": "2.21.5
|
|
28
|
-
"@opensumi/ide-main-layout": "2.21.5
|
|
29
|
-
"@opensumi/ide-monaco": "2.21.5
|
|
30
|
-
"@opensumi/ide-overlay": "2.21.5
|
|
25
|
+
"@opensumi/ide-editor": "2.21.5",
|
|
26
|
+
"@opensumi/ide-file-service": "2.21.5",
|
|
27
|
+
"@opensumi/ide-main-layout": "2.21.5",
|
|
28
|
+
"@opensumi/ide-monaco": "2.21.5",
|
|
29
|
+
"@opensumi/ide-overlay": "2.21.5"
|
|
31
30
|
},
|
|
32
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "343a6a2981759121bc3b6e62b61fb2f429e5f637"
|
|
33
32
|
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { Injectable, Autowired } from '@opensumi/di';
|
|
2
|
-
import { URI, ILogger, revive } from '@opensumi/ide-core-common';
|
|
3
|
-
import { UriComponents } from '@opensumi/ide-editor';
|
|
4
|
-
import {
|
|
5
|
-
ResourceEdit,
|
|
6
|
-
ResourceFileEdit,
|
|
7
|
-
ResourceTextEdit,
|
|
8
|
-
} from '@opensumi/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService';
|
|
9
|
-
import type {
|
|
10
|
-
IBulkEditPreviewHandler,
|
|
11
|
-
IBulkEditResult,
|
|
12
|
-
IBulkEditService,
|
|
13
|
-
IBulkEditOptions,
|
|
14
|
-
} from '@opensumi/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService';
|
|
15
|
-
import { WorkspaceEdit } from '@opensumi/monaco-editor-core/esm/vs/editor/common/languages';
|
|
16
|
-
import * as monaco from '@opensumi/monaco-editor-core/esm/vs/editor/editor.api';
|
|
17
|
-
|
|
18
|
-
import { IWorkspaceEdit, IWorkspaceEditService, IResourceTextEdit, IResourceFileEdit } from '../common';
|
|
19
|
-
|
|
20
|
-
import { isResourceFileEdit, isResourceTextEdit } from './utils';
|
|
21
|
-
|
|
22
|
-
function reviveWorkspaceEditDto2(data: ResourceEdit[] | WorkspaceEdit | undefined): ResourceEdit[] {
|
|
23
|
-
if (!data) {
|
|
24
|
-
return [];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const edits = Array.isArray(data) ? data : data.edits;
|
|
28
|
-
const result: ResourceEdit[] = [];
|
|
29
|
-
|
|
30
|
-
for (const edit of revive(edits)) {
|
|
31
|
-
if (isResourceFileEdit(edit)) {
|
|
32
|
-
result.push(new ResourceFileEdit(edit.oldResource, edit.newResource, edit.options, edit.metadata));
|
|
33
|
-
} else if (isResourceTextEdit(edit)) {
|
|
34
|
-
result.push(new ResourceTextEdit(edit.resource, edit.textEdit, edit.versionId, edit.metadata));
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
@Injectable()
|
|
41
|
-
export class MonacoBulkEditService implements IBulkEditService {
|
|
42
|
-
_serviceBrand: undefined;
|
|
43
|
-
|
|
44
|
-
@Autowired(IWorkspaceEditService)
|
|
45
|
-
workspaceEditService: IWorkspaceEditService;
|
|
46
|
-
|
|
47
|
-
@Autowired(ILogger)
|
|
48
|
-
private readonly logger: ILogger;
|
|
49
|
-
|
|
50
|
-
private _previewHandler?: IBulkEditPreviewHandler;
|
|
51
|
-
|
|
52
|
-
protected getAriaSummary(totalEdits: number, totalFiles: number): string {
|
|
53
|
-
if (totalEdits === 0) {
|
|
54
|
-
return 'Made no edits';
|
|
55
|
-
}
|
|
56
|
-
if (totalEdits > 1 && totalFiles > 1) {
|
|
57
|
-
return `Made ${totalEdits} text edits in ${totalFiles} files`;
|
|
58
|
-
}
|
|
59
|
-
return `Made ${totalEdits} text edits in one file`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async apply(
|
|
63
|
-
resourceEdits: ResourceEdit[] | WorkspaceEdit,
|
|
64
|
-
options?: IBulkEditOptions,
|
|
65
|
-
): Promise<IBulkEditResult & { success: boolean }> {
|
|
66
|
-
let edits = reviveWorkspaceEditDto2(resourceEdits);
|
|
67
|
-
|
|
68
|
-
if (options?.showPreview && this._previewHandler) {
|
|
69
|
-
try {
|
|
70
|
-
edits = await this._previewHandler(edits, options);
|
|
71
|
-
} catch (err) {
|
|
72
|
-
this.logger.error(`Handle refactor preview error: \n ${err.message || err}`);
|
|
73
|
-
return { ariaSummary: err.message, success: false };
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
const { workspaceEdit, totalEdits, totalFiles } = this.convertWorkspaceEdit(edits);
|
|
79
|
-
await this.workspaceEditService.apply(workspaceEdit);
|
|
80
|
-
return {
|
|
81
|
-
ariaSummary: this.getAriaSummary(totalEdits, totalFiles),
|
|
82
|
-
success: true,
|
|
83
|
-
};
|
|
84
|
-
} catch (err) {
|
|
85
|
-
const errMsg = `Error applying workspace edits: ${err.toString()}`;
|
|
86
|
-
this.logger.error(errMsg);
|
|
87
|
-
return { ariaSummary: errMsg, success: false };
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
hasPreviewHandler(): boolean {
|
|
92
|
-
return Boolean(this._previewHandler);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
setPreviewHandler(handler: IBulkEditPreviewHandler): monaco.IDisposable {
|
|
96
|
-
this._previewHandler = handler;
|
|
97
|
-
|
|
98
|
-
const disposePreviewHandler = () => {
|
|
99
|
-
if (this._previewHandler === handler) {
|
|
100
|
-
this._previewHandler = undefined;
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
dispose(): void {
|
|
106
|
-
disposePreviewHandler();
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private convertWorkspaceEdit(edit: ResourceEdit[]): {
|
|
112
|
-
workspaceEdit: IWorkspaceEdit;
|
|
113
|
-
totalEdits: number;
|
|
114
|
-
totalFiles: number;
|
|
115
|
-
} {
|
|
116
|
-
const workspaceEdit: IWorkspaceEdit = { edits: [] };
|
|
117
|
-
let totalEdits = 0;
|
|
118
|
-
let totalFiles = 0;
|
|
119
|
-
for (const resourceEdit of edit) {
|
|
120
|
-
if ((resourceEdit as IResourceTextEdit).resource) {
|
|
121
|
-
const resourceTextEdit = resourceEdit as IResourceTextEdit;
|
|
122
|
-
const tmp: IResourceTextEdit = {
|
|
123
|
-
resource: URI.from(resourceTextEdit.resource as unknown as UriComponents),
|
|
124
|
-
textEdit: resourceTextEdit.textEdit,
|
|
125
|
-
options: {
|
|
126
|
-
dirtyIfInEditor: true,
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
workspaceEdit.edits.push(tmp);
|
|
130
|
-
totalEdits += 1;
|
|
131
|
-
} else {
|
|
132
|
-
const resourceFileEdit = resourceEdit as ResourceFileEdit;
|
|
133
|
-
const { oldResource, newResource, options = {} } = resourceFileEdit;
|
|
134
|
-
const tmp: IResourceFileEdit = {
|
|
135
|
-
oldResource: oldResource ? URI.from(oldResource as UriComponents) : undefined,
|
|
136
|
-
newResource: newResource ? URI.from(newResource as UriComponents) : undefined,
|
|
137
|
-
options,
|
|
138
|
-
};
|
|
139
|
-
workspaceEdit.edits.push(tmp);
|
|
140
|
-
totalFiles += 1;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return { workspaceEdit, totalEdits, totalFiles };
|
|
144
|
-
}
|
|
145
|
-
}
|
package/src/browser/index.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { Provider, Injectable, Autowired } from '@opensumi/di';
|
|
2
|
-
import {
|
|
3
|
-
BrowserModule,
|
|
4
|
-
Domain,
|
|
5
|
-
MonacoContribution,
|
|
6
|
-
ServiceNames,
|
|
7
|
-
ILogger,
|
|
8
|
-
TabBarToolbarContribution,
|
|
9
|
-
ToolbarRegistry,
|
|
10
|
-
localize,
|
|
11
|
-
CommandContribution,
|
|
12
|
-
getIcon,
|
|
13
|
-
MonacoOverrideServiceRegistry,
|
|
14
|
-
} from '@opensumi/ide-core-browser';
|
|
15
|
-
import { CommandRegistry } from '@opensumi/ide-core-common';
|
|
16
|
-
import type {
|
|
17
|
-
IBulkEditOptions,
|
|
18
|
-
ResourceEdit,
|
|
19
|
-
} from '@opensumi/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService';
|
|
20
|
-
|
|
21
|
-
import { IBulkEditServiceShape, IWorkspaceEditService, IWorkspaceFileService } from '../common';
|
|
22
|
-
|
|
23
|
-
import { MonacoBulkEditService } from './bulk-edit.service';
|
|
24
|
-
import { IRefactorPreviewService, RefactorPreviewServiceImpl, PreviewViewId } from './refactor-preview.service';
|
|
25
|
-
import { WorkspaceEditServiceImpl } from './workspace-edit.service';
|
|
26
|
-
import { WorkspaceFileService } from './workspace-file.service';
|
|
27
|
-
|
|
28
|
-
const ClearEditsId = 'refactor-preview.clear.edits';
|
|
29
|
-
const ApplyEditsId = 'refactor-preview.apply.edits';
|
|
30
|
-
|
|
31
|
-
@Injectable()
|
|
32
|
-
export class WorkspaceEditModule extends BrowserModule {
|
|
33
|
-
providers: Provider[] = [
|
|
34
|
-
{
|
|
35
|
-
token: IWorkspaceEditService,
|
|
36
|
-
useClass: WorkspaceEditServiceImpl,
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
token: IWorkspaceFileService,
|
|
40
|
-
useClass: WorkspaceFileService,
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
token: IRefactorPreviewService,
|
|
44
|
-
useClass: RefactorPreviewServiceImpl,
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
token: IBulkEditServiceShape,
|
|
48
|
-
useClass: MonacoBulkEditService,
|
|
49
|
-
},
|
|
50
|
-
WorkspaceEditContribution,
|
|
51
|
-
];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
@Domain(MonacoContribution, TabBarToolbarContribution, CommandContribution)
|
|
55
|
-
export class WorkspaceEditContribution implements MonacoContribution, TabBarToolbarContribution, CommandContribution {
|
|
56
|
-
@Autowired(IBulkEditServiceShape)
|
|
57
|
-
protected readonly bulkEditService: IBulkEditServiceShape;
|
|
58
|
-
|
|
59
|
-
@Autowired(ILogger)
|
|
60
|
-
protected readonly logger: ILogger;
|
|
61
|
-
|
|
62
|
-
@Autowired(IRefactorPreviewService)
|
|
63
|
-
protected readonly refactorPreviewService: IRefactorPreviewService;
|
|
64
|
-
|
|
65
|
-
private async previewEdit(edits: ResourceEdit[], options?: IBulkEditOptions): Promise<ResourceEdit[]> {
|
|
66
|
-
try {
|
|
67
|
-
const filteredEdits = await this.refactorPreviewService.previewEdits(edits);
|
|
68
|
-
return filteredEdits;
|
|
69
|
-
} catch (err) {
|
|
70
|
-
if (!err) {
|
|
71
|
-
// Canceled
|
|
72
|
-
} else {
|
|
73
|
-
this.logger.error(`Preview textEdit error: \n ${err.message}`);
|
|
74
|
-
}
|
|
75
|
-
return edits;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
registerOverrideService(registry: MonacoOverrideServiceRegistry) {
|
|
80
|
-
// Monaco BulkEditService
|
|
81
|
-
registry.registerOverrideService(ServiceNames.BULK_EDIT_SERVICE, this.bulkEditService);
|
|
82
|
-
this.bulkEditService.setPreviewHandler(this.previewEdit.bind(this));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
registerToolbarItems(registry: ToolbarRegistry) {
|
|
86
|
-
registry.registerItem({
|
|
87
|
-
id: ClearEditsId,
|
|
88
|
-
viewId: PreviewViewId,
|
|
89
|
-
command: ClearEditsId,
|
|
90
|
-
tooltip: localize('refactor-preview.title.clear'),
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
registry.registerItem({
|
|
94
|
-
id: ApplyEditsId,
|
|
95
|
-
viewId: PreviewViewId,
|
|
96
|
-
command: ApplyEditsId,
|
|
97
|
-
tooltip: localize('refactor-preview.title.apply'),
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
registerCommands(registry: CommandRegistry) {
|
|
102
|
-
registry.registerCommand(
|
|
103
|
-
{
|
|
104
|
-
id: ClearEditsId,
|
|
105
|
-
iconClass: getIcon('clear'),
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
execute: () => {
|
|
109
|
-
this.refactorPreviewService.clearAllEdits();
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
registry.registerCommand(
|
|
115
|
-
{
|
|
116
|
-
id: ApplyEditsId,
|
|
117
|
-
iconClass: getIcon('check'),
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
execute: () => {
|
|
121
|
-
this.refactorPreviewService.applyEdits();
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { observable, action } from 'mobx';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
import { Injector, Injectable, Autowired, INJECTOR_TOKEN } from '@opensumi/di';
|
|
5
|
-
import { Deferred, localize, MessageType } from '@opensumi/ide-core-common';
|
|
6
|
-
import { IMainLayoutService } from '@opensumi/ide-main-layout';
|
|
7
|
-
import { IDialogService } from '@opensumi/ide-overlay';
|
|
8
|
-
import { ResourceEdit } from '@opensumi/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService';
|
|
9
|
-
import type {
|
|
10
|
-
IWorkspaceFileEdit,
|
|
11
|
-
IWorkspaceTextEdit,
|
|
12
|
-
} from '@opensumi/monaco-editor-core/esm/vs/editor/common/languages';
|
|
13
|
-
|
|
14
|
-
import { RefactorPreview } from './refactor-preview';
|
|
15
|
-
|
|
16
|
-
export const PreviewViewId = 'RefactorPreview';
|
|
17
|
-
|
|
18
|
-
export interface IRefactorPreviewService {
|
|
19
|
-
edits: Array<IWorkspaceTextEdit | IWorkspaceFileEdit>;
|
|
20
|
-
selectedFileOrTextEdits: Set<IWorkspaceTextEdit | IWorkspaceFileEdit>;
|
|
21
|
-
|
|
22
|
-
previewEdits(edit: ResourceEdit[]): Promise<ResourceEdit[]>;
|
|
23
|
-
|
|
24
|
-
filterEdit(edit: IWorkspaceTextEdit | IWorkspaceFileEdit, checked: boolean): void;
|
|
25
|
-
|
|
26
|
-
applyEdits(): void;
|
|
27
|
-
|
|
28
|
-
clearAllEdits(): void;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const IRefactorPreviewService = Symbol('IRefactorPreviewService');
|
|
32
|
-
|
|
33
|
-
@Injectable()
|
|
34
|
-
export class RefactorPreviewServiceImpl implements IRefactorPreviewService {
|
|
35
|
-
@observable.shallow
|
|
36
|
-
public edits: Array<IWorkspaceTextEdit | IWorkspaceFileEdit> = [];
|
|
37
|
-
|
|
38
|
-
public selectedFileOrTextEdits = observable.set<IWorkspaceTextEdit | IWorkspaceFileEdit>([], { deep: false });
|
|
39
|
-
|
|
40
|
-
@Autowired(IMainLayoutService)
|
|
41
|
-
protected readonly mainLayout: IMainLayoutService;
|
|
42
|
-
|
|
43
|
-
@Autowired(IDialogService)
|
|
44
|
-
protected readonly dialogService: IDialogService;
|
|
45
|
-
|
|
46
|
-
@Autowired(INJECTOR_TOKEN)
|
|
47
|
-
protected readonly injector: Injector;
|
|
48
|
-
|
|
49
|
-
private previewDeferred: Deferred<Array<IWorkspaceTextEdit | IWorkspaceFileEdit>> | null;
|
|
50
|
-
|
|
51
|
-
private clear() {
|
|
52
|
-
this.togglePreviewView(false);
|
|
53
|
-
this.edits = [];
|
|
54
|
-
this.previewDeferred = null;
|
|
55
|
-
this.selectedFileOrTextEdits.clear();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private registerRefactorPreviewView() {
|
|
59
|
-
const handler = this.mainLayout.getTabbarHandler(PreviewViewId);
|
|
60
|
-
if (handler) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
this.mainLayout.collectTabbarComponent(
|
|
65
|
-
[
|
|
66
|
-
{
|
|
67
|
-
component: RefactorPreview,
|
|
68
|
-
id: PreviewViewId,
|
|
69
|
-
},
|
|
70
|
-
],
|
|
71
|
-
{
|
|
72
|
-
title: localize('refactor-preview.title', 'REFACTOR PREVIEW'),
|
|
73
|
-
containerId: PreviewViewId,
|
|
74
|
-
hidden: true,
|
|
75
|
-
},
|
|
76
|
-
'bottom',
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private togglePreviewView(show: boolean) {
|
|
81
|
-
const handler = this.mainLayout.getTabbarHandler(PreviewViewId);
|
|
82
|
-
if (show) {
|
|
83
|
-
handler?.show();
|
|
84
|
-
handler?.activate();
|
|
85
|
-
} else {
|
|
86
|
-
handler?.hide();
|
|
87
|
-
handler?.deactivate();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async previewEdits(edits: ResourceEdit[]): Promise<ResourceEdit[]> {
|
|
92
|
-
this.registerRefactorPreviewView();
|
|
93
|
-
|
|
94
|
-
if (this.previewDeferred) {
|
|
95
|
-
const continued = await this.dialogService.open(
|
|
96
|
-
<div>
|
|
97
|
-
{localize('refactor-preview.overlay.title')}
|
|
98
|
-
<p>{localize('refactor-preview.overlay.detail')}</p>
|
|
99
|
-
</div>,
|
|
100
|
-
MessageType.Warning,
|
|
101
|
-
[localize('refactor-preview.overlay.cancel'), localize('refactor-preview.overlay.continue')],
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
if (continued === localize('refactor-preview.overlay.cancel')) {
|
|
105
|
-
return [];
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
this.togglePreviewView(true);
|
|
110
|
-
|
|
111
|
-
this.edits = edits;
|
|
112
|
-
// 默认全选
|
|
113
|
-
edits.forEach((edit) => {
|
|
114
|
-
this.selectedFileOrTextEdits.add(edit);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
this.previewDeferred = new Deferred();
|
|
118
|
-
|
|
119
|
-
return this.previewDeferred.promise;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
@action
|
|
123
|
-
filterEdit(edit: IWorkspaceTextEdit | IWorkspaceFileEdit, checked: boolean) {
|
|
124
|
-
if (checked) {
|
|
125
|
-
this.selectedFileOrTextEdits.add(edit);
|
|
126
|
-
} else {
|
|
127
|
-
this.selectedFileOrTextEdits.delete(edit);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
applyEdits(): void {
|
|
132
|
-
if (!this.previewDeferred) {
|
|
133
|
-
// it's can not be happened
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const candidate = this.edits.filter((edit: IWorkspaceTextEdit) => this.selectedFileOrTextEdits.has(edit));
|
|
138
|
-
|
|
139
|
-
this.previewDeferred.resolve(candidate);
|
|
140
|
-
this.clear();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
clearAllEdits(): void {
|
|
144
|
-
if (!this.previewDeferred) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
this.previewDeferred.resolve([]);
|
|
149
|
-
this.clear();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import { observer } from 'mobx-react-lite';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
import { CheckBox } from '@opensumi/ide-components/lib/checkbox';
|
|
5
|
-
import { RecycleList } from '@opensumi/ide-components/lib/recycle-list';
|
|
6
|
-
import { ViewState } from '@opensumi/ide-core-browser/lib/layout';
|
|
7
|
-
import { useInjectable } from '@opensumi/ide-core-browser/lib/react-hooks';
|
|
8
|
-
import { LabelService } from '@opensumi/ide-core-browser/lib/services/label-service';
|
|
9
|
-
import { URI, Uri, path } from '@opensumi/ide-core-common';
|
|
10
|
-
import { localize } from '@opensumi/ide-core-common/lib/localize';
|
|
11
|
-
import { IEditorDocumentModelService } from '@opensumi/ide-editor/lib/browser/doc-model/types';
|
|
12
|
-
import { ITextModel } from '@opensumi/ide-monaco/lib/browser/monaco-api/types';
|
|
13
|
-
import type {
|
|
14
|
-
ResourceFileEdit,
|
|
15
|
-
ResourceTextEdit,
|
|
16
|
-
} from '@opensumi/monaco-editor-core/esm/vs/editor/browser/services/bulkEditService';
|
|
17
|
-
import type { IRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/range';
|
|
18
|
-
import * as monaco from '@opensumi/monaco-editor-core/esm/vs/editor/editor.api';
|
|
19
|
-
|
|
20
|
-
import { IRefactorPreviewService } from './refactor-preview.service';
|
|
21
|
-
import styles from './refactor_preview.module.less';
|
|
22
|
-
import { isResourceFileEdit } from './utils';
|
|
23
|
-
|
|
24
|
-
interface IRefactorNodeProps {
|
|
25
|
-
data: ResourceTextEdit | ResourceFileEdit;
|
|
26
|
-
onClick: (item: ResourceTextEdit | ResourceFileEdit) => void;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface ITextEditNodeProps {
|
|
30
|
-
data: ResourceTextEdit;
|
|
31
|
-
onClick: (item: ResourceTextEdit) => void;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface IFileEditNodeProps {
|
|
35
|
-
data: ResourceFileEdit;
|
|
36
|
-
onClick: (item: ResourceFileEdit) => void;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @param range
|
|
41
|
-
* @param textModel
|
|
42
|
-
* @example
|
|
43
|
-
* ```ts
|
|
44
|
-
* const str = `import path from 'path'`;
|
|
45
|
-
*
|
|
46
|
-
* const {
|
|
47
|
-
* leftPad, // import * as
|
|
48
|
-
* base, // path
|
|
49
|
-
* rightPad, // from 'path';
|
|
50
|
-
* } = splitLeftAndRightPadInTextModel(range\/** path range *\/, model);
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
function splitLeftAndRightPadInTextModel(range: IRange, textModel: ITextModel) {
|
|
54
|
-
const lineContent = textModel.getLineContent(range.startLineNumber);
|
|
55
|
-
const base = textModel.getValueInRange(range);
|
|
56
|
-
|
|
57
|
-
const leftPadRange = new monaco.Range(range.startLineNumber, 0, range.startLineNumber, range.startColumn);
|
|
58
|
-
const rightPadRange = new monaco.Range(
|
|
59
|
-
range.endLineNumber,
|
|
60
|
-
range.startColumn + base.length,
|
|
61
|
-
range.endLineNumber,
|
|
62
|
-
lineContent.length + 1,
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const leftPad = textModel.getValueInRange(leftPadRange);
|
|
66
|
-
const rightPad = textModel.getValueInRange(rightPadRange);
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
leftPad,
|
|
70
|
-
rightPad,
|
|
71
|
-
base,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const ResourceIcon: React.FC<{ uri: Uri }> = (props) => {
|
|
76
|
-
const labelService = useInjectable<LabelService>(LabelService);
|
|
77
|
-
const iconClass = labelService.getIcon(URI.from(props.uri));
|
|
78
|
-
return <span className={`file-icon ${iconClass}`} />;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const TextEditNode = observer<ITextEditNodeProps>(({ data: item }) => {
|
|
82
|
-
const modelService = useInjectable<IEditorDocumentModelService>(IEditorDocumentModelService);
|
|
83
|
-
const refactorPreviewService = useInjectable<IRefactorPreviewService>(IRefactorPreviewService);
|
|
84
|
-
|
|
85
|
-
const renderTextEditDiff = () => {
|
|
86
|
-
const model = modelService.getModelReference(URI.from(item.resource));
|
|
87
|
-
if (!model) {
|
|
88
|
-
return <div className={styles.refactor_preview_node_wrapper}>{item.textEdit.text}</div>;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const textModel = model.instance.getMonacoModel();
|
|
92
|
-
const { leftPad, base, rightPad } = splitLeftAndRightPadInTextModel(item.textEdit.range, textModel);
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<div className={styles.refactor_preview_node_wrapper}>
|
|
96
|
-
{leftPad}
|
|
97
|
-
<span className={styles.refactor_preview_node_base}>{base}</span>
|
|
98
|
-
<span className={styles.refactor_preview_node_new}>{item.textEdit.text}</span>
|
|
99
|
-
{rightPad}
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<div className={styles.resource_node} data-workspace-edit-type='text'>
|
|
106
|
-
<CheckBox
|
|
107
|
-
checked={refactorPreviewService.selectedFileOrTextEdits.has(item)}
|
|
108
|
-
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
109
|
-
refactorPreviewService.filterEdit(item, event.target.checked);
|
|
110
|
-
}}
|
|
111
|
-
/>
|
|
112
|
-
<ResourceIcon uri={item.resource as unknown as Uri /* monaco#Uri */} />
|
|
113
|
-
{renderTextEditDiff()}
|
|
114
|
-
<span className={styles.resource_node_path}>{item.resource.path}</span>
|
|
115
|
-
</div>
|
|
116
|
-
);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
function mapDescForFileEdit(edit: ResourceFileEdit) {
|
|
120
|
-
if (edit.newResource && edit.oldResource) {
|
|
121
|
-
// rename
|
|
122
|
-
return {
|
|
123
|
-
uri: edit.newResource,
|
|
124
|
-
desc: localize('refactor-preview.file.move'),
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
if (edit.newResource && !edit.oldResource) {
|
|
128
|
-
// create
|
|
129
|
-
return {
|
|
130
|
-
uri: edit.newResource,
|
|
131
|
-
desc: localize('refactor-preview.file.create'),
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
if (!edit.newResource && edit.oldResource) {
|
|
135
|
-
return {
|
|
136
|
-
uri: edit.oldResource,
|
|
137
|
-
desc: localize('refactor-preview.file.delete'),
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
return undefined;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const FileEditNode = observer<IFileEditNodeProps>(({ data: item }) => {
|
|
144
|
-
const refactorPreviewService = useInjectable<IRefactorPreviewService>(IRefactorPreviewService);
|
|
145
|
-
|
|
146
|
-
const editDesc = mapDescForFileEdit(item);
|
|
147
|
-
if (editDesc === undefined) {
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const filename = path.basename(editDesc.uri.fsPath);
|
|
152
|
-
const dirname = path.dirname(editDesc.uri.fsPath);
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<div className={styles.resource_node} data-workspace-edit-type='file'>
|
|
156
|
-
<CheckBox
|
|
157
|
-
checked={refactorPreviewService.selectedFileOrTextEdits.has(item)}
|
|
158
|
-
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
159
|
-
refactorPreviewService.filterEdit(item, event.target.checked);
|
|
160
|
-
}}
|
|
161
|
-
/>
|
|
162
|
-
<ResourceIcon uri={editDesc.uri as unknown as Uri /* monaco#Uri */} />
|
|
163
|
-
<span className={styles.refactor_preview_node_wrapper}>{filename}</span>
|
|
164
|
-
<span className={styles.resource_node_path}>
|
|
165
|
-
{dirname} ({editDesc.desc})
|
|
166
|
-
</span>
|
|
167
|
-
</div>
|
|
168
|
-
);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const RefactorNode = observer<IRefactorNodeProps>(({ data, ...restProps }) => {
|
|
172
|
-
if (isResourceFileEdit(data)) {
|
|
173
|
-
return <FileEditNode data={data} {...restProps} />;
|
|
174
|
-
}
|
|
175
|
-
return <TextEditNode data={data} {...restProps} />;
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
export const RefactorPreview = observer(({ viewState }: React.PropsWithChildren<{ viewState: ViewState }>) => {
|
|
179
|
-
const refactorPreviewService = useInjectable<IRefactorPreviewService>(IRefactorPreviewService);
|
|
180
|
-
|
|
181
|
-
return (
|
|
182
|
-
<div>
|
|
183
|
-
{refactorPreviewService.edits.length > 0 && (
|
|
184
|
-
<RecycleList
|
|
185
|
-
itemHeight={23}
|
|
186
|
-
width={viewState.width}
|
|
187
|
-
height={viewState.height}
|
|
188
|
-
data={refactorPreviewService.edits}
|
|
189
|
-
template={RefactorNode}
|
|
190
|
-
/>
|
|
191
|
-
)}
|
|
192
|
-
</div>
|
|
193
|
-
);
|
|
194
|
-
});
|