Files
vscode/src/vs/editor/standalone/browser/standaloneServices.ts
Sandeep Somavarapu 13ea41dc8f remove workbench mode concept (#294985)
* remove workbench mode concept

* clean up completely
2026-02-12 19:15:10 +01:00

1280 lines
49 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './standaloneCodeEditorService.js';
import './standaloneLayoutService.js';
import '../../../platform/undoRedo/common/undoRedoService.js';
import '../../common/services/languageFeatureDebounce.js';
import '../../common/services/semanticTokensStylingService.js';
import '../../common/services/languageFeaturesService.js';
import '../../../platform/hover/browser/hoverService.js';
import '../../browser/services/inlineCompletionsService.js';
import * as strings from '../../../base/common/strings.js';
import * as dom from '../../../base/browser/dom.js';
import { StandardKeyboardEvent } from '../../../base/browser/keyboardEvent.js';
import { Emitter, Event, IValueWithChangeEvent, ValueWithChangeEvent } from '../../../base/common/event.js';
import { ResolvedKeybinding, KeyCodeChord, Keybinding, decodeKeybinding } from '../../../base/common/keybindings.js';
import { IDisposable, IReference, ImmortalReference, toDisposable, DisposableStore, Disposable, combinedDisposable } from '../../../base/common/lifecycle.js';
import { OS, isLinux, isMacintosh } from '../../../base/common/platform.js';
import Severity from '../../../base/common/severity.js';
import { URI } from '../../../base/common/uri.js';
import { IRenameSymbolTrackerService, NullRenameSymbolTrackerService } from '../../browser/services/renameSymbolTrackerService.js';
import { IBulkEditOptions, IBulkEditResult, IBulkEditService, ResourceEdit, ResourceTextEdit } from '../../browser/services/bulkEditService.js';
import { isDiffEditorConfigurationKey, isEditorConfigurationKey } from '../../common/config/editorConfigurationSchema.js';
import { EditOperation, ISingleEditOperation } from '../../common/core/editOperation.js';
import { IPosition, Position as Pos } from '../../common/core/position.js';
import { Range } from '../../common/core/range.js';
import { ITextModel, ITextSnapshot } from '../../common/model.js';
import { IModelService } from '../../common/services/model.js';
import { IResolvedTextEditorModel, ITextModelContentProvider, ITextModelService } from '../../common/services/resolverService.js';
import { ITextResourceConfigurationService, ITextResourcePropertiesService, ITextResourceConfigurationChangeEvent } from '../../common/services/textResourceConfiguration.js';
import { CommandsRegistry, ICommandEvent, ICommandHandler, ICommandService } from '../../../platform/commands/common/commands.js';
import { IConfigurationChangeEvent, IConfigurationData, IConfigurationOverrides, IConfigurationService, IConfigurationModel, IConfigurationValue, ConfigurationTarget } from '../../../platform/configuration/common/configuration.js';
import { Configuration, ConfigurationModel, ConfigurationChangeEvent } from '../../../platform/configuration/common/configurationModels.js';
import { IContextKeyService, ContextKeyExpression } from '../../../platform/contextkey/common/contextkey.js';
import { IConfirmation, IConfirmationResult, IDialogService, IInputResult, IPrompt, IPromptResult, IPromptWithCustomCancel, IPromptResultWithCancel, IPromptWithDefaultCancel, IPromptBaseButton } from '../../../platform/dialogs/common/dialogs.js';
import { createDecorator, IInstantiationService, ServiceIdentifier } from '../../../platform/instantiation/common/instantiation.js';
import { AbstractKeybindingService } from '../../../platform/keybinding/common/abstractKeybindingService.js';
import { IKeybindingService, IKeyboardEvent, KeybindingsSchemaContribution } from '../../../platform/keybinding/common/keybinding.js';
import { KeybindingResolver } from '../../../platform/keybinding/common/keybindingResolver.js';
import { IKeybindingItem, KeybindingsRegistry } from '../../../platform/keybinding/common/keybindingsRegistry.js';
import { ResolvedKeybindingItem } from '../../../platform/keybinding/common/resolvedKeybindingItem.js';
import { USLayoutResolvedKeybinding } from '../../../platform/keybinding/common/usLayoutResolvedKeybinding.js';
import { ILabelService, ResourceLabelFormatter, IFormatterChangeEvent, Verbosity } from '../../../platform/label/common/label.js';
import { INotification, INotificationHandle, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions, INotificationSource, INotificationSourceFilter, NotificationsFilter, IStatusHandle } from '../../../platform/notification/common/notification.js';
import { IProgressRunner, IEditorProgressService, IProgressService, IProgress, IProgressCompositeOptions, IProgressDialogOptions, IProgressNotificationOptions, IProgressOptions, IProgressStep, IProgressWindowOptions } from '../../../platform/progress/common/progress.js';
import { ITelemetryService, TelemetryLevel } from '../../../platform/telemetry/common/telemetry.js';
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, IWorkspaceFoldersWillChangeEvent, WorkbenchState, WorkspaceFolder, STANDALONE_EDITOR_WORKSPACE_ID } from '../../../platform/workspace/common/workspace.js';
import { ILayoutService } from '../../../platform/layout/browser/layoutService.js';
import { StandaloneServicesNLS } from '../../common/standaloneStrings.js';
import { basename } from '../../../base/common/resources.js';
import { ICodeEditorService } from '../../browser/services/codeEditorService.js';
import { ConsoleLogger, ILoggerService, ILogService, NullLoggerService } from '../../../platform/log/common/log.js';
import { IWorkspaceTrustManagementService, IWorkspaceTrustTransitionParticipant, IWorkspaceTrustUriInfo } from '../../../platform/workspace/common/workspaceTrust.js';
import { EditorOption } from '../../common/config/editorOptions.js';
import { ICodeEditor, IDiffEditor } from '../../browser/editorBrowser.js';
import { IContextMenuService, IContextViewDelegate, IContextViewService, IOpenContextView } from '../../../platform/contextview/browser/contextView.js';
import { ContextViewService } from '../../../platform/contextview/browser/contextViewService.js';
import { LanguageService } from '../../common/services/languageService.js';
import { ContextMenuService } from '../../../platform/contextview/browser/contextMenuService.js';
import { getSingletonServiceDescriptors, InstantiationType, registerSingleton } from '../../../platform/instantiation/common/extensions.js';
import { OpenerService } from '../../browser/services/openerService.js';
import { ILanguageService } from '../../common/languages/language.js';
import { MarkerDecorationsService } from '../../common/services/markerDecorationsService.js';
import { IMarkerDecorationsService } from '../../common/services/markerDecorations.js';
import { ModelService } from '../../common/services/modelService.js';
import { StandaloneQuickInputService } from './quickInput/standaloneQuickInputService.js';
import { StandaloneThemeService } from './standaloneThemeService.js';
import { IStandaloneThemeService } from '../common/standaloneTheme.js';
import { AccessibilityService } from '../../../platform/accessibility/browser/accessibilityService.js';
import { IAccessibilityService } from '../../../platform/accessibility/common/accessibility.js';
import { IMenuService } from '../../../platform/actions/common/actions.js';
import { MenuService } from '../../../platform/actions/common/menuService.js';
import { BrowserClipboardService } from '../../../platform/clipboard/browser/clipboardService.js';
import { IClipboardService } from '../../../platform/clipboard/common/clipboardService.js';
import { ContextKeyService } from '../../../platform/contextkey/browser/contextKeyService.js';
import { SyncDescriptor } from '../../../platform/instantiation/common/descriptors.js';
import { InstantiationService } from '../../../platform/instantiation/common/instantiationService.js';
import { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';
import { IListService, ListService } from '../../../platform/list/browser/listService.js';
import { IMarkerService } from '../../../platform/markers/common/markers.js';
import { MarkerService } from '../../../platform/markers/common/markerService.js';
import { IOpenerService } from '../../../platform/opener/common/opener.js';
import { IQuickInputService } from '../../../platform/quickinput/common/quickInput.js';
import { IStorageService, InMemoryStorageService } from '../../../platform/storage/common/storage.js';
import { DefaultConfiguration } from '../../../platform/configuration/common/configurations.js';
import { WorkspaceEdit } from '../../common/languages.js';
import { AccessibilitySignal, AccessibilityModality, IAccessibilitySignalService, Sound } from '../../../platform/accessibilitySignal/browser/accessibilitySignalService.js';
import { LogService } from '../../../platform/log/common/logService.js';
import { getEditorFeatures } from '../../common/editorFeatures.js';
import { onUnexpectedError } from '../../../base/common/errors.js';
import { ExtensionKind, IEnvironmentService, IExtensionHostDebugParams } from '../../../platform/environment/common/environment.js';
import { mainWindow } from '../../../base/browser/window.js';
import { ResourceMap } from '../../../base/common/map.js';
import { ITreeSitterLibraryService } from '../../common/services/treeSitter/treeSitterLibraryService.js';
import { StandaloneTreeSitterLibraryService } from './standaloneTreeSitterLibraryService.js';
import { IDataChannelService, NullDataChannelService } from '../../../platform/dataChannel/common/dataChannel.js';
import { IWebWorkerService } from '../../../platform/webWorker/browser/webWorkerService.js';
import { StandaloneWebWorkerService } from './services/standaloneWebWorkerService.js';
import { IDefaultAccountService } from '../../../platform/defaultAccount/common/defaultAccount.js';
import { IDefaultAccount, IDefaultAccountAuthenticationProvider, IPolicyData } from '../../../base/common/defaultAccount.js';
import { IUserInteractionService } from '../../../platform/userInteraction/browser/userInteractionService.js';
import { UserInteractionService } from '../../../platform/userInteraction/browser/userInteractionServiceImpl.js';
class SimpleModel implements IResolvedTextEditorModel {
private readonly model: ITextModel;
private readonly _onWillDispose: Emitter<void>;
constructor(model: ITextModel) {
this.model = model;
this._onWillDispose = new Emitter<void>();
}
public get onWillDispose(): Event<void> {
return this._onWillDispose.event;
}
public resolve(): Promise<void> {
return Promise.resolve();
}
public get textEditorModel(): ITextModel {
return this.model;
}
public createSnapshot(): ITextSnapshot {
return this.model.createSnapshot();
}
public isReadonly(): boolean {
return false;
}
private disposed = false;
public dispose(): void {
this.disposed = true;
this._onWillDispose.fire();
}
public isDisposed(): boolean {
return this.disposed;
}
public isResolved(): boolean {
return true;
}
public getLanguageId(): string | undefined {
return this.model.getLanguageId();
}
}
class StandaloneTextModelService implements ITextModelService {
public _serviceBrand: undefined;
constructor(
@IModelService private readonly modelService: IModelService
) { }
public createModelReference(resource: URI): Promise<IReference<IResolvedTextEditorModel>> {
const model = this.modelService.getModel(resource);
if (!model) {
return Promise.reject(new Error(`Model not found`));
}
return Promise.resolve(new ImmortalReference(new SimpleModel(model)));
}
public registerTextModelContentProvider(scheme: string, provider: ITextModelContentProvider): IDisposable {
return {
dispose: function () { /* no op */ }
};
}
public canHandleResource(resource: URI): boolean {
return false;
}
}
class StandaloneEditorProgressService implements IEditorProgressService {
declare readonly _serviceBrand: undefined;
private static NULL_PROGRESS_RUNNER: IProgressRunner = {
done: () => { },
total: () => { },
worked: () => { }
};
show(infinite: true, delay?: number): IProgressRunner;
show(total: number, delay?: number): IProgressRunner;
show(): IProgressRunner {
return StandaloneEditorProgressService.NULL_PROGRESS_RUNNER;
}
async showWhile(promise: Promise<unknown>, delay?: number): Promise<void> {
await promise;
}
}
class StandaloneProgressService implements IProgressService {
declare readonly _serviceBrand: undefined;
withProgress<R>(_options: IProgressOptions | IProgressDialogOptions | IProgressNotificationOptions | IProgressWindowOptions | IProgressCompositeOptions, task: (progress: IProgress<IProgressStep>) => Promise<R>, onDidCancel?: ((choice?: number | undefined) => void) | undefined): Promise<R> {
return task({
report: () => { },
});
}
}
class StandaloneEnvironmentService implements IEnvironmentService {
declare readonly _serviceBrand: undefined;
readonly stateResource: URI = URI.from({ scheme: 'monaco', authority: 'stateResource' });
readonly userRoamingDataHome: URI = URI.from({ scheme: 'monaco', authority: 'userRoamingDataHome' });
readonly keyboardLayoutResource: URI = URI.from({ scheme: 'monaco', authority: 'keyboardLayoutResource' });
readonly argvResource: URI = URI.from({ scheme: 'monaco', authority: 'argvResource' });
readonly untitledWorkspacesHome: URI = URI.from({ scheme: 'monaco', authority: 'untitledWorkspacesHome' });
readonly workspaceStorageHome: URI = URI.from({ scheme: 'monaco', authority: 'workspaceStorageHome' });
readonly localHistoryHome: URI = URI.from({ scheme: 'monaco', authority: 'localHistoryHome' });
readonly cacheHome: URI = URI.from({ scheme: 'monaco', authority: 'cacheHome' });
readonly userDataSyncHome: URI = URI.from({ scheme: 'monaco', authority: 'userDataSyncHome' });
readonly sync: 'on' | 'off' | undefined = undefined;
readonly continueOn?: string | undefined = undefined;
readonly editSessionId?: string | undefined = undefined;
readonly debugExtensionHost: IExtensionHostDebugParams = { port: null, break: false };
readonly isExtensionDevelopment: boolean = false;
readonly disableExtensions: boolean | string[] = false;
readonly disableExperiments: boolean = false;
readonly enableExtensions?: readonly string[] | undefined = undefined;
readonly extensionDevelopmentLocationURI?: URI[] | undefined = undefined;
readonly extensionDevelopmentKind?: ExtensionKind[] | undefined = undefined;
readonly extensionTestsLocationURI?: URI | undefined = undefined;
readonly logsHome: URI = URI.from({ scheme: 'monaco', authority: 'logsHome' });
readonly logLevel?: string | undefined = undefined;
readonly extensionLogLevel?: [string, string][] | undefined = undefined;
readonly verbose: boolean = false;
readonly isBuilt: boolean = false;
readonly disableTelemetry: boolean = false;
readonly serviceMachineIdResource: URI = URI.from({ scheme: 'monaco', authority: 'serviceMachineIdResource' });
readonly policyFile?: URI | undefined = undefined;
}
class StandaloneDialogService implements IDialogService {
_serviceBrand: undefined;
readonly onWillShowDialog = Event.None;
readonly onDidShowDialog = Event.None;
async confirm(confirmation: IConfirmation): Promise<IConfirmationResult> {
const confirmed = this.doConfirm(confirmation.message, confirmation.detail);
return {
confirmed,
checkboxChecked: false // unsupported
};
}
private doConfirm(message: string, detail?: string): boolean {
let messageText = message;
if (detail) {
messageText = messageText + '\n\n' + detail;
}
return mainWindow.confirm(messageText);
}
prompt<T>(prompt: IPromptWithCustomCancel<T>): Promise<IPromptResultWithCancel<T>>;
prompt<T>(prompt: IPrompt<T>): Promise<IPromptResult<T>>;
prompt<T>(prompt: IPromptWithDefaultCancel<T>): Promise<IPromptResult<T>>;
async prompt<T>(prompt: IPrompt<T> | IPromptWithCustomCancel<T>): Promise<IPromptResult<T> | IPromptResultWithCancel<T>> {
let result: T | undefined = undefined;
const confirmed = this.doConfirm(prompt.message, prompt.detail);
if (confirmed) {
const promptButtons: IPromptBaseButton<T>[] = [...(prompt.buttons ?? [])];
if (prompt.cancelButton && typeof prompt.cancelButton !== 'string' && typeof prompt.cancelButton !== 'boolean') {
promptButtons.push(prompt.cancelButton);
}
result = await promptButtons[0]?.run({ checkboxChecked: false });
}
return { result };
}
async info(message: string, detail?: string): Promise<void> {
await this.prompt({ type: Severity.Info, message, detail });
}
async warn(message: string, detail?: string): Promise<void> {
await this.prompt({ type: Severity.Warning, message, detail });
}
async error(message: string, detail?: string): Promise<void> {
await this.prompt({ type: Severity.Error, message, detail });
}
input(): Promise<IInputResult> {
return Promise.resolve({ confirmed: false }); // unsupported
}
about(): Promise<void> {
return Promise.resolve(undefined);
}
}
export class StandaloneNotificationService implements INotificationService {
readonly onDidChangeFilter: Event<void> = Event.None;
public _serviceBrand: undefined;
private static readonly NO_OP: INotificationHandle = new NoOpNotification();
public info(message: string): INotificationHandle {
return this.notify({ severity: Severity.Info, message });
}
public warn(message: string): INotificationHandle {
return this.notify({ severity: Severity.Warning, message });
}
public error(error: string | Error): INotificationHandle {
return this.notify({ severity: Severity.Error, message: error });
}
public notify(notification: INotification): INotificationHandle {
switch (notification.severity) {
case Severity.Error:
console.error(notification.message);
break;
case Severity.Warning:
console.warn(notification.message);
break;
default:
console.log(notification.message);
break;
}
return StandaloneNotificationService.NO_OP;
}
public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
return StandaloneNotificationService.NO_OP;
}
public status(message: string | Error, options?: IStatusMessageOptions): IStatusHandle {
return { close: () => { } };
}
public setFilter(filter: NotificationsFilter | INotificationSourceFilter): void { }
public getFilter(source?: INotificationSource): NotificationsFilter {
return NotificationsFilter.OFF;
}
public getFilters(): INotificationSourceFilter[] {
return [];
}
public removeFilter(sourceId: string): void { }
}
export class StandaloneCommandService implements ICommandService {
declare readonly _serviceBrand: undefined;
private readonly _instantiationService: IInstantiationService;
private readonly _onWillExecuteCommand = new Emitter<ICommandEvent>();
private readonly _onDidExecuteCommand = new Emitter<ICommandEvent>();
public readonly onWillExecuteCommand: Event<ICommandEvent> = this._onWillExecuteCommand.event;
public readonly onDidExecuteCommand: Event<ICommandEvent> = this._onDidExecuteCommand.event;
constructor(
@IInstantiationService instantiationService: IInstantiationService
) {
this._instantiationService = instantiationService;
}
public executeCommand<T>(id: string, ...args: unknown[]): Promise<T> {
const command = CommandsRegistry.getCommand(id);
if (!command) {
return Promise.reject(new Error(`command '${id}' not found`));
}
try {
this._onWillExecuteCommand.fire({ commandId: id, args });
const result = this._instantiationService.invokeFunction.apply(this._instantiationService, [command.handler, ...args]) as T;
this._onDidExecuteCommand.fire({ commandId: id, args });
return Promise.resolve(result);
} catch (err) {
return Promise.reject(err);
}
}
}
export interface IKeybindingRule {
keybinding: number;
command?: string | null;
commandArgs?: unknown;
when?: ContextKeyExpression | null;
}
export class StandaloneKeybindingService extends AbstractKeybindingService {
private _cachedResolver: KeybindingResolver | null;
private _dynamicKeybindings: IKeybindingItem[];
private readonly _domNodeListeners: DomNodeListeners[];
constructor(
@IContextKeyService contextKeyService: IContextKeyService,
@ICommandService commandService: ICommandService,
@ITelemetryService telemetryService: ITelemetryService,
@INotificationService notificationService: INotificationService,
@ILogService logService: ILogService,
@ICodeEditorService codeEditorService: ICodeEditorService
) {
super(contextKeyService, commandService, telemetryService, notificationService, logService);
this._cachedResolver = null;
this._dynamicKeybindings = [];
this._domNodeListeners = [];
const addContainer = (domNode: HTMLElement) => {
const disposables = new DisposableStore();
// for standard keybindings
disposables.add(dom.addDisposableListener(domNode, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
const keyEvent = new StandardKeyboardEvent(e);
const shouldPreventDefault = this._dispatch(keyEvent, keyEvent.target);
if (shouldPreventDefault) {
keyEvent.preventDefault();
keyEvent.stopPropagation();
}
}));
// for single modifier chord keybindings (e.g. shift shift)
disposables.add(dom.addDisposableListener(domNode, dom.EventType.KEY_UP, (e: KeyboardEvent) => {
const keyEvent = new StandardKeyboardEvent(e);
const shouldPreventDefault = this._singleModifierDispatch(keyEvent, keyEvent.target);
if (shouldPreventDefault) {
keyEvent.preventDefault();
}
}));
this._domNodeListeners.push(new DomNodeListeners(domNode, disposables));
};
const removeContainer = (domNode: HTMLElement) => {
for (let i = 0; i < this._domNodeListeners.length; i++) {
const domNodeListeners = this._domNodeListeners[i];
if (domNodeListeners.domNode === domNode) {
this._domNodeListeners.splice(i, 1);
domNodeListeners.dispose();
}
}
};
const addCodeEditor = (codeEditor: ICodeEditor) => {
if (codeEditor.getOption(EditorOption.inDiffEditor)) {
return;
}
addContainer(codeEditor.getContainerDomNode());
};
const removeCodeEditor = (codeEditor: ICodeEditor) => {
if (codeEditor.getOption(EditorOption.inDiffEditor)) {
return;
}
removeContainer(codeEditor.getContainerDomNode());
};
this._register(codeEditorService.onCodeEditorAdd(addCodeEditor));
this._register(codeEditorService.onCodeEditorRemove(removeCodeEditor));
codeEditorService.listCodeEditors().forEach(addCodeEditor);
const addDiffEditor = (diffEditor: IDiffEditor) => {
addContainer(diffEditor.getContainerDomNode());
};
const removeDiffEditor = (diffEditor: IDiffEditor) => {
removeContainer(diffEditor.getContainerDomNode());
};
this._register(codeEditorService.onDiffEditorAdd(addDiffEditor));
this._register(codeEditorService.onDiffEditorRemove(removeDiffEditor));
codeEditorService.listDiffEditors().forEach(addDiffEditor);
}
public addDynamicKeybinding(command: string, keybinding: number, handler: ICommandHandler, when: ContextKeyExpression | undefined): IDisposable {
return combinedDisposable(
CommandsRegistry.registerCommand(command, handler),
this.addDynamicKeybindings([{
keybinding,
command,
when
}])
);
}
public addDynamicKeybindings(rules: IKeybindingRule[]): IDisposable {
const entries: IKeybindingItem[] = rules.map((rule) => {
const keybinding = decodeKeybinding(rule.keybinding, OS);
return {
keybinding,
command: rule.command ?? null,
commandArgs: rule.commandArgs,
when: rule.when,
weight1: 1000,
weight2: 0,
extensionId: null,
isBuiltinExtension: false
};
});
this._dynamicKeybindings = this._dynamicKeybindings.concat(entries);
this.updateResolver();
return toDisposable(() => {
// Search the first entry and remove them all since they will be contiguous
for (let i = 0; i < this._dynamicKeybindings.length; i++) {
if (this._dynamicKeybindings[i] === entries[0]) {
this._dynamicKeybindings.splice(i, entries.length);
this.updateResolver();
return;
}
}
});
}
private updateResolver(): void {
this._cachedResolver = null;
this._onDidUpdateKeybindings.fire();
}
protected _getResolver(): KeybindingResolver {
if (!this._cachedResolver) {
const defaults = this._toNormalizedKeybindingItems(KeybindingsRegistry.getDefaultKeybindings(), true);
const overrides = this._toNormalizedKeybindingItems(this._dynamicKeybindings, false);
this._cachedResolver = new KeybindingResolver(defaults, overrides, (str) => this._log(str));
}
return this._cachedResolver;
}
protected _documentHasFocus(): boolean {
return mainWindow.document.hasFocus();
}
private _toNormalizedKeybindingItems(items: IKeybindingItem[], isDefault: boolean): ResolvedKeybindingItem[] {
const result: ResolvedKeybindingItem[] = [];
let resultLen = 0;
for (const item of items) {
const when = item.when || undefined;
const keybinding = item.keybinding;
if (!keybinding) {
// This might be a removal keybinding item in user settings => accept it
result[resultLen++] = new ResolvedKeybindingItem(undefined, item.command, item.commandArgs, when, isDefault, null, false);
} else {
const resolvedKeybindings = USLayoutResolvedKeybinding.resolveKeybinding(keybinding, OS);
for (const resolvedKeybinding of resolvedKeybindings) {
result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault, null, false);
}
}
}
return result;
}
public resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[] {
return USLayoutResolvedKeybinding.resolveKeybinding(keybinding, OS);
}
public resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding {
const chord = new KeyCodeChord(
keyboardEvent.ctrlKey,
keyboardEvent.shiftKey,
keyboardEvent.altKey,
keyboardEvent.metaKey,
keyboardEvent.keyCode
);
return new USLayoutResolvedKeybinding([chord], OS);
}
public resolveUserBinding(userBinding: string): ResolvedKeybinding[] {
return [];
}
public _dumpDebugInfo(): string {
return '';
}
public _dumpDebugInfoJSON(): string {
return '';
}
public registerSchemaContribution(contribution: KeybindingsSchemaContribution): IDisposable {
return Disposable.None;
}
/**
* not yet supported
*/
public override enableKeybindingHoldMode(commandId: string): Promise<void> | undefined {
return undefined;
}
}
class DomNodeListeners extends Disposable {
constructor(
public readonly domNode: HTMLElement,
disposables: DisposableStore
) {
super();
this._register(disposables);
}
}
function isConfigurationOverrides(thing: unknown): thing is IConfigurationOverrides {
return !!thing
&& typeof thing === 'object'
&& (!(thing as IConfigurationOverrides).overrideIdentifier || typeof (thing as IConfigurationOverrides).overrideIdentifier === 'string')
&& (!(thing as IConfigurationOverrides).resource || (thing as IConfigurationOverrides).resource instanceof URI);
}
export class StandaloneConfigurationService implements IConfigurationService {
declare readonly _serviceBrand: undefined;
private readonly _onDidChangeConfiguration = new Emitter<IConfigurationChangeEvent>();
public readonly onDidChangeConfiguration: Event<IConfigurationChangeEvent> = this._onDidChangeConfiguration.event;
private readonly _configuration: Configuration;
constructor(
@ILogService private readonly logService: ILogService,
) {
const defaultConfiguration = new DefaultConfiguration(logService);
this._configuration = new Configuration(
defaultConfiguration.reload(),
ConfigurationModel.createEmptyModel(logService),
ConfigurationModel.createEmptyModel(logService),
ConfigurationModel.createEmptyModel(logService),
ConfigurationModel.createEmptyModel(logService),
ConfigurationModel.createEmptyModel(logService),
new ResourceMap<ConfigurationModel>(),
ConfigurationModel.createEmptyModel(logService),
new ResourceMap<ConfigurationModel>(),
logService
);
defaultConfiguration.dispose();
}
getValue<T>(): T;
getValue<T>(section: string): T;
getValue<T>(overrides: IConfigurationOverrides): T;
getValue<T>(section: string, overrides: IConfigurationOverrides): T;
getValue(arg1?: unknown, arg2?: unknown): unknown {
const section = typeof arg1 === 'string' ? arg1 : undefined;
const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : {};
return this._configuration.getValue(section, overrides, undefined);
}
public updateValues(values: [string, unknown][]): Promise<void> {
const previous = { data: this._configuration.toData() };
const changedKeys: string[] = [];
for (const entry of values) {
const [key, value] = entry;
if (this.getValue(key) === value) {
continue;
}
this._configuration.updateValue(key, value);
changedKeys.push(key);
}
if (changedKeys.length > 0) {
const configurationChangeEvent = new ConfigurationChangeEvent({ keys: changedKeys, overrides: [] }, previous, this._configuration, undefined, this.logService);
configurationChangeEvent.source = ConfigurationTarget.MEMORY;
this._onDidChangeConfiguration.fire(configurationChangeEvent);
}
return Promise.resolve();
}
public updateValue(key: string, value: unknown, arg3?: unknown, arg4?: unknown): Promise<void> {
return this.updateValues([[key, value]]);
}
public inspect<C>(key: string, options: IConfigurationOverrides = {}): IConfigurationValue<C> {
return this._configuration.inspect<C>(key, options, undefined);
}
public keys() {
return this._configuration.keys(undefined);
}
public reloadConfiguration(): Promise<void> {
return Promise.resolve(undefined);
}
public getConfigurationData(): IConfigurationData | null {
const emptyModel: IConfigurationModel = {
contents: {},
keys: [],
overrides: []
};
return {
defaults: emptyModel,
policy: emptyModel,
application: emptyModel,
userLocal: emptyModel,
userRemote: emptyModel,
workspace: emptyModel,
folders: []
};
}
}
class StandaloneResourceConfigurationService extends Disposable implements ITextResourceConfigurationService {
declare readonly _serviceBrand: undefined;
private readonly _onDidChangeConfiguration = this._register(new Emitter<ITextResourceConfigurationChangeEvent>());
public readonly onDidChangeConfiguration = this._onDidChangeConfiguration.event;
constructor(
@IConfigurationService private readonly configurationService: StandaloneConfigurationService,
@IModelService private readonly modelService: IModelService,
@ILanguageService private readonly languageService: ILanguageService
) {
super();
this._register(this.configurationService.onDidChangeConfiguration((e) => {
this._onDidChangeConfiguration.fire({ affectedKeys: e.affectedKeys, affectsConfiguration: (resource: URI, configuration: string) => e.affectsConfiguration(configuration) });
}));
}
getValue<T>(resource: URI, section?: string): T;
getValue<T>(resource: URI, position?: IPosition, section?: string): T;
getValue<T>(resource: URI | undefined, arg2?: unknown, arg3?: unknown) {
const position: IPosition | null = Pos.isIPosition(arg2) ? arg2 : null;
const section: string | undefined = position ? (typeof arg3 === 'string' ? arg3 : undefined) : (typeof arg2 === 'string' ? arg2 : undefined);
const language = resource ? this.getLanguage(resource, position) : undefined;
if (typeof section === 'undefined') {
return this.configurationService.getValue<T>({
resource,
overrideIdentifier: language
});
}
return this.configurationService.getValue<T>(section, {
resource,
overrideIdentifier: language
});
}
inspect<T>(resource: URI | undefined, position: IPosition | null, section: string): IConfigurationValue<Readonly<T>> {
const language = resource ? this.getLanguage(resource, position) : undefined;
return this.configurationService.inspect<T>(section, { resource, overrideIdentifier: language });
}
private getLanguage(resource: URI, position: IPosition | null): string | null {
const model = this.modelService.getModel(resource);
if (model) {
return position ? model.getLanguageIdAtPosition(position.lineNumber, position.column) : model.getLanguageId();
}
return this.languageService.guessLanguageIdByFilepathOrFirstLine(resource);
}
updateValue(resource: URI, key: string, value: unknown, configurationTarget?: ConfigurationTarget): Promise<void> {
return this.configurationService.updateValue(key, value, { resource }, configurationTarget);
}
}
class StandaloneResourcePropertiesService implements ITextResourcePropertiesService {
declare readonly _serviceBrand: undefined;
constructor(
@IConfigurationService private readonly configurationService: IConfigurationService,
) {
}
getEOL(resource: URI, language?: string): string {
const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource });
if (eol && typeof eol === 'string' && eol !== 'auto') {
return eol;
}
return (isLinux || isMacintosh) ? '\n' : '\r\n';
}
}
class StandaloneTelemetryService implements ITelemetryService {
declare readonly _serviceBrand: undefined;
readonly telemetryLevel = TelemetryLevel.NONE;
readonly sessionId = 'someValue.sessionId';
readonly machineId = 'someValue.machineId';
readonly sqmId = 'someValue.sqmId';
readonly devDeviceId = 'someValue.devDeviceId';
readonly firstSessionDate = 'someValue.firstSessionDate';
readonly sendErrorTelemetry = false;
setEnabled(): void { }
setExperimentProperty(): void { }
publicLog() { }
publicLog2() { }
publicLogError() { }
publicLogError2() { }
}
class StandaloneWorkspaceContextService implements IWorkspaceContextService {
public _serviceBrand: undefined;
private static readonly SCHEME = 'inmemory';
private readonly _onDidChangeWorkspaceName = new Emitter<void>();
public readonly onDidChangeWorkspaceName: Event<void> = this._onDidChangeWorkspaceName.event;
private readonly _onWillChangeWorkspaceFolders = new Emitter<IWorkspaceFoldersWillChangeEvent>();
public readonly onWillChangeWorkspaceFolders: Event<IWorkspaceFoldersWillChangeEvent> = this._onWillChangeWorkspaceFolders.event;
private readonly _onDidChangeWorkspaceFolders = new Emitter<IWorkspaceFoldersChangeEvent>();
public readonly onDidChangeWorkspaceFolders: Event<IWorkspaceFoldersChangeEvent> = this._onDidChangeWorkspaceFolders.event;
private readonly _onDidChangeWorkbenchState = new Emitter<WorkbenchState>();
public readonly onDidChangeWorkbenchState: Event<WorkbenchState> = this._onDidChangeWorkbenchState.event;
private readonly workspace: IWorkspace;
constructor() {
const resource = URI.from({ scheme: StandaloneWorkspaceContextService.SCHEME, authority: 'model', path: '/' });
this.workspace = { id: STANDALONE_EDITOR_WORKSPACE_ID, folders: [new WorkspaceFolder({ uri: resource, name: '', index: 0 })] };
}
getCompleteWorkspace(): Promise<IWorkspace> {
return Promise.resolve(this.getWorkspace());
}
public getWorkspace(): IWorkspace {
return this.workspace;
}
public getWorkbenchState(): WorkbenchState {
if (this.workspace) {
if (this.workspace.configuration) {
return WorkbenchState.WORKSPACE;
}
return WorkbenchState.FOLDER;
}
return WorkbenchState.EMPTY;
}
public getWorkspaceFolder(resource: URI): IWorkspaceFolder | null {
return resource && resource.scheme === StandaloneWorkspaceContextService.SCHEME ? this.workspace.folders[0] : null;
}
public isInsideWorkspace(resource: URI): boolean {
return resource && resource.scheme === StandaloneWorkspaceContextService.SCHEME;
}
public isCurrentWorkspace(workspaceIdOrFolder: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI): boolean {
return true;
}
}
export function updateConfigurationService(configurationService: IConfigurationService, source: any, isDiffEditor: boolean): void {
if (!source) {
return;
}
if (!(configurationService instanceof StandaloneConfigurationService)) {
return;
}
const toUpdate: [string, unknown][] = [];
Object.keys(source).forEach((key) => {
if (isEditorConfigurationKey(key)) {
toUpdate.push([`editor.${key}`, source[key]]);
}
if (isDiffEditor && isDiffEditorConfigurationKey(key)) {
toUpdate.push([`diffEditor.${key}`, source[key]]);
}
});
if (toUpdate.length > 0) {
configurationService.updateValues(toUpdate);
}
}
class StandaloneBulkEditService implements IBulkEditService {
declare readonly _serviceBrand: undefined;
constructor(
@IModelService private readonly _modelService: IModelService
) {
//
}
hasPreviewHandler(): false {
return false;
}
setPreviewHandler(): IDisposable {
return Disposable.None;
}
async apply(editsIn: ResourceEdit[] | WorkspaceEdit, _options?: IBulkEditOptions): Promise<IBulkEditResult> {
const edits = Array.isArray(editsIn) ? editsIn : ResourceEdit.convert(editsIn);
const textEdits = new Map<ITextModel, ISingleEditOperation[]>();
for (const edit of edits) {
if (!(edit instanceof ResourceTextEdit)) {
throw new Error('bad edit - only text edits are supported');
}
const model = this._modelService.getModel(edit.resource);
if (!model) {
throw new Error('bad edit - model not found');
}
if (typeof edit.versionId === 'number' && model.getVersionId() !== edit.versionId) {
throw new Error('bad state - model changed in the meantime');
}
let array = textEdits.get(model);
if (!array) {
array = [];
textEdits.set(model, array);
}
array.push(EditOperation.replaceMove(Range.lift(edit.textEdit.range), edit.textEdit.text));
}
let totalEdits = 0;
let totalFiles = 0;
for (const [model, edits] of textEdits) {
model.pushStackElement();
model.pushEditOperations([], edits, () => []);
model.pushStackElement();
totalFiles += 1;
totalEdits += edits.length;
}
return {
ariaSummary: strings.format(StandaloneServicesNLS.bulkEditServiceSummary, totalEdits, totalFiles),
isApplied: totalEdits > 0
};
}
}
class StandaloneUriLabelService implements ILabelService {
declare readonly _serviceBrand: undefined;
public readonly onDidChangeFormatters: Event<IFormatterChangeEvent> = Event.None;
public getUriLabel(resource: URI, options?: { relative?: boolean; forceNoTildify?: boolean }): string {
if (resource.scheme === 'file') {
return resource.fsPath;
}
return resource.path;
}
getUriBasenameLabel(resource: URI): string {
return basename(resource);
}
public getWorkspaceLabel(workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | IWorkspace, options?: { verbose: Verbosity }): string {
return '';
}
public getSeparator(scheme: string, authority?: string): '/' | '\\' {
return '/';
}
public registerFormatter(formatter: ResourceLabelFormatter): IDisposable {
throw new Error('Not implemented');
}
public registerCachedFormatter(formatter: ResourceLabelFormatter): IDisposable {
return this.registerFormatter(formatter);
}
public getHostLabel(): string {
return '';
}
public getHostTooltip(): string | undefined {
return undefined;
}
}
class StandaloneContextViewService extends ContextViewService {
constructor(
@ILayoutService layoutService: ILayoutService,
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
) {
super(layoutService);
}
override showContextView(delegate: IContextViewDelegate, container?: HTMLElement, shadowRoot?: boolean): IOpenContextView {
if (!container) {
const codeEditor = this._codeEditorService.getFocusedCodeEditor() || this._codeEditorService.getActiveCodeEditor();
if (codeEditor) {
container = codeEditor.getContainerDomNode();
}
}
return super.showContextView(delegate, container, shadowRoot);
}
}
class StandaloneWorkspaceTrustManagementService implements IWorkspaceTrustManagementService {
_serviceBrand: undefined;
private _neverEmitter = new Emitter<never>();
public readonly onDidChangeTrust: Event<boolean> = this._neverEmitter.event;
readonly onDidChangeTrustedFolders: Event<void> = this._neverEmitter.event;
public readonly workspaceResolved = Promise.resolve();
public readonly workspaceTrustInitialized = Promise.resolve();
public readonly acceptsOutOfWorkspaceFiles = true;
isWorkspaceTrusted(): boolean {
return true;
}
isWorkspaceTrustForced(): boolean {
return false;
}
canSetParentFolderTrust(): boolean {
return false;
}
async setParentFolderTrust(trusted: boolean): Promise<void> {
// noop
}
canSetWorkspaceTrust(): boolean {
return false;
}
async setWorkspaceTrust(trusted: boolean): Promise<void> {
// noop
}
getUriTrustInfo(uri: URI): Promise<IWorkspaceTrustUriInfo> {
throw new Error('Method not supported.');
}
async setUrisTrust(uri: URI[], trusted: boolean): Promise<void> {
// noop
}
getTrustedUris(): URI[] {
return [];
}
async setTrustedUris(uris: URI[]): Promise<void> {
// noop
}
addWorkspaceTrustTransitionParticipant(participant: IWorkspaceTrustTransitionParticipant): IDisposable {
throw new Error('Method not supported.');
}
}
class StandaloneLanguageService extends LanguageService {
constructor() {
super();
}
}
class StandaloneLogService extends LogService {
constructor() {
super(new ConsoleLogger());
}
}
class StandaloneContextMenuService extends ContextMenuService {
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@INotificationService notificationService: INotificationService,
@IContextViewService contextViewService: IContextViewService,
@IKeybindingService keybindingService: IKeybindingService,
@IMenuService menuService: IMenuService,
@IContextKeyService contextKeyService: IContextKeyService,
) {
super(telemetryService, notificationService, contextViewService, keybindingService, menuService, contextKeyService);
this.configure({ blockMouse: false }); // we do not want that in the standalone editor
}
}
class StandaloneAccessbilitySignalService implements IAccessibilitySignalService {
_serviceBrand: undefined;
async playSignal(cue: AccessibilitySignal, options: {}): Promise<void> {
}
async playSignals(cues: AccessibilitySignal[]): Promise<void> {
}
getEnabledState(signal: AccessibilitySignal, userGesture: boolean, modality?: AccessibilityModality | undefined): IValueWithChangeEvent<boolean> {
return ValueWithChangeEvent.const(false);
}
getDelayMs(signal: AccessibilitySignal, modality: AccessibilityModality): number {
return 0;
}
isSoundEnabled(cue: AccessibilitySignal): boolean {
return false;
}
isAnnouncementEnabled(cue: AccessibilitySignal): boolean {
return false;
}
onSoundEnabledChanged(cue: AccessibilitySignal): Event<void> {
return Event.None;
}
async playSound(cue: Sound, allowManyInParallel?: boolean | undefined): Promise<void> {
}
playSignalLoop(cue: AccessibilitySignal): IDisposable {
return toDisposable(() => { });
}
}
class StandaloneDefaultAccountService implements IDefaultAccountService {
declare readonly _serviceBrand: undefined;
readonly onDidChangeDefaultAccount: Event<IDefaultAccount | null> = Event.None;
readonly onDidChangePolicyData: Event<IPolicyData | null> = Event.None;
readonly policyData: IPolicyData | null = null;
async getDefaultAccount(): Promise<IDefaultAccount | null> {
return null;
}
setDefaultAccountProvider(): void {
// no-op
}
async refresh(): Promise<IDefaultAccount | null> {
return null;
}
getDefaultAccountAuthenticationProvider(): IDefaultAccountAuthenticationProvider {
return { id: 'default', name: 'Default', enterprise: false };
}
async signIn(): Promise<IDefaultAccount | null> {
return null;
}
}
export interface IEditorOverrideServices {
[index: string]: unknown;
}
registerSingleton(IWebWorkerService, StandaloneWebWorkerService, InstantiationType.Eager);
registerSingleton(ILogService, StandaloneLogService, InstantiationType.Eager);
registerSingleton(IConfigurationService, StandaloneConfigurationService, InstantiationType.Eager);
registerSingleton(ITextResourceConfigurationService, StandaloneResourceConfigurationService, InstantiationType.Eager);
registerSingleton(ITextResourcePropertiesService, StandaloneResourcePropertiesService, InstantiationType.Eager);
registerSingleton(IWorkspaceContextService, StandaloneWorkspaceContextService, InstantiationType.Eager);
registerSingleton(ILabelService, StandaloneUriLabelService, InstantiationType.Eager);
registerSingleton(ITelemetryService, StandaloneTelemetryService, InstantiationType.Eager);
registerSingleton(IDialogService, StandaloneDialogService, InstantiationType.Eager);
registerSingleton(IEnvironmentService, StandaloneEnvironmentService, InstantiationType.Eager);
registerSingleton(INotificationService, StandaloneNotificationService, InstantiationType.Eager);
registerSingleton(IMarkerService, MarkerService, InstantiationType.Eager);
registerSingleton(ILanguageService, StandaloneLanguageService, InstantiationType.Eager);
registerSingleton(IStandaloneThemeService, StandaloneThemeService, InstantiationType.Eager);
registerSingleton(IModelService, ModelService, InstantiationType.Eager);
registerSingleton(IMarkerDecorationsService, MarkerDecorationsService, InstantiationType.Eager);
registerSingleton(IContextKeyService, ContextKeyService, InstantiationType.Eager);
registerSingleton(IProgressService, StandaloneProgressService, InstantiationType.Eager);
registerSingleton(IEditorProgressService, StandaloneEditorProgressService, InstantiationType.Eager);
registerSingleton(IStorageService, InMemoryStorageService, InstantiationType.Eager);
registerSingleton(IBulkEditService, StandaloneBulkEditService, InstantiationType.Eager);
registerSingleton(IWorkspaceTrustManagementService, StandaloneWorkspaceTrustManagementService, InstantiationType.Eager);
registerSingleton(ITextModelService, StandaloneTextModelService, InstantiationType.Eager);
registerSingleton(IAccessibilityService, AccessibilityService, InstantiationType.Eager);
registerSingleton(IListService, ListService, InstantiationType.Eager);
registerSingleton(ICommandService, StandaloneCommandService, InstantiationType.Eager);
registerSingleton(IKeybindingService, StandaloneKeybindingService, InstantiationType.Eager);
registerSingleton(IQuickInputService, StandaloneQuickInputService, InstantiationType.Eager);
registerSingleton(IContextViewService, StandaloneContextViewService, InstantiationType.Eager);
registerSingleton(IOpenerService, OpenerService, InstantiationType.Eager);
registerSingleton(IClipboardService, BrowserClipboardService, InstantiationType.Eager);
registerSingleton(IContextMenuService, StandaloneContextMenuService, InstantiationType.Eager);
registerSingleton(IMenuService, MenuService, InstantiationType.Eager);
registerSingleton(IAccessibilitySignalService, StandaloneAccessbilitySignalService, InstantiationType.Eager);
registerSingleton(ITreeSitterLibraryService, StandaloneTreeSitterLibraryService, InstantiationType.Eager);
registerSingleton(ILoggerService, NullLoggerService, InstantiationType.Eager);
registerSingleton(IDataChannelService, NullDataChannelService, InstantiationType.Eager);
registerSingleton(IDefaultAccountService, StandaloneDefaultAccountService, InstantiationType.Eager);
registerSingleton(IRenameSymbolTrackerService, NullRenameSymbolTrackerService, InstantiationType.Eager);
registerSingleton(IUserInteractionService, UserInteractionService, InstantiationType.Eager);
/**
* We don't want to eagerly instantiate services because embedders get a one time chance
* to override services when they create the first editor.
*/
export namespace StandaloneServices {
const serviceCollection = new ServiceCollection();
for (const [id, descriptor] of getSingletonServiceDescriptors()) {
serviceCollection.set(id, descriptor);
}
const instantiationService = new InstantiationService(serviceCollection, true);
serviceCollection.set(IInstantiationService, instantiationService);
export function get<T>(serviceId: ServiceIdentifier<T>): T {
if (!initialized) {
initialize({});
}
const r = serviceCollection.get(serviceId);
if (!r) {
throw new Error('Missing service ' + serviceId);
}
if (r instanceof SyncDescriptor) {
return instantiationService.invokeFunction((accessor) => accessor.get(serviceId));
} else {
return r;
}
}
let initialized = false;
const onDidInitialize = new Emitter<void>();
export function initialize(overrides: IEditorOverrideServices): IInstantiationService {
if (initialized) {
return instantiationService;
}
initialized = true;
// Add singletons that were registered after this module loaded
for (const [id, descriptor] of getSingletonServiceDescriptors()) {
if (!serviceCollection.get(id)) {
serviceCollection.set(id, descriptor);
}
}
// Initialize the service collection with the overrides, but only if the
// service was not instantiated in the meantime.
for (const serviceId in overrides) {
if (overrides.hasOwnProperty(serviceId)) {
const serviceIdentifier = createDecorator(serviceId);
const r = serviceCollection.get(serviceIdentifier);
if (r instanceof SyncDescriptor) {
serviceCollection.set(serviceIdentifier, overrides[serviceId]);
}
}
}
// Instantiate all editor features
const editorFeatures = getEditorFeatures();
for (const feature of editorFeatures) {
try {
instantiationService.createInstance(feature);
} catch (err) {
onUnexpectedError(err);
}
}
onDidInitialize.fire();
return instantiationService;
}
/**
* Executes callback once services are initialized.
*/
export function withServices(callback: () => IDisposable): IDisposable {
if (initialized) {
return callback();
}
const disposable = new DisposableStore();
const listener = disposable.add(onDidInitialize.event(() => {
listener.dispose();
disposable.add(callback());
}));
return disposable;
}
}