UNPKG

@codingame/monaco-vscode-extensions-service-override

Version:

VSCode public API plugged on the monaco editor - extensions service-override

412 lines (409 loc) 21.7 kB
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js'; import { DisposableStore, MutableDisposable, combinedDisposable, Disposable } from 'vscode/vscode/vs/base/common/lifecycle'; import { ExtHostContext, MainContext } from 'vscode/vscode/vs/workbench/api/common/extHost.protocol'; import { extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js'; import { URI } from 'vscode/vscode/vs/base/common/uri'; import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service'; import { TerminalLocation, TerminalExitReason, ProcessPropertyType } from 'vscode/vscode/vs/platform/terminal/common/terminal'; import { TerminalDataBufferer } from 'vscode/vscode/vs/platform/terminal/common/terminalDataBuffering'; import { ITerminalService, ITerminalGroupService, ITerminalEditorService } from 'vscode/vscode/vs/workbench/contrib/terminal/browser/terminal.service'; import { TerminalProcessExtHostProxy } from 'vscode/vscode/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy'; import { IEnvironmentVariableService } from 'vscode/vscode/vs/workbench/contrib/terminal/common/environmentVariable.service'; import { serializeEnvironmentVariableCollection, deserializeEnvironmentVariableCollection, deserializeEnvironmentDescriptionMap } from 'vscode/vscode/vs/platform/terminal/common/environmentVariableShared'; import { ITerminalProfileResolverService, ITerminalProfileService } from 'vscode/vscode/vs/workbench/contrib/terminal/common/terminal.service'; import { IRemoteAgentService } from 'vscode/vscode/vs/workbench/services/remote/common/remoteAgentService.service'; import { OS } from 'vscode/vscode/vs/base/common/platform'; import { Promises } from 'vscode/vscode/vs/base/common/async'; import { ITerminalLinkProviderService } from 'vscode/vscode/vs/workbench/contrib/terminalContrib/links/browser/links.service'; import { TerminalQuickFixType } from 'vscode/vscode/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix'; import { ITerminalQuickFixService } from 'vscode/vscode/vs/workbench/contrib/terminalContrib/quickFix/browser/quickFix.service'; import { TerminalCapability } from 'vscode/vscode/vs/platform/terminal/common/capabilities/capabilities'; let MainThreadTerminalService = class MainThreadTerminalService { constructor(_extHostContext, _terminalService, _terminalLinkProviderService, _terminalQuickFixService, _instantiationService, _environmentVariableService, _logService, _terminalProfileResolverService, remoteAgentService, _terminalGroupService, _terminalEditorService, _terminalProfileService) { this._extHostContext = _extHostContext; this._terminalService = _terminalService; this._terminalLinkProviderService = _terminalLinkProviderService; this._terminalQuickFixService = _terminalQuickFixService; this._instantiationService = _instantiationService; this._environmentVariableService = _environmentVariableService; this._logService = _logService; this._terminalProfileResolverService = _terminalProfileResolverService; this._terminalGroupService = _terminalGroupService; this._terminalEditorService = _terminalEditorService; this._terminalProfileService = _terminalProfileService; this._store = ( new DisposableStore()); this._extHostTerminals = ( new Map()); this._terminalProcessProxies = ( new Map()); this._profileProviders = ( new Map()); this._quickFixProviders = ( new Map()); this._dataEventTracker = ( new MutableDisposable()); this._sendCommandEventListener = ( new MutableDisposable()); this._linkProvider = this._store.add(( new MutableDisposable())); this._os = OS; this._proxy = ( _extHostContext.getProxy(ExtHostContext.ExtHostTerminalService)); this._store.add(_terminalService.onDidCreateInstance((instance) => { this._onTerminalOpened(instance); this._onInstanceDimensionsChanged(instance); })); this._store.add(_terminalService.onDidDisposeInstance(instance => this._onTerminalDisposed(instance))); this._store.add(_terminalService.onAnyInstanceProcessIdReady(instance => this._onTerminalProcessIdReady(instance))); this._store.add(_terminalService.onDidChangeInstanceDimensions(instance => this._onInstanceDimensionsChanged(instance))); this._store.add(_terminalService.onAnyInstanceMaximumDimensionsChange(instance => this._onInstanceMaximumDimensionsChanged(instance))); this._store.add(_terminalService.onDidRequestStartExtensionTerminal(e => this._onRequestStartExtensionTerminal(e))); this._store.add(_terminalService.onDidChangeActiveInstance(instance => this._onActiveTerminalChanged(instance ? instance.instanceId : null))); this._store.add(_terminalService.onAnyInstanceTitleChange(instance => instance && this._onTitleChanged(instance.instanceId, instance.title))); this._store.add(_terminalService.onAnyInstanceDataInput(instance => this._proxy.$acceptTerminalInteraction(instance.instanceId))); this._store.add(_terminalService.onAnyInstanceSelectionChange(instance => this._proxy.$acceptTerminalSelection(instance.instanceId, instance.selection))); for (const instance of this._terminalService.instances) { this._onTerminalOpened(instance); instance.processReady.then(() => this._onTerminalProcessIdReady(instance)); } const activeInstance = this._terminalService.activeInstance; if (activeInstance) { this._proxy.$acceptActiveTerminalChanged(activeInstance.instanceId); } if (this._environmentVariableService.collections.size > 0) { const collectionAsArray = [...this._environmentVariableService.collections.entries()]; const serializedCollections = ( collectionAsArray.map(e => { return [e[0], serializeEnvironmentVariableCollection(e[1].map)]; })); this._proxy.$initEnvironmentVariableCollections(serializedCollections); } remoteAgentService.getEnvironment().then(async (env) => { this._os = env?.os || OS; this._updateDefaultProfile(); }); this._store.add(this._terminalProfileService.onDidChangeAvailableProfiles(() => this._updateDefaultProfile())); } dispose() { this._store.dispose(); for (const provider of ( this._profileProviders.values())) { provider.dispose(); } for (const provider of ( this._quickFixProviders.values())) { provider.dispose(); } } async _updateDefaultProfile() { const remoteAuthority = this._extHostContext.remoteAuthority ?? undefined; const defaultProfile = this._terminalProfileResolverService.getDefaultProfile({ remoteAuthority, os: this._os }); const defaultAutomationProfile = this._terminalProfileResolverService.getDefaultProfile({ remoteAuthority, os: this._os, allowAutomationShell: true }); this._proxy.$acceptDefaultProfile(...(await Promise.all([defaultProfile, defaultAutomationProfile]))); } async _getTerminalInstance(id) { if (typeof id === 'string') { return this._extHostTerminals.get(id); } return this._terminalService.getInstanceFromId(id); } async $createTerminal(extHostTerminalId, launchConfig) { const shellLaunchConfig = { name: launchConfig.name, executable: launchConfig.shellPath, args: launchConfig.shellArgs, cwd: typeof launchConfig.cwd === 'string' ? launchConfig.cwd : URI.revive(launchConfig.cwd), icon: launchConfig.icon, color: launchConfig.color, initialText: launchConfig.initialText, waitOnExit: launchConfig.waitOnExit, ignoreConfigurationCwd: true, env: launchConfig.env, strictEnv: launchConfig.strictEnv, hideFromUser: launchConfig.hideFromUser, customPtyImplementation: launchConfig.isExtensionCustomPtyTerminal ? (id, cols, rows) => ( new TerminalProcessExtHostProxy(id, cols, rows, this._terminalService)) : undefined, extHostTerminalId, forceShellIntegration: launchConfig.forceShellIntegration, isFeatureTerminal: launchConfig.isFeatureTerminal, isExtensionOwnedTerminal: launchConfig.isExtensionOwnedTerminal, useShellEnvironment: launchConfig.useShellEnvironment, isTransient: launchConfig.isTransient }; const terminal = Promises.withAsyncBody(async (r) => { const terminal = await this._terminalService.createTerminal({ config: shellLaunchConfig, location: await this._deserializeParentTerminal(launchConfig.location) }); r(terminal); }); this._extHostTerminals.set(extHostTerminalId, terminal); const terminalInstance = await terminal; this._store.add(terminalInstance.onDisposed(() => { this._extHostTerminals.delete(extHostTerminalId); })); } async _deserializeParentTerminal(location) { if (typeof location === 'object' && 'parentTerminal' in location) { const parentTerminal = await this._extHostTerminals.get(( location.parentTerminal.toString())); return parentTerminal ? { parentTerminal } : undefined; } return location; } async $show(id, preserveFocus) { const terminalInstance = await this._getTerminalInstance(id); if (terminalInstance) { this._terminalService.setActiveInstance(terminalInstance); if (terminalInstance.target === TerminalLocation.Editor) { await this._terminalEditorService.revealActiveEditor(preserveFocus); } else { await this._terminalGroupService.showPanel(!preserveFocus); } } } async $hide(id) { const instanceToHide = await this._getTerminalInstance(id); const activeInstance = this._terminalService.activeInstance; if (activeInstance && activeInstance.instanceId === instanceToHide?.instanceId && activeInstance.target !== TerminalLocation.Editor) { this._terminalGroupService.hidePanel(); } } async $dispose(id) { (await this._getTerminalInstance(id))?.dispose(TerminalExitReason.Extension); } async $sendText(id, text, shouldExecute) { const instance = await this._getTerminalInstance(id); await instance?.sendText(text, shouldExecute); } $sendProcessExit(terminalId, exitCode) { this._terminalProcessProxies.get(terminalId)?.emitExit(exitCode); } $startSendingDataEvents() { if (!this._dataEventTracker.value) { this._dataEventTracker.value = this._instantiationService.createInstance(TerminalDataEventTracker, (id, data) => { this._onTerminalData(id, data); }); for (const instance of this._terminalService.instances) { for (const data of instance.initialDataEvents || []) { this._onTerminalData(instance.instanceId, data); } } } } $stopSendingDataEvents() { this._dataEventTracker.clear(); } $startSendingCommandEvents() { if (this._sendCommandEventListener.value) { return; } const multiplexer = this._terminalService.createOnInstanceCapabilityEvent(TerminalCapability.CommandDetection, capability => capability.onCommandFinished); const sub = multiplexer.event(e => { this._onDidExecuteCommand(e.instance.instanceId, { commandLine: e.data.command, cwd: e.data.cwd, exitCode: e.data.exitCode, output: e.data.getOutput() }); }); this._sendCommandEventListener.value = combinedDisposable(multiplexer, sub); } $stopSendingCommandEvents() { this._sendCommandEventListener.clear(); } $startLinkProvider() { this._linkProvider.value = this._terminalLinkProviderService.registerLinkProvider(( new ExtensionTerminalLinkProvider(this._proxy))); } $stopLinkProvider() { this._linkProvider.clear(); } $registerProcessSupport(isSupported) { this._terminalService.registerProcessSupport(isSupported); } $registerProfileProvider(id, extensionIdentifier) { this._profileProviders.set(id, this._terminalProfileService.registerTerminalProfileProvider(extensionIdentifier, id, { createContributedTerminalProfile: async (options) => { return this._proxy.$createContributedProfileTerminal(id, options); } })); } $unregisterProfileProvider(id) { this._profileProviders.get(id)?.dispose(); this._profileProviders.delete(id); } async $registerQuickFixProvider(id, extensionId) { this._quickFixProviders.set(id, this._terminalQuickFixService.registerQuickFixProvider(id, { provideTerminalQuickFixes: async (terminalCommand, lines, options, token) => { if (token.isCancellationRequested) { return; } if (options.outputMatcher?.length && options.outputMatcher.length > 40) { options.outputMatcher.length = 40; this._logService.warn('Cannot exceed output matcher length of 40'); } const commandLineMatch = terminalCommand.command.match(options.commandLineMatcher); if (!commandLineMatch || !lines) { return; } const outputMatcher = options.outputMatcher; let outputMatch; if (outputMatcher) { outputMatch = getOutputMatchForLines(lines, outputMatcher); } if (!outputMatch) { return; } const matchResult = { commandLineMatch, outputMatch, commandLine: terminalCommand.command }; if (matchResult) { const result = await this._proxy.$provideTerminalQuickFixes(id, matchResult, token); if (result && Array.isArray(result)) { return ( result.map(r => parseQuickFix(id, extensionId, r))); } else if (result) { return parseQuickFix(id, extensionId, result); } } return; } })); } $unregisterQuickFixProvider(id) { this._quickFixProviders.get(id)?.dispose(); this._quickFixProviders.delete(id); } _onActiveTerminalChanged(terminalId) { this._proxy.$acceptActiveTerminalChanged(terminalId); } _onTerminalData(terminalId, data) { this._proxy.$acceptTerminalProcessData(terminalId, data); } _onDidExecuteCommand(terminalId, command) { this._proxy.$acceptDidExecuteCommand(terminalId, command); } _onTitleChanged(terminalId, name) { this._proxy.$acceptTerminalTitleChange(terminalId, name); } _onTerminalDisposed(terminalInstance) { this._proxy.$acceptTerminalClosed(terminalInstance.instanceId, terminalInstance.exitCode, terminalInstance.exitReason ?? TerminalExitReason.Unknown); } _onTerminalOpened(terminalInstance) { const extHostTerminalId = terminalInstance.shellLaunchConfig.extHostTerminalId; const shellLaunchConfigDto = { name: terminalInstance.shellLaunchConfig.name, executable: terminalInstance.shellLaunchConfig.executable, args: terminalInstance.shellLaunchConfig.args, cwd: terminalInstance.shellLaunchConfig.cwd, env: terminalInstance.shellLaunchConfig.env, hideFromUser: terminalInstance.shellLaunchConfig.hideFromUser }; this._proxy.$acceptTerminalOpened(terminalInstance.instanceId, extHostTerminalId, terminalInstance.title, shellLaunchConfigDto); } _onTerminalProcessIdReady(terminalInstance) { if (terminalInstance.processId === undefined) { return; } this._proxy.$acceptTerminalProcessId(terminalInstance.instanceId, terminalInstance.processId); } _onInstanceDimensionsChanged(instance) { this._proxy.$acceptTerminalDimensions(instance.instanceId, instance.cols, instance.rows); } _onInstanceMaximumDimensionsChanged(instance) { this._proxy.$acceptTerminalMaximumDimensions(instance.instanceId, instance.maxCols, instance.maxRows); } _onRequestStartExtensionTerminal(request) { const proxy = request.proxy; this._terminalProcessProxies.set(proxy.instanceId, proxy); const initialDimensions = request.cols && request.rows ? { columns: request.cols, rows: request.rows } : undefined; this._proxy.$startExtensionTerminal(proxy.instanceId, initialDimensions).then(request.callback); proxy.onInput(data => this._proxy.$acceptProcessInput(proxy.instanceId, data)); proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(proxy.instanceId, immediate)); proxy.onRequestCwd(() => this._proxy.$acceptProcessRequestCwd(proxy.instanceId)); proxy.onRequestInitialCwd(() => this._proxy.$acceptProcessRequestInitialCwd(proxy.instanceId)); } $sendProcessData(terminalId, data) { this._terminalProcessProxies.get(terminalId)?.emitData(data); } $sendProcessReady(terminalId, pid, cwd, windowsPty) { this._terminalProcessProxies.get(terminalId)?.emitReady(pid, cwd, windowsPty); } $sendProcessProperty(terminalId, property) { if (property.type === ProcessPropertyType.Title) { const instance = this._terminalService.getInstanceFromId(terminalId); instance?.rename(property.value); } this._terminalProcessProxies.get(terminalId)?.emitProcessProperty(property); } $setEnvironmentVariableCollection(extensionIdentifier, persistent, collection, descriptionMap) { if (collection) { const translatedCollection = { persistent, map: deserializeEnvironmentVariableCollection(collection), descriptionMap: deserializeEnvironmentDescriptionMap(descriptionMap) }; this._environmentVariableService.set(extensionIdentifier, translatedCollection); } else { this._environmentVariableService.delete(extensionIdentifier); } } }; MainThreadTerminalService = __decorate([ extHostNamedCustomer(MainContext.MainThreadTerminalService), ( __param(1, ITerminalService)), ( __param(2, ITerminalLinkProviderService)), ( __param(3, ITerminalQuickFixService)), ( __param(4, IInstantiationService)), ( __param(5, IEnvironmentVariableService)), ( __param(6, ILogService)), ( __param(7, ITerminalProfileResolverService)), ( __param(8, IRemoteAgentService)), ( __param(9, ITerminalGroupService)), ( __param(10, ITerminalEditorService)), ( __param(11, ITerminalProfileService)) ], MainThreadTerminalService); let TerminalDataEventTracker = class TerminalDataEventTracker extends Disposable { constructor(_callback, _terminalService) { super(); this._callback = _callback; this._terminalService = _terminalService; this._register(this._bufferer = ( new TerminalDataBufferer(this._callback))); for (const instance of this._terminalService.instances) { this._registerInstance(instance); } this._register(this._terminalService.onDidCreateInstance(instance => this._registerInstance(instance))); this._register(this._terminalService.onDidDisposeInstance(instance => this._bufferer.stopBuffering(instance.instanceId))); } _registerInstance(instance) { this._register(this._bufferer.startBuffering(instance.instanceId, instance.onData)); } }; TerminalDataEventTracker = ( __decorate([ ( __param(1, ITerminalService)) ], TerminalDataEventTracker)); class ExtensionTerminalLinkProvider { constructor(_proxy) { this._proxy = _proxy; } async provideLinks(instance, line) { const proxy = this._proxy; const extHostLinks = await proxy.$provideLinks(instance.instanceId, line); return ( extHostLinks.map(dto => ({ id: dto.id, startIndex: dto.startIndex, length: dto.length, label: dto.label, activate: () => proxy.$activateLink(instance.instanceId, dto.id) }))); } } function getOutputMatchForLines(lines, outputMatcher) { const match = lines.join('\n').match(outputMatcher.lineMatcher); return match ? { regexMatch: match, outputLines: lines } : undefined; } function parseQuickFix(id, source, fix) { let type = TerminalQuickFixType.TerminalCommand; if ('uri' in fix) { fix.uri = URI.revive(fix.uri); type = TerminalQuickFixType.Opener; } else if ('id' in fix) { type = TerminalQuickFixType.VscodeCommand; } return { id, type, source, ...fix }; } export { MainThreadTerminalService, getOutputMatchForLines };