only allow primitive values in context keys

This commit is contained in:
Johannes committed 2022-04-22 16:20:43 +02:00
1 parent a9dbd356a3
commit b9cbee9fac
14 files changed
+62 -54

No files matched your search

+1 -1
View File
@@ -63,7 +63,7 @@ declare namespace monaco.editor {
export interface ICommandHandler {
(...args: any[]): void;
}
#include(vs/platform/contextkey/common/contextkey): IContextKey
#include(vs/platform/contextkey/common/contextkey): IContextKey, ContextKeyValue
#include(vs/editor/standalone/browser/standaloneServices): IEditorOverrideServices
#include(vs/platform/markers/common/markers): IMarker, IMarkerData, IRelatedInformation
#include(vs/editor/standalone/browser/colorizer): IColorizerOptions, IColorizerElementOptions
@@ -32,11 +32,11 @@ export const Context = {
Visible: historyNavigationVisible,
DetailsVisible: new RawContextKey<boolean>('suggestWidgetDetailsVisible', false, localize('suggestWidgetDetailsVisible', "Whether suggestion details are visible")),
MultipleSuggestions: new RawContextKey<boolean>('suggestWidgetMultipleSuggestions', false, localize('suggestWidgetMultipleSuggestions', "Whether there are multiple suggestions to pick from")),
MakesTextEdit: new RawContextKey('suggestionMakesTextEdit', true, localize('suggestionMakesTextEdit', "Whether inserting the current suggestion yields in a change or has everything already been typed")),
MakesTextEdit: new RawContextKey<boolean>('suggestionMakesTextEdit', true, localize('suggestionMakesTextEdit', "Whether inserting the current suggestion yields in a change or has everything already been typed")),
AcceptSuggestionsOnEnter: new RawContextKey<boolean>('acceptSuggestionOnEnter', true, localize('acceptSuggestionOnEnter', "Whether suggestions are inserted when pressing Enter")),
HasInsertAndReplaceRange: new RawContextKey('suggestionHasInsertAndReplaceRange', false, localize('suggestionHasInsertAndReplaceRange', "Whether the current suggestion has insert and replace behaviour")),
HasInsertAndReplaceRange: new RawContextKey<boolean>('suggestionHasInsertAndReplaceRange', false, localize('suggestionHasInsertAndReplaceRange', "Whether the current suggestion has insert and replace behaviour")),
InsertMode: new RawContextKey<'insert' | 'replace'>('suggestionInsertMode', undefined, { type: 'string', description: localize('suggestionInsertMode', "Whether the default behaviour is to insert or replace") }),
CanResolve: new RawContextKey('suggestionCanResolve', false, localize('suggestionCanResolve', "Whether the current suggestion supports to resolve further details")),
CanResolve: new RawContextKey<boolean>('suggestionCanResolve', false, localize('suggestionCanResolve', "Whether the current suggestion supports to resolve further details")),
};
export const suggestWidgetStatusbarMenu = new MenuId('suggestWidgetStatusBar');
@@ -19,7 +19,7 @@ import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneT
import { IMenuItem, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpr, ContextKeyValue, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
@@ -224,13 +224,13 @@ export interface IStandaloneDiffEditorConstructionOptions extends IDiffEditorCon
export interface IStandaloneCodeEditor extends ICodeEditor {
updateOptions(newOptions: IEditorOptions & IGlobalEditorOptions): void;
addCommand(keybinding: number, handler: ICommandHandler, context?: string): string | null;
createContextKey<T>(key: string, defaultValue: T): IContextKey<T>;
createContextKey<T extends ContextKeyValue = ContextKeyValue>(key: string, defaultValue: T): IContextKey<T>;
addAction(descriptor: IActionDescriptor): IDisposable;
}
export interface IStandaloneDiffEditor extends IDiffEditor {
addCommand(keybinding: number, handler: ICommandHandler, context?: string): string | null;
createContextKey<T>(key: string, defaultValue: T): IContextKey<T>;
createContextKey<T extends ContextKeyValue = ContextKeyValue>(key: string, defaultValue: T): IContextKey<T>;
addAction(descriptor: IActionDescriptor): IDisposable;
getOriginalEditor(): IStandaloneCodeEditor;
@@ -301,7 +301,7 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon
return commandId;
}
public createContextKey<T>(key: string, defaultValue: T): IContextKey<T> {
public createContextKey<T extends ContextKeyValue = ContextKeyValue>(key: string, defaultValue: T): IContextKey<T> {
return this._contextKeyService.createKey(key, defaultValue);
}
@@ -548,7 +548,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
return this.getModifiedEditor().addCommand(keybinding, handler, context);
}
public createContextKey<T>(key: string, defaultValue: T): IContextKey<T> {
public createContextKey<T extends ContextKeyValue = ContextKeyValue>(key: string, defaultValue: T): IContextKey<T> {
return this.getModifiedEditor().createContextKey(key, defaultValue);
}
+5 -3
View File
@@ -1265,13 +1265,13 @@ declare namespace monaco.editor {
export interface IStandaloneCodeEditor extends ICodeEditor {
updateOptions(newOptions: IEditorOptions & IGlobalEditorOptions): void;
addCommand(keybinding: number, handler: ICommandHandler, context?: string): string | null;
createContextKey<T>(key: string, defaultValue: T): IContextKey<T>;
createContextKey<T extends ContextKeyValue = ContextKeyValue>(key: string, defaultValue: T): IContextKey<T>;
addAction(descriptor: IActionDescriptor): IDisposable;
}
export interface IStandaloneDiffEditor extends IDiffEditor {
addCommand(keybinding: number, handler: ICommandHandler, context?: string): string | null;
createContextKey<T>(key: string, defaultValue: T): IContextKey<T>;
createContextKey<T extends ContextKeyValue = ContextKeyValue>(key: string, defaultValue: T): IContextKey<T>;
addAction(descriptor: IActionDescriptor): IDisposable;
getOriginalEditor(): IStandaloneCodeEditor;
getModifiedEditor(): IStandaloneCodeEditor;
@@ -1280,12 +1280,14 @@ declare namespace monaco.editor {
(...args: any[]): void;
}
export interface IContextKey<T> {
export interface IContextKey<T extends ContextKeyValue = ContextKeyValue> {
set(value: T): void;
reset(): void;
get(): T | undefined;
}
export type ContextKeyValue = null | undefined | boolean | number | string;
export interface IEditorOverrideServices {
[index: string]: any;
}
@@ -11,7 +11,7 @@ import { distinct } from 'vs/base/common/objects';
import { localize } from 'vs/nls';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpression, ContextKeyInfo, IContext, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget, IReadableSet, RawContextKey, SET_CONTEXT_COMMAND_ID } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpression, ContextKeyInfo, ContextKeyValue, IContext, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget, IReadableSet, RawContextKey, SET_CONTEXT_COMMAND_ID } from 'vs/platform/contextkey/common/contextkey';
const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';
@@ -182,7 +182,7 @@ class ConfigAwareContextValuesContainer extends Context {
}
}
class ContextKey<T> implements IContextKey<T> {
class ContextKey<T extends ContextKeyValue> implements IContextKey<T> {
private _service: AbstractContextKeyService;
private _key: string;
@@ -263,7 +263,7 @@ export abstract class AbstractContextKeyService implements IContextKeyService {
abstract dispose(): void;
public createKey<T>(key: string, defaultValue: T | undefined): IContextKey<T> {
public createKey<T extends ContextKeyValue>(key: string, defaultValue: T | undefined): IContextKey<T> {
if (this._isDisposed) {
throw new Error(`AbstractContextKeyService has been disposed`);
}
@@ -520,7 +520,7 @@ class OverlayContextKeyService implements IContextKeyService {
this.parent.bufferChangeEvents(callback);
}
createKey<T>(): IContextKey<T> {
createKey<T extends ContextKeyValue>(): IContextKey<T> {
throw new Error('Not supported.');
}
@@ -1524,7 +1524,7 @@ export interface ContextKeyInfo {
readonly description?: string;
}
export class RawContextKey<T> extends ContextKeyDefinedExpr {
export class RawContextKey<T extends ContextKeyValue> extends ContextKeyDefinedExpr {
private static _info: ContextKeyInfo[] = [];
@@ -1567,11 +1567,13 @@ export class RawContextKey<T> extends ContextKeyDefinedExpr {
}
}
export type ContextKeyValue = null | undefined | boolean | number | string;
export interface IContext {
getValue<T>(key: string): T | undefined;
getValue<T extends ContextKeyValue = ContextKeyValue>(key: string): T | undefined;
}
export interface IContextKey<T> {
export interface IContextKey<T extends ContextKeyValue = ContextKeyValue> {
set(value: T): void;
reset(): void;
get(): T | undefined;
@@ -1602,7 +1604,7 @@ export interface IContextKeyService {
onDidChangeContext: Event<IContextKeyChangeEvent>;
bufferChangeEvents(callback: Function): void;
createKey<T>(key: string, defaultValue: T | undefined): IContextKey<T>;
createKey<T extends ContextKeyValue>(key: string, defaultValue: T | undefined): IContextKey<T>;
contextMatchesRules(rules: ContextKeyExpression | undefined): boolean;
getContextKeyValue<T>(key: string): T | undefined;
@@ -6,13 +6,13 @@
import { Event } from 'vs/base/common/event';
import { Keybinding, ResolvedKeybinding, SimpleKeybinding } from 'vs/base/common/keybindings';
import { OS } from 'vs/base/common/platform';
import { ContextKeyExpression, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpression, ContextKeyValue, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
import { IKeybindingEvent, IKeybindingService, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
import { IResolveResult } from 'vs/platform/keybinding/common/keybindingResolver';
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
class MockKeybindingContextKey<T> implements IContextKey<T> {
class MockKeybindingContextKey<T extends ContextKeyValue = ContextKeyValue> implements IContextKey<T> {
private _defaultValue: T | undefined;
private _value: T | undefined;
@@ -42,7 +42,7 @@ export class MockContextKeyService implements IContextKeyService {
public dispose(): void {
//
}
public createKey<T>(key: string, defaultValue: T | undefined): IContextKey<T> {
public createKey<T extends ContextKeyValue = ContextKeyValue>(key: string, defaultValue: T | undefined): IContextKey<T> {
let ret = new MockKeybindingContextKey(defaultValue);
this._keys.set(key, ret);
return ret;
+11 -7
View File
@@ -136,7 +136,7 @@ export function getEnabledViewContainerContextKey(viewContainerId: string): stri
//#region < --- Resources --- >
export class ResourceContextKey implements IContextKey<URI> {
export class ResourceContextKey {
// NOTE: DO NOT CHANGE THE DEFAULT VALUE TO ANYTHING BUT
// UNDEFINED! IT IS IMPORTANT THAT DEFAULTS ARE INHERITED
@@ -147,14 +147,15 @@ export class ResourceContextKey implements IContextKey<URI> {
static readonly Dirname = new RawContextKey<string>('resourceDirname', undefined, { type: 'string', description: localize('resourceDirname', "The folder name the resource is contained in") });
static readonly Path = new RawContextKey<string>('resourcePath', undefined, { type: 'string', description: localize('resourcePath', "The full path of the resource") });
static readonly LangId = new RawContextKey<string>('resourceLangId', undefined, { type: 'string', description: localize('resourceLangId', "The language identifier of the resource") });
static readonly Resource = new RawContextKey<URI>('resource', undefined, { type: 'URI', description: localize('resource', "The full value of the resource including scheme and path") });
static readonly Resource = new RawContextKey<string>('resource', undefined, { type: 'URI', description: localize('resource', "The full value of the resource including scheme and path") });
static readonly Extension = new RawContextKey<string>('resourceExtname', undefined, { type: 'string', description: localize('resourceExtname', "The extension name of the resource") });
static readonly HasResource = new RawContextKey<boolean>('resourceSet', undefined, { type: 'boolean', description: localize('resourceSet', "Whether a resource is present or not") });
static readonly IsFileSystemResource = new RawContextKey<boolean>('isFileSystemResource', undefined, { type: 'boolean', description: localize('isFileSystemResource', "Whether the resource is backed by a file system provider") });
private readonly _disposables = new DisposableStore();
private readonly _resourceKey: IContextKey<URI | null>;
private _value: URI | undefined;
private readonly _resourceKey: IContextKey<string | null>;
private readonly _schemeKey: IContextKey<string | null>;
private readonly _filenameKey: IContextKey<string | null>;
private readonly _dirnameKey: IContextKey<string | null>;
@@ -211,12 +212,14 @@ export class ResourceContextKey implements IContextKey<URI> {
this._langIdKey.set(langId);
}
set(value: URI | null) {
if (isEqual(this.get(), value ?? undefined)) {
set(value: URI | null | undefined) {
value = value ?? undefined;
if (isEqual(this._value, value)) {
return;
}
this._value = value;
this._contextKeyService.bufferChangeEvents(() => {
this._resourceKey.set(value);
this._resourceKey.set(value ? value.toString() : null);
this._schemeKey.set(value ? value.scheme : null);
this._filenameKey.set(value ? basename(value) : null);
this._dirnameKey.set(value ? dirname(value).fsPath : null);
@@ -229,6 +232,7 @@ export class ResourceContextKey implements IContextKey<URI> {
}
reset(): void {
this._value = undefined;
this._contextKeyService.bufferChangeEvents(() => {
this._resourceKey.reset();
this._schemeKey.reset();
@@ -243,7 +247,7 @@ export class ResourceContextKey implements IContextKey<URI> {
}
get(): URI | undefined {
return this._resourceKey.get() ?? undefined;
return this._value;
}
}
@@ -34,7 +34,7 @@ export class ViewModel implements IViewModel {
private terminateDebuggeeSupported!: IContextKey<boolean>;
private suspendDebuggeeSupported!: IContextKey<boolean>;
private disassembleRequestSupported!: IContextKey<boolean>;
private focusedStackFrameHasInstructionPointerReference!: IContextKey<Boolean>;
private focusedStackFrameHasInstructionPointerReference!: IContextKey<boolean>;
constructor(private contextKeyService: IContextKeyService) {
contextKeyService.bufferChangeEvents(() => {
@@ -1855,8 +1855,8 @@ class SCMInputWidget extends Disposable {
}, 0);
}));
const firstLineKey = contextKeyService2.createKey('scmInputIsInFirstPosition', false);
const lastLineKey = contextKeyService2.createKey('scmInputIsInLastPosition', false);
const firstLineKey = contextKeyService2.createKey<boolean>('scmInputIsInFirstPosition', false);
const lastLineKey = contextKeyService2.createKey<boolean>('scmInputIsInLastPosition', false);
this._register(this.inputEditor.onDidChangeCursorPosition(({ position }) => {
const viewModel = this.inputEditor._getViewModel()!;
@@ -26,13 +26,13 @@ export namespace TestingContextKeys {
[TestRunProfileBitset.HasConfigurable]: hasConfigurableProfile,
};
export const hasAnyResults = new RawContextKey('testing.hasAnyResults', false);
export const viewMode = new RawContextKey('testing.explorerViewMode', TestExplorerViewMode.List);
export const viewSorting = new RawContextKey('testing.explorerViewSorting', TestExplorerViewSorting.ByLocation);
export const isRunning = new RawContextKey('testing.isRunning', false);
export const isInPeek = new RawContextKey('testing.isInPeek', true);
export const isPeekVisible = new RawContextKey('testing.isPeekVisible', false);
export const autoRun = new RawContextKey('testing.autoRun', false);
export const hasAnyResults = new RawContextKey<boolean>('testing.hasAnyResults', false);
export const viewMode = new RawContextKey<TestExplorerViewMode>('testing.explorerViewMode', TestExplorerViewMode.List);
export const viewSorting = new RawContextKey<TestExplorerViewSorting>('testing.explorerViewSorting', TestExplorerViewSorting.ByLocation);
export const isRunning = new RawContextKey<boolean>('testing.isRunning', false);
export const isInPeek = new RawContextKey<boolean>('testing.isInPeek', true);
export const isPeekVisible = new RawContextKey<boolean>('testing.isPeekVisible', false);
export const autoRun = new RawContextKey<boolean>('testing.autoRun', false);
export const peekItemType = new RawContextKey<string | undefined>('peekItemType', undefined, {
type: 'string',
@@ -74,8 +74,8 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
const SLIDE_TRANSITION_TIME_MS = 250;
const configurationKey = 'workbench.startupEditor';
export const allWalkthroughsHiddenContext = new RawContextKey('allWalkthroughsHidden', false);
export const inWelcomeContext = new RawContextKey('inWelcome', false);
export const allWalkthroughsHiddenContext = new RawContextKey<boolean>('allWalkthroughsHidden', false);
export const inWelcomeContext = new RawContextKey<boolean>('inWelcome', false);
export const embedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined);
export interface IWelcomePageStartEntry {
@@ -167,7 +167,7 @@ registerSingleton(IExtensionBisectService, ExtensionBisectService, true);
class ExtensionBisectUi {
static ctxIsBisectActive = new RawContextKey('isExtensionBisectActive', false);
static ctxIsBisectActive = new RawContextKey<boolean>('isExtensionBisectActive', false);
constructor(
@IContextKeyService contextKeyService: IContextKeyService,
@@ -113,7 +113,7 @@ suite('ViewContainerModel', () => {
assert.strictEqual(testObject.visibleViewDescriptors.length, 0, 'view should not appear since context isnt in');
assert.strictEqual(target.elements.length, 0);
const key = contextKeyService.createKey('showview1', false);
const key = contextKeyService.createKey<boolean>('showview1', false);
assert.strictEqual(testObject.visibleViewDescriptors.length, 0, 'view should still not appear since showview1 isnt true');
assert.strictEqual(target.elements.length, 0);
@@ -150,7 +150,7 @@ suite('ViewContainerModel', () => {
assert.deepStrictEqual(testObject.visibleViewDescriptors, [view1], 'only view1 should be visible');
assert.deepStrictEqual(target.elements, [view1], 'only view1 should be visible');
const key = contextKeyService.createKey('showview2', false);
const key = contextKeyService.createKey<boolean>('showview2', false);
assert.deepStrictEqual(testObject.visibleViewDescriptors, [view1], 'still only view1 should be visible');
assert.deepStrictEqual(target.elements, [view1], 'still only view1 should be visible');
@@ -173,7 +173,7 @@ suite('ViewContainerModel', () => {
assert.deepStrictEqual(testObject.visibleViewDescriptors, [view2], 'only view2 should be visible');
assert.deepStrictEqual(target.elements, [view2], 'only view2 should be visible');
const key = contextKeyService.createKey('showview1', false);
const key = contextKeyService.createKey<boolean>('showview1', false);
assert.deepStrictEqual(testObject.visibleViewDescriptors, [view2], 'still only view2 should be visible');
assert.deepStrictEqual(target.elements, [view2], 'still only view2 should be visible');
@@ -299,7 +299,7 @@ suite('ViewContainerModel', () => {
assert.strictEqual(testObject.visibleViewDescriptors.length, 0, 'view should not appear since context isnt in');
assert.strictEqual(target.elements.length, 0);
const key = contextKeyService.createKey('showview1', false);
const key = contextKeyService.createKey<boolean>('showview1', false);
assert.strictEqual(testObject.visibleViewDescriptors.length, 0, 'view should still not appear since showview1 isnt true');
assert.strictEqual(target.elements.length, 0);
@@ -340,7 +340,7 @@ suite('ViewContainerModel', () => {
assert.deepStrictEqual(testObject.visibleViewDescriptors, [view2], 'Only view2 should be visible');
assert.deepStrictEqual(target.elements, [view2]);
const key = contextKeyService.createKey('showview', false);
const key = contextKeyService.createKey<boolean>('showview', false);
assert.deepStrictEqual(testObject.visibleViewDescriptors, [view2], 'Only view2 should be visible');
assert.deepStrictEqual(target.elements, [view2]);
@@ -369,7 +369,7 @@ suite('ViewContainerModel', () => {
ViewsRegistry.registerViews([viewDescriptor], container);
const key = contextKeyService.createKey('showview1', true);
const key = contextKeyService.createKey<boolean>('showview1', true);
await new Promise(c => setTimeout(c, 30));
assert.strictEqual(testObject.visibleViewDescriptors.length, 1, 'view should appear after context is set');
assert.strictEqual(target.elements.length, 1);
@@ -397,7 +397,7 @@ suite('ViewContainerModel', () => {
canToggleVisibility: true
};
const key = contextKeyService.createKey('showview1', true);
const key = contextKeyService.createKey<boolean>('showview1', true);
key.set(false);
ViewsRegistry.registerViews([viewDescriptor], container);
@@ -424,7 +424,7 @@ suite('ViewContainerModel', () => {
canToggleVisibility: true
};
const key = contextKeyService.createKey('showview1', true);
const key = contextKeyService.createKey<boolean>('showview1', true);
key.set(false);
ViewsRegistry.registerViews([viewDescriptor], container);
@@ -451,7 +451,7 @@ suite('ViewContainerModel', () => {
canToggleVisibility: true
};
const key = contextKeyService.createKey('showview1', true);
const key = contextKeyService.createKey<boolean>('showview1', true);
key.set(false);
ViewsRegistry.registerViews([viewDescriptor], container);
@@ -533,7 +533,7 @@ suite('ViewContainerModel', () => {
canToggleVisibility: true
};
const key = contextKeyService.createKey('showview1', true);
const key = contextKeyService.createKey<boolean>('showview1', true);
key.set(false);
ViewsRegistry.registerViews([viewDescriptor], container);
testObject.setVisible('view1', false);
@@ -564,7 +564,7 @@ suite('ViewContainerModel', () => {
canToggleVisibility: true
};
const key = contextKeyService.createKey('showview1', true);
const key = contextKeyService.createKey<boolean>('showview1', true);
key.set(false);
ViewsRegistry.registerViews([viewDescriptor], container);