VSCode
在 1.88
的更新日志中宣布了 Restart extensions
的功能:
在本地 VSCode
中,现在不需要 Reload Window
就可以重启插件了。这不禁让我好奇,他们到底做了些什么?
ToC
找找
让我们先用关键词 Reload Extensions
来找一找:
1608 this.enabled = true;1609 this.class = ExtensionRuntimeStateAction.EnabledClass;1610 this.tooltip = runtimeState.reason;1611 this.label = runtimeState.action === ExtensionRuntimeActionType.ReloadWindow ? localize('reload window', 'Reload Window')1612 : runtimeState.action === ExtensionRuntimeActionType.RestartExtensions ? localize('restart extensions', 'Restart Extensions')1613 : runtimeState.action === ExtensionRuntimeActionType.QuitAndInstall ? localize('restart product', 'Restart to Update')1614 : runtimeState.action === ExtensionRuntimeActionType.ApplyUpdate || runtimeState.action === ExtensionRuntimeActionType.DownloadUpdate ? localize('update product', 'Update {0}', this.productService.nameShort) : '';1615 }
找到了 runtimeState.action
。它是怎么定义的呢?
42export const enum ExtensionRuntimeActionType {43 ReloadWindow = "reloadWindow",44 RestartExtensions = "restartExtensions",45 DownloadUpdate = "downloadUpdate",46 ApplyUpdate = "applyUpdate",47 QuitAndInstall = "quitAndInstall",48}
看来是加了个 ExtensionRuntimeActionType.RestartExtensions
。继续追引用:
1617 override async run(): Promise<any> {21 collapsed lines
1618 const runtimeState = this.extension?.runtimeState;1619 if (!runtimeState?.action) {1620 return;1621 }1622
1623 type ExtensionRuntimeStateActionClassification = {1624 owner: 'sandy081';1625 comment: 'Extension runtime state action event';1626 action: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Executed action' };1627 };1628 type ExtensionRuntimeStateActionEvent = {1629 action: string;1630 };1631 this.telemetryService.publicLog2<ExtensionRuntimeStateActionEvent, ExtensionRuntimeStateActionClassification>('extensions:runtimestate:action', {1632 action: runtimeState.action1633 });1634
1635 if (runtimeState?.action === ExtensionRuntimeActionType.ReloadWindow) {1636 return this.hostService.reload();1637 }1638
1639 else if (runtimeState?.action === ExtensionRuntimeActionType.RestartExtensions) {1640 return this.extensionsWorkbenchService.updateRunningExtensions();1641 }13 collapsed lines
1642
1643 else if (runtimeState?.action === ExtensionRuntimeActionType.DownloadUpdate) {1644 return this.updateService.downloadUpdate();1645 }1646
1647 else if (runtimeState?.action === ExtensionRuntimeActionType.ApplyUpdate) {1648 return this.updateService.applyUpdate();1649 }1650
1651 else if (runtimeState?.action === ExtensionRuntimeActionType.QuitAndInstall) {1652 return this.updateService.quitAndInstall();1653 }1654
1655 }
看来核心逻辑都在 updateRunningExtensions
里了。
看看
看看 updateRunningExtensions
:
1235 async updateRunningExtensions(): Promise<void> {1236 const toAdd: ILocalExtension[] = [];1237 const toRemove: string[] = [];1238
1239 const extensionsToCheck = [...this.local];1240
1241 const notExistingRunningExtensions = this.extensionService.extensions.filter(e => !this.local.some(local => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, local.identifier)));1242 if (notExistingRunningExtensions.length) {1243 const extensions = await this.getExtensions(notExistingRunningExtensions.map(e => ({ id: e.identifier.value })), CancellationToken.None);1244 extensionsToCheck.push(...extensions);1245 }1246
1247 for (const extension of extensionsToCheck) {1248 const runtimeState = extension.runtimeState;1249 if (!runtimeState || runtimeState.action !== ExtensionRuntimeActionType.RestartExtensions) {1250 continue;1251 }1252 if (extension.state === ExtensionState.Uninstalled) {1253 toRemove.push(extension.identifier.id);1254 continue;1255 }1256 if (!extension.local) {1257 continue;1258 }1259 const isEnabled = this.extensionEnablementService.isEnabled(extension.local);1260 if (isEnabled) {1261 const runningExtension = this.extensionService.extensions.find(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, extension.identifier));1262 if (runningExtension) {1263 toRemove.push(runningExtension.identifier.value);1264 }1265 toAdd.push(extension.local);1266 } else {1267 toRemove.push(extension.identifier.id);1268 }1269 }1270 if (toAdd.length || toRemove.length) {1271 if (await this.extensionService.stopExtensionHosts(nls.localize('restart', "Enable or Disable extensions"))) {1272 await this.extensionService.startExtensionHosts({ toAdd, toRemove });1273 }1274 }1275 }
还以为会有什么魔法,结果居然是先 Stop
再 Start
??
这里 startExtensionHosts()
的签名相比于之前的版本增加了 toAdd
和 toRemove
两个参数,传到内部之后是直接调用了 _handleDeltaExtensions
:
1 public async startExtensionHosts(updates?: { toAdd: IExtension[]; toRemove: string[] }): Promise<void> {2 this._doStopExtensionHosts();3
4 if (updates) {5 await this._handleDeltaExtensions(new DeltaExtensionsQueueItem(updates.toAdd, updates.toRemove));6 }7
8 const lock = await this._registry.acquireLock('startExtensionHosts');9 try {10 this._startExtensionHostsIfNecessary(false, Array.from(this._allRequestedActivateEvents.keys()));11
12 const localProcessExtensionHosts = this._getExtensionHostManagers(ExtensionHostKind.LocalProcess);13 await Promise.all(localProcessExtensionHosts.map(extHost => extHost.ready()));14 } finally {15 lock.dispose();16 }17 }
没意思,还以为是做了什么好东西,这样实现居然还不支持 Remote
,软软没救了,散了散了)