Skip to content

Commit 0b22a5e

Browse files
author
guqiankun.gqk
committed
fix: 修复monaco override dispose 问题
1 parent 9ae4c93 commit 0b22a5e

11 files changed

Lines changed: 357 additions & 41 deletions

File tree

packages/core/src/client/index.ts

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from '@opensumi/ide-core-browser';
1111
import { ClientApp as BasicClientApp } from '@opensumi/ide-core-browser/lib/bootstrap/app';
1212

13-
import { BackService, BasicModule } from '@opensumi/ide-core-common';
13+
import { BackService, BasicModule, Disposable } from '@opensumi/ide-core-common';
1414
import { WSChannelHandler } from '@opensumi/ide-connection/lib/browser';
1515

1616
import { FCServiceCenter, ClientPort, initFCService } from '../connection';
@@ -36,8 +36,8 @@ import { LayoutRestoreContributation } from './layout/index.contribution';
3636
import {
3737
MonacoCodeService,
3838
IMonacoCodeService,
39-
codeServiceEditor,
40-
} from './override/codeEditorService';
39+
monacoCodeServiceProxy,
40+
} from './override/monacoOverride/codeEditorService';
4141
import { BreadCrumbServiceImplOverride, IBreadCrumbService } from './override/breadcrumb.service';
4242
import { SearchContribution } from './search/index.contribution';
4343
import {
@@ -51,7 +51,24 @@ import {
5151
} from './override/vscodeContributesService';
5252

5353
import { ExtensionNodeServiceServerPath } from '@opensumi/ide-extension';
54-
export * from './override/codeEditorService';
54+
import {
55+
IMonacoTextModelService,
56+
MonacoTextModelService,
57+
monacoTextModelServiceProxy,
58+
} from './override/monacoOverride/textModelService';
59+
import {
60+
IMonacoBulkEditServiceProxy,
61+
MonacoBulkEditService,
62+
monacoBulkEditServiceProxy,
63+
} from './override/monacoOverride/workspaceEditService';
64+
import { ICommandServiceToken } from '@opensumi/ide-monaco/lib/browser/contrib/command';
65+
import { MonacoCommandService } from '@opensumi/ide-editor/lib/browser/monaco-contrib/command/command.service';
66+
import { IBulkEditServiceShape } from '@opensumi/ide-workspace-edit';
67+
import {
68+
IMonacoCommandServiceProxy,
69+
monacoCommandServiceProxy,
70+
} from './override/monacoOverride/commandService';
71+
export * from './override/monacoOverride/codeEditorService';
5572

5673
export { ExtensionManagerModule as ExtensionClientManagerModule } from './extension-manager';
5774

@@ -80,27 +97,66 @@ export class ClientModule extends BrowserModule {
8097
SearchContribution,
8198
PreferenceSettingContribution,
8299
LayoutRestoreContributation,
100+
101+
/* monaco override*/
83102
{
84103
token: MonacoCodeService,
85-
useValue: codeServiceEditor,
104+
useValue: monacoCodeServiceProxy,
105+
override: true,
86106
},
87107
{
88108
token: IMonacoCodeService,
89109
useClass: MonacoCodeService,
90110
},
111+
// MonacoTextModelService
91112
{
92-
token: IBreadCrumbService,
93-
useClass: BreadCrumbServiceImplOverride,
113+
token: MonacoTextModelService,
114+
useValue: monacoTextModelServiceProxy,
94115
override: true,
95116
},
96117
{
97-
token: MonacoSnippetSuggestProvider,
98-
useClass: MonacoSnippetSuggestProviderOverride,
118+
token: IMonacoTextModelService,
119+
useClass: MonacoTextModelService,
120+
},
121+
// IBulkEditServiceShape
122+
{
123+
token: IBulkEditServiceShape,
124+
useValue: monacoBulkEditServiceProxy,
125+
override: true,
126+
},
127+
{
128+
token: IMonacoBulkEditServiceProxy,
129+
useClass: MonacoBulkEditService,
130+
},
131+
// MonacoCommandService
132+
{
133+
token: ICommandServiceToken,
134+
useValue: monacoCommandServiceProxy,
99135
override: true,
100136
},
137+
{
138+
token: IMonacoCommandServiceProxy,
139+
useClass: MonacoCommandService,
140+
},
141+
// MonacoContextKeyService
101142
{
102143
token: IContextKeyService,
103-
useClass: MonacoContextKeyService,
144+
useValue: monacoCommandServiceProxy,
145+
override: true,
146+
},
147+
{
148+
token: IMonacoCommandServiceProxy,
149+
useClass: MonacoCommandService,
150+
},
151+
/* monaco override */
152+
{
153+
token: IBreadCrumbService,
154+
useClass: BreadCrumbServiceImplOverride,
155+
override: true,
156+
},
157+
{
158+
token: MonacoSnippetSuggestProvider,
159+
useClass: MonacoSnippetSuggestProviderOverride,
104160
override: true,
105161
},
106162
{
@@ -126,15 +182,21 @@ export class ClientApp extends BasicClientApp {
126182

127183
private modules: ModuleConstructor[] = [];
128184

185+
private disposer = new Disposable();
186+
129187
constructor(opts: IAppOpts) {
130188
super(opts);
131189
this.modules = opts.modules;
132190
this.initServer(opts);
133-
this.initCodeServiceEditor();
191+
// monaco override proxy 防止组件卸载后 monaco override 实例被销毁
192+
this.initMonacoProxy();
134193
}
135194

136-
initCodeServiceEditor() {
137-
this.clearInjector = codeServiceEditor.setInjector(this.injector);
195+
initMonacoProxy() {
196+
this.disposer.addDispose(monacoCodeServiceProxy.setInjector(this.injector));
197+
this.disposer.addDispose(monacoTextModelServiceProxy.setInjector(this.injector));
198+
this.disposer.addDispose(monacoBulkEditServiceProxy.setInjector(this.injector));
199+
this.disposer.addDispose(monacoCommandServiceProxy.setInjector(this.injector));
138200
}
139201

140202
private initServer(opts: IAppOpts) {
@@ -190,7 +252,7 @@ export class ClientApp extends BasicClientApp {
190252
}
191253
async dispose() {
192254
super.dispose();
193-
this.clearInjector();
255+
this.disposer.dispose();
194256
}
195257
}
196258

packages/core/src/client/override/monacoContextKeyService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export class MonacoContextKeyService extends BaseContextKeyService implements IC
1515
(window as any)?._alex?.ContextKeyService || new ContextKeyService(this.configurationService);
1616
(window as any)._alex = {};
1717
(window as any)._alex.ContextKeyService = this.contextKeyService;
18+
this.listenToContextChanges();
1819
}
1920

2021
dispose(): void {}

packages/core/src/client/override/codeEditorService.ts renamed to packages/core/src/client/override/monacoOverride/codeEditorService.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const IMonacoCodeService = Symbol('IMonacoCodeService');
1515

1616
export { MonacoCodeService };
1717

18-
class CodeEditorService extends AbstractCodeEditorService {
18+
class MonacoCodeServiceProxy extends AbstractCodeEditorService {
1919
private injector: Injector | null = null;
2020
private uid = 0;
2121

@@ -27,10 +27,12 @@ class CodeEditorService extends AbstractCodeEditorService {
2727
this.injector = injector;
2828
this.uid++;
2929
const currentUId = this.uid;
30-
return () => {
31-
if (currentUId === this.uid) {
32-
this.injector = null;
33-
}
30+
return {
31+
dispose: () => {
32+
if (currentUId === this.uid && this.injector) {
33+
this.injector = null;
34+
}
35+
},
3436
};
3537
}
3638

@@ -43,4 +45,4 @@ class CodeEditorService extends AbstractCodeEditorService {
4345
}
4446
}
4547

46-
export const codeServiceEditor = new CodeEditorService();
48+
export const monacoCodeServiceProxy = new MonacoCodeServiceProxy();
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { MonacoTextModelService } from '@opensumi/ide-editor/lib/browser/doc-model/override';
2+
import { Injector } from '@opensumi/di';
3+
4+
import {
5+
ICommandServiceToken,
6+
IMonacoActionRegistry,
7+
IMonacoCommandsRegistry,
8+
IMonacoCommandService,
9+
ICommandEvent,
10+
ICommandService,
11+
} from '@opensumi/ide-monaco/lib/browser/contrib/command';
12+
import { Event } from '@opensumi/ide-monaco';
13+
14+
export const IMonacoCommandServiceProxy = Symbol('IMonacoCommandServiceProxy');
15+
export { MonacoTextModelService };
16+
17+
class MonacoCommandServiceProxy implements IMonacoCommandService {
18+
_serviceBrand: undefined;
19+
20+
private injector: Injector | null = null;
21+
private uid = 0;
22+
23+
setInjector(injector: Injector) {
24+
this.injector = injector;
25+
this.uid++;
26+
const currentUId = this.uid;
27+
return {
28+
dispose: () => {
29+
if (currentUId === this.uid && this.injector) {
30+
this.injector = null;
31+
}
32+
},
33+
};
34+
}
35+
36+
setDelegate(delegate: ICommandService): void {
37+
return this.injector!.get(IMonacoCommandServiceProxy).setDelegate(delegate);
38+
}
39+
get onWillExecuteCommand(): Event<ICommandEvent> {
40+
return this.injector!.get(IMonacoCommandServiceProxy).onWillExecuteCommand;
41+
}
42+
get onDidExecuteCommand(): Event<ICommandEvent> {
43+
return this.injector!.get(IMonacoCommandServiceProxy).onDidExecuteCommand;
44+
}
45+
executeCommand<T = any>(commandId: string, ...args: any[]): Promise<T | undefined> {
46+
return this.injector!.get(IMonacoCommandServiceProxy).executeCommand(commandId, ...args);
47+
}
48+
}
49+
50+
export const monacoCommandServiceProxy = new MonacoCommandServiceProxy();
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Injector } from '@opensumi/di';
2+
import {
3+
ContextKeyChangeEvent,
4+
Event,
5+
IContextKey,
6+
IScopedContextKeyService,
7+
} from '@opensumi/ide-core-browser';
8+
import { ContextKeyService } from '@opensumi/monaco-editor-core/esm/vs/platform/contextkey/browser/contextKeyService';
9+
import {
10+
ContextKeyValue,
11+
ContextKeyExpr,
12+
IContextKeyService,
13+
IContextKeyServiceTarget,
14+
} from '@opensumi/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey';
15+
export const IScopedContextKeyServiceProxy = Symbol('IScopedContextKeyServiceProxy');
16+
17+
// override 传入的是scope
18+
19+
class ScopedContextKeyServiceProxy implements IScopedContextKeyService {
20+
private injector: Injector | null = null;
21+
private uid = 0;
22+
23+
setInjector(injector: Injector) {
24+
this.injector = injector;
25+
this.uid++;
26+
const currentUId = this.uid;
27+
return {
28+
dispose: () => {
29+
if (currentUId === this.uid && this.injector) {
30+
this.injector = null;
31+
}
32+
},
33+
};
34+
}
35+
36+
attachToDomNode(domNode: HTMLElement): void {
37+
return this.injector!.get(IScopedContextKeyServiceProxy).attachToDomNode(domNode);
38+
}
39+
onDidChangeContext: Event<ContextKeyChangeEvent>;
40+
bufferChangeEvents(callback: Function): void {
41+
return this.injector!.get(IScopedContextKeyServiceProxy).bufferChangeEvents(callback);
42+
}
43+
getValue<T>(key: string): T | undefined {
44+
return this.injector!.get(IScopedContextKeyServiceProxy).getValue(key);
45+
}
46+
createKey<T extends ContextKeyValue = any>(
47+
key: string,
48+
defaultValue: T | undefined
49+
): IContextKey<T> {
50+
return this.injector!.get(IScopedContextKeyServiceProxy).createKey(key, defaultValue);
51+
}
52+
match(
53+
expression: string | ContextKeyExpr | undefined,
54+
context?: HTMLElement | null | undefined
55+
): boolean {
56+
return this.injector!.get(IScopedContextKeyServiceProxy).match(expression, context);
57+
}
58+
getKeysInWhen(when: string | ContextKeyExpr | undefined): string[] {
59+
return this.injector!.get(IScopedContextKeyServiceProxy).getKeysInWhen(when);
60+
}
61+
getContextValue<T>(key: string): T | undefined {
62+
return this.injector!.get(IScopedContextKeyServiceProxy).getContextValue(key);
63+
}
64+
contextKeyService: IContextKeyService;
65+
createScoped(
66+
target?: ContextKeyService | IContextKeyServiceTarget | undefined
67+
): IScopedContextKeyService {
68+
return this.injector!.get(IScopedContextKeyServiceProxy).createScoped(target);
69+
}
70+
parse(when: string | undefined): ContextKeyExpr | undefined {
71+
throw new Error('Method not implemented.');
72+
}
73+
dispose(): void {
74+
throw new Error('Method not implemented.');
75+
}
76+
}
77+
78+
export const monacoTextModelServiceProxy = new ScopedContextKeyServiceProxy();
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import {
2+
ITextModelService,
3+
ITextModelContentProvider,
4+
} from '@opensumi/monaco-editor-core/esm/vs/editor/common/services/resolverService';
5+
import * as monaco from '@opensumi/monaco-editor-core/esm/vs/editor/editor.api';
6+
import { MonacoTextModelService } from '@opensumi/ide-editor/lib/browser/doc-model/override';
7+
import { Injector } from '@opensumi/di';
8+
export const IMonacoTextModelService = Symbol('IMonacoTextModelService');
9+
export { MonacoTextModelService };
10+
11+
class MonacoTextModelServiceProxy implements ITextModelService {
12+
_serviceBrand: undefined;
13+
14+
private injector: Injector | null = null;
15+
private uid = 0;
16+
17+
setInjector(injector: Injector) {
18+
this.injector = injector;
19+
this.uid++;
20+
const currentUId = this.uid;
21+
return {
22+
dispose: () => {
23+
if (currentUId === this.uid && this.injector) {
24+
this.injector = null;
25+
}
26+
},
27+
};
28+
}
29+
30+
canHandleResource(resource: any): boolean {
31+
return this.injector!.get(IMonacoTextModelService).canHandleResource(resource);
32+
}
33+
34+
hasTextModelContentProvider(scheme: string): boolean {
35+
return this.injector!.get(IMonacoTextModelService).hasTextModelContentProvider(scheme);
36+
}
37+
38+
async createModelReference(resource: monaco.Uri) {
39+
return this.injector!.get(IMonacoTextModelService).createModelReference(resource);
40+
}
41+
42+
registerTextModelContentProvider(
43+
scheme: string,
44+
provider: ITextModelContentProvider
45+
): monaco.IDisposable {
46+
return this.injector!.get(IMonacoTextModelService).registerTextModelContentProvider(
47+
scheme,
48+
provider
49+
);
50+
}
51+
}
52+
53+
export const monacoTextModelServiceProxy = new MonacoTextModelServiceProxy();

0 commit comments

Comments
 (0)