万字详文:微软 VSCode IDE 源码分析揭秘( 六 )


ipcMain
server.on('error', e);
server.listen(hook, () => {
server.removeListener('error', e);
c(new Server(server));
});
});
}
创建信道src/vs/code/electron-main/app.ts

  • mainIpcServer * launchChannel
  • electronIpcServer
  • _ updateChannel
  • _ issueChannel
  • _ workspacesChannel
  • _ windowsChannel
  • _ menubarChannel
  • _ urlChannel
  • _ storageChannel
  • _ logLevelChannel
private openFirstWindow(accessor: ServicesAccessor, electronIpcServer: ElectronIPCServer, sharedProcessClient: Promise): ICodeWindow[] {
// Register more Main IPC services
const launchService = accessor.get(ILaunchService);
const launchChannel = new LaunchChannel(launchService);
this.mainIpcServer.registerChannel('launch', launchChannel);
// Register more Electron IPC services
const updateService = accessor.get(IUpdateService);
const updateChannel = new UpdateChannel(updateService);
electronIpcServer.registerChannel('update', updateChannel);
const issueService = accessor.get(IIssueService);
const issueChannel = new IssueChannel(issueService);
electronIpcServer.registerChannel('issue', issueChannel);
const workspacesService = accessor.get(IWorkspacesMainService);
const workspacesChannel = new WorkspacesChannel(workspacesService);
electronIpcServer.registerChannel('workspaces', workspacesChannel);
const windowsService = accessor.get(IWindowsService);
const windowsChannel = new WindowsChannel(windowsService);
electronIpcServer.registerChannel('windows', windowsChannel);
sharedProcessClient.then(client => client.registerChannel('windows', windowsChannel));
const menubarService = accessor.get(IMenubarService);
const menubarChannel = new MenubarChannel(menubarService);
electronIpcServer.registerChannel('menubar', menubarChannel);
const urlService = accessor.get(IURLService);
const urlChannel = new URLServiceChannel(urlService);
electronIpcServer.registerChannel('url', urlChannel);
const storageMainService = accessor.get(IStorageMainService);
const storageChannel = this._register(new GlobalStorageDatabaseChannel(this.logService, storageMainService));
electronIpcServer.registerChannel('storage', storageChannel);
// Log level management
const logLevelChannel = new LogLevelSetterChannel(accessor.get(ILogService));
electronIpcServer.registerChannel('loglevel', logLevelChannel);
sharedProcessClient.then(client => client.registerChannel('loglevel', logLevelChannel));
...
// default: read paths from cli
return windowsMainService.open({
context,
cli: args,
forceNewWindow: args['new-window'] || (!hasCliArgs
}
每一个信道 , 内部实现两个方法 listen 和 call
例如:src/vs/platform/localizations/node/localizationsIpc.ts
构造函数绑定事件
export class LocalizationsChannel implements IServerChannel {
onDidLanguagesChange: Event;
constructor(private service: ILocalizationsService) {
this.onDidLanguagesChange = Event.buffer(service.onDidLanguagesChange, true);
}
listen(_: unknown, event: string): Event {
switch (event) {
case 'onDidLanguagesChange': return this.onDidLanguagesChange;
}
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, arg?: any): Promise {
switch (command) {
case 'getLanguageIds': return this.service.getLanguageIds(arg);
}
throw new Error(`Call not found: ${command}`);
}
}
7.主要窗口workbench.ts 中 startup 里面 Workbench 负责创建主界面src/vs/workbench/browser/workbench.ts
startup(): IInstantiationService {
try {
...
instantiationService.invokeFunction(async accessor => {
// 渲染主工作界面
this.renderWorkbench(instantiationService, accessor.get(INotificationService) as NotificationService, storageService, configurationService);
// 界面布局
this.createWorkbenchLayout(instantiationService);
// Layout
this.layout();
// Restore
try {
await this.restoreWorkbench(accessor.get(IEditorService), accessor.get(IEditorGroupsService), accessor.get(IViewletService), accessor.get(IPanelService), accessor.get(ILogService), lifecycleService);
} catch (error) {
onUnexpectedError(error);
}
});
return instantiationService;
} catch (error) {
onUnexpectedError(error);
throw error; // rethrow because this is a critical issue we cannot handle properly here
}
}
渲染主工作台 , 渲染完之后加入到 container 中 , container 加入到 parent, parent 就是 body 了 。
this.parent.appendChild(this.container);
private renderWorkbench(instantiationService: IInstantiationService, notificationService: NotificationService, storageService: IStorageService, configurationService: IConfigurationService): void {