mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 2cfc8172e533e50c90e6a3152f6bfb1f82f963f3 (#6516)
* Merge from vscode 2cfc8172e533e50c90e6a3152f6bfb1f82f963f3 * fix tests
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IAccessibilityService, AccessibilitySupport, CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
export abstract class AbstractAccessibilityService extends Disposable implements IAccessibilityService {
|
||||
_serviceBrand: any;
|
||||
|
||||
private _accessibilityModeEnabledContext: IContextKey<boolean>;
|
||||
protected readonly _onDidChangeAccessibilitySupport = new Emitter<void>();
|
||||
readonly onDidChangeAccessibilitySupport: Event<void> = this._onDidChangeAccessibilitySupport.event;
|
||||
|
||||
constructor(
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
this._accessibilityModeEnabledContext = CONTEXT_ACCESSIBILITY_MODE_ENABLED.bindTo(this._contextKeyService);
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('editor.accessibilitySupport')) {
|
||||
this._updateContextKey();
|
||||
}
|
||||
}));
|
||||
this._updateContextKey();
|
||||
this.onDidChangeAccessibilitySupport(() => this._updateContextKey());
|
||||
}
|
||||
|
||||
abstract alwaysUnderlineAccessKeys(): Promise<boolean>;
|
||||
abstract getAccessibilitySupport(): AccessibilitySupport;
|
||||
abstract setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void;
|
||||
|
||||
private _updateContextKey(): void {
|
||||
const detected = this.getAccessibilitySupport() === AccessibilitySupport.Enabled;
|
||||
const config = this._configurationService.getValue('editor.accessibilitySupport');
|
||||
this._accessibilityModeEnabledContext.set(config === 'on' || (config === 'auto' && detected));
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
export const IAccessibilityService = createDecorator<IAccessibilityService>('accessibilityService');
|
||||
|
||||
@@ -28,3 +29,5 @@ export const enum AccessibilitySupport {
|
||||
|
||||
Enabled = 2
|
||||
}
|
||||
|
||||
export const CONTEXT_ACCESSIBILITY_MODE_ENABLED = new RawContextKey<boolean>('accessibilityModeEnabled', false);
|
||||
|
||||
@@ -4,17 +4,34 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IAccessibilityService, AccessibilitySupport, CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
export class BrowserAccessibilityService extends Disposable implements IAccessibilityService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private _accessibilitySupport = AccessibilitySupport.Unknown;
|
||||
private _accessibilityModeEnabledContext: IContextKey<boolean>;
|
||||
private readonly _onDidChangeAccessibilitySupport = new Emitter<void>();
|
||||
readonly onDidChangeAccessibilitySupport: Event<void> = this._onDidChangeAccessibilitySupport.event;
|
||||
|
||||
constructor(
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
this._accessibilityModeEnabledContext = CONTEXT_ACCESSIBILITY_MODE_ENABLED.bindTo(this._contextKeyService);
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('editor.accessibilitySupport')) {
|
||||
this._updateContextKey();
|
||||
}
|
||||
}));
|
||||
this._updateContextKey();
|
||||
}
|
||||
|
||||
alwaysUnderlineAccessKeys(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
@@ -26,9 +43,16 @@ export class BrowserAccessibilityService extends Disposable implements IAccessib
|
||||
|
||||
this._accessibilitySupport = accessibilitySupport;
|
||||
this._onDidChangeAccessibilitySupport.fire();
|
||||
this._updateContextKey();
|
||||
}
|
||||
|
||||
getAccessibilitySupport(): AccessibilitySupport {
|
||||
return this._accessibilitySupport;
|
||||
}
|
||||
|
||||
private _updateContextKey(): void {
|
||||
const detected = this.getAccessibilitySupport() === AccessibilitySupport.Enabled;
|
||||
const config = this._configurationService.getValue('editor.accessibilitySupport');
|
||||
this._accessibilityModeEnabledContext.set(config === 'on' || (config === 'auto' && detected));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IContextKeyService, ContextKeyDefinedExpr, ContextKeyExpr, ContextKeyAndExpr, ContextKeyEqualsExpr, RawContextKey, IContextKey, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextKeyService, ContextKeyExpr, RawContextKey, IContextKey, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { HistoryInputBox, IHistoryInputOptions } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { FindInput, IFindInputOptions } from 'vs/base/browser/ui/findinput/findInput';
|
||||
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
|
||||
@@ -66,7 +66,7 @@ export class ContextScopedFindInput extends FindInput {
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'history.showPrevious',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(new ContextKeyDefinedExpr(HistoryNavigationWidgetContext), new ContextKeyEqualsExpr(HistoryNavigationEnablementContext, true)),
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has(HistoryNavigationWidgetContext), ContextKeyExpr.equals(HistoryNavigationEnablementContext, true)),
|
||||
primary: KeyCode.UpArrow,
|
||||
secondary: [KeyMod.Alt | KeyCode.UpArrow],
|
||||
handler: (accessor, arg2) => {
|
||||
@@ -81,7 +81,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'history.showNext',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: new ContextKeyAndExpr([new ContextKeyDefinedExpr(HistoryNavigationWidgetContext), new ContextKeyEqualsExpr(HistoryNavigationEnablementContext, true)]),
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has(HistoryNavigationWidgetContext), ContextKeyExpr.equals(HistoryNavigationEnablementContext, true)),
|
||||
primary: KeyCode.DownArrow,
|
||||
secondary: [KeyMod.Alt | KeyCode.DownArrow],
|
||||
handler: (accessor, arg2) => {
|
||||
|
||||
@@ -15,11 +15,13 @@ export const ICommandService = createDecorator<ICommandService>('commandService'
|
||||
|
||||
export interface ICommandEvent {
|
||||
commandId: string;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export interface ICommandService {
|
||||
_serviceBrand: any;
|
||||
onWillExecuteCommand: Event<ICommandEvent>;
|
||||
onDidExecuteCommand: Event<ICommandEvent>;
|
||||
executeCommand<T = any>(commandId: string, ...args: any[]): Promise<T | undefined>;
|
||||
}
|
||||
|
||||
@@ -135,6 +137,7 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR
|
||||
export const NullCommandService: ICommandService = {
|
||||
_serviceBrand: undefined,
|
||||
onWillExecuteCommand: () => ({ dispose: () => { } }),
|
||||
onDidExecuteCommand: () => ({ dispose: () => { } }),
|
||||
executeCommand() {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,8 @@ suite('ConfigurationService - Node', () => {
|
||||
const service = new ConfigurationService(URI.file(res.testFile));
|
||||
await service.initialize();
|
||||
return new Promise((c, e) => {
|
||||
service.onDidChangeConfiguration(() => {
|
||||
const disposable = service.onDidChangeConfiguration(() => {
|
||||
disposable.dispose();
|
||||
assert.equal(service.getValue('foo'), 'bar');
|
||||
service.dispose();
|
||||
c();
|
||||
|
||||
@@ -14,10 +14,10 @@ export const enum ContextKeyExprType {
|
||||
NotEquals = 4,
|
||||
And = 5,
|
||||
Regex = 6,
|
||||
// {{SQL CARBON EDIT}}
|
||||
GreaterThanEquals = 7,
|
||||
LessThanEquals = 8
|
||||
//
|
||||
NotRegex = 7,
|
||||
Or = 8,
|
||||
GreaterThanEquals = 9, // {{SQL CARBON EDIT}} add value
|
||||
LessThanEquals = 10 // {{SQL CARBON EDIT}} add value
|
||||
}
|
||||
|
||||
export interface IContextKeyExprMapper {
|
||||
@@ -31,27 +31,31 @@ export interface IContextKeyExprMapper {
|
||||
export abstract class ContextKeyExpr {
|
||||
|
||||
public static has(key: string): ContextKeyExpr {
|
||||
return new ContextKeyDefinedExpr(key);
|
||||
return ContextKeyDefinedExpr.create(key);
|
||||
}
|
||||
|
||||
public static equals(key: string, value: any): ContextKeyExpr {
|
||||
return new ContextKeyEqualsExpr(key, value);
|
||||
return ContextKeyEqualsExpr.create(key, value);
|
||||
}
|
||||
|
||||
public static notEquals(key: string, value: any): ContextKeyExpr {
|
||||
return new ContextKeyNotEqualsExpr(key, value);
|
||||
return ContextKeyNotEqualsExpr.create(key, value);
|
||||
}
|
||||
|
||||
public static regex(key: string, value: RegExp): ContextKeyExpr {
|
||||
return new ContextKeyRegexExpr(key, value);
|
||||
return ContextKeyRegexExpr.create(key, value);
|
||||
}
|
||||
|
||||
public static not(key: string): ContextKeyExpr {
|
||||
return new ContextKeyNotExpr(key);
|
||||
return ContextKeyNotExpr.create(key);
|
||||
}
|
||||
|
||||
public static and(...expr: Array<ContextKeyExpr | undefined | null>): ContextKeyExpr {
|
||||
return new ContextKeyAndExpr(expr);
|
||||
public static and(...expr: Array<ContextKeyExpr | undefined | null>): ContextKeyExpr | undefined {
|
||||
return ContextKeyAndExpr.create(expr);
|
||||
}
|
||||
|
||||
public static or(...expr: Array<ContextKeyExpr | undefined | null>): ContextKeyExpr | undefined {
|
||||
return ContextKeyOrExpr.create(expr);
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
@@ -69,9 +73,17 @@ export abstract class ContextKeyExpr {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this._deserializeOrExpression(serialized, strict);
|
||||
}
|
||||
|
||||
private static _deserializeOrExpression(serialized: string, strict: boolean): ContextKeyExpr | undefined {
|
||||
let pieces = serialized.split('||');
|
||||
return ContextKeyOrExpr.create(pieces.map(p => this._deserializeAndExpression(p, strict)));
|
||||
}
|
||||
|
||||
private static _deserializeAndExpression(serialized: string, strict: boolean): ContextKeyExpr | undefined {
|
||||
let pieces = serialized.split('&&');
|
||||
let result = new ContextKeyAndExpr(pieces.map(p => this._deserializeOne(p, strict)));
|
||||
return result.normalize();
|
||||
return ContextKeyAndExpr.create(pieces.map(p => this._deserializeOne(p, strict)));
|
||||
}
|
||||
|
||||
private static _deserializeOne(serializedOne: string, strict: boolean): ContextKeyExpr {
|
||||
@@ -79,17 +91,17 @@ export abstract class ContextKeyExpr {
|
||||
|
||||
if (serializedOne.indexOf('!=') >= 0) {
|
||||
let pieces = serializedOne.split('!=');
|
||||
return new ContextKeyNotEqualsExpr(pieces[0].trim(), this._deserializeValue(pieces[1], strict));
|
||||
return ContextKeyNotEqualsExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict));
|
||||
}
|
||||
|
||||
if (serializedOne.indexOf('==') >= 0) {
|
||||
let pieces = serializedOne.split('==');
|
||||
return new ContextKeyEqualsExpr(pieces[0].trim(), this._deserializeValue(pieces[1], strict));
|
||||
return ContextKeyEqualsExpr.create(pieces[0].trim(), this._deserializeValue(pieces[1], strict));
|
||||
}
|
||||
|
||||
if (serializedOne.indexOf('=~') >= 0) {
|
||||
let pieces = serializedOne.split('=~');
|
||||
return new ContextKeyRegexExpr(pieces[0].trim(), this._deserializeRegexValue(pieces[1], strict));
|
||||
return ContextKeyRegexExpr.create(pieces[0].trim(), this._deserializeRegexValue(pieces[1], strict));
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
@@ -104,10 +116,10 @@ export abstract class ContextKeyExpr {
|
||||
//
|
||||
|
||||
if (/^\!\s*/.test(serializedOne)) {
|
||||
return new ContextKeyNotExpr(serializedOne.substr(1).trim());
|
||||
return ContextKeyNotExpr.create(serializedOne.substr(1).trim());
|
||||
}
|
||||
|
||||
return new ContextKeyDefinedExpr(serializedOne);
|
||||
return ContextKeyDefinedExpr.create(serializedOne);
|
||||
}
|
||||
|
||||
private static _deserializeValue(serializedValue: string, strict: boolean): any {
|
||||
@@ -168,10 +180,10 @@ export abstract class ContextKeyExpr {
|
||||
public abstract getType(): ContextKeyExprType;
|
||||
public abstract equals(other: ContextKeyExpr): boolean;
|
||||
public abstract evaluate(context: IContext): boolean;
|
||||
public abstract normalize(): ContextKeyExpr | undefined;
|
||||
public abstract serialize(): string;
|
||||
public abstract keys(): string[];
|
||||
public abstract map(mapFnc: IContextKeyExprMapper): ContextKeyExpr;
|
||||
public abstract negate(): ContextKeyExpr;
|
||||
}
|
||||
|
||||
function cmp(a: ContextKeyExpr, b: ContextKeyExpr): number {
|
||||
@@ -191,19 +203,25 @@ function cmp(a: ContextKeyExpr, b: ContextKeyExpr): number {
|
||||
return (<ContextKeyNotEqualsExpr>a).cmp(<ContextKeyNotEqualsExpr>b);
|
||||
case ContextKeyExprType.Regex:
|
||||
return (<ContextKeyRegexExpr>a).cmp(<ContextKeyRegexExpr>b);
|
||||
// {{SQL CARBON EDIT}}
|
||||
case ContextKeyExprType.GreaterThanEquals:
|
||||
case ContextKeyExprType.GreaterThanEquals: // {{SQL CARBON EDIT}} add case
|
||||
return (<ContextKeyGreaterThanEqualsExpr>a).cmp(<ContextKeyGreaterThanEqualsExpr>b);
|
||||
case ContextKeyExprType.LessThanEquals:
|
||||
case ContextKeyExprType.LessThanEquals: // {{SQL CARBON EDIT}} add case
|
||||
return (<ContextKeyLessThanEqualsExpr>a).cmp(<ContextKeyLessThanEqualsExpr>b);
|
||||
//
|
||||
case ContextKeyExprType.NotRegex:
|
||||
return (<ContextKeyNotRegexExpr>a).cmp(<ContextKeyNotRegexExpr>b);
|
||||
case ContextKeyExprType.And:
|
||||
return (<ContextKeyAndExpr>a).cmp(<ContextKeyAndExpr>b);
|
||||
default:
|
||||
throw new Error('Unknown ContextKeyExpr!');
|
||||
}
|
||||
}
|
||||
|
||||
export class ContextKeyDefinedExpr implements ContextKeyExpr {
|
||||
constructor(protected key: string) {
|
||||
public static create(key: string): ContextKeyExpr {
|
||||
return new ContextKeyDefinedExpr(key);
|
||||
}
|
||||
|
||||
protected constructor(protected key: string) {
|
||||
}
|
||||
|
||||
public getType(): ContextKeyExprType {
|
||||
@@ -231,10 +249,6 @@ export class ContextKeyDefinedExpr implements ContextKeyExpr {
|
||||
return (!!context.getValue(this.key));
|
||||
}
|
||||
|
||||
public normalize(): ContextKeyExpr {
|
||||
return this;
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
return this.key;
|
||||
}
|
||||
@@ -246,10 +260,25 @@ export class ContextKeyDefinedExpr implements ContextKeyExpr {
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr {
|
||||
return mapFnc.mapDefined(this.key);
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
return ContextKeyNotExpr.create(this.key);
|
||||
}
|
||||
}
|
||||
|
||||
export class ContextKeyEqualsExpr implements ContextKeyExpr {
|
||||
constructor(private readonly key: string, private readonly value: any) {
|
||||
|
||||
public static create(key: string, value: any): ContextKeyExpr {
|
||||
if (typeof value === 'boolean') {
|
||||
if (value) {
|
||||
return ContextKeyDefinedExpr.create(key);
|
||||
}
|
||||
return ContextKeyNotExpr.create(key);
|
||||
}
|
||||
return new ContextKeyEqualsExpr(key, value);
|
||||
}
|
||||
|
||||
private constructor(private readonly key: string, private readonly value: any) {
|
||||
}
|
||||
|
||||
public getType(): ContextKeyExprType {
|
||||
@@ -286,21 +315,7 @@ export class ContextKeyEqualsExpr implements ContextKeyExpr {
|
||||
/* tslint:enable:triple-equals */
|
||||
}
|
||||
|
||||
public normalize(): ContextKeyExpr {
|
||||
if (typeof this.value === 'boolean') {
|
||||
if (this.value) {
|
||||
return new ContextKeyDefinedExpr(this.key);
|
||||
}
|
||||
return new ContextKeyNotExpr(this.key);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
if (typeof this.value === 'boolean') {
|
||||
return this.normalize().serialize();
|
||||
}
|
||||
|
||||
return this.key + ' == \'' + this.value + '\'';
|
||||
}
|
||||
|
||||
@@ -311,10 +326,25 @@ export class ContextKeyEqualsExpr implements ContextKeyExpr {
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr {
|
||||
return mapFnc.mapEquals(this.key, this.value);
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
return ContextKeyNotEqualsExpr.create(this.key, this.value);
|
||||
}
|
||||
}
|
||||
|
||||
export class ContextKeyNotEqualsExpr implements ContextKeyExpr {
|
||||
constructor(private key: string, private value: any) {
|
||||
|
||||
public static create(key: string, value: any): ContextKeyExpr {
|
||||
if (typeof value === 'boolean') {
|
||||
if (value) {
|
||||
return ContextKeyNotExpr.create(key);
|
||||
}
|
||||
return ContextKeyDefinedExpr.create(key);
|
||||
}
|
||||
return new ContextKeyNotEqualsExpr(key, value);
|
||||
}
|
||||
|
||||
private constructor(private key: string, private value: any) {
|
||||
}
|
||||
|
||||
public getType(): ContextKeyExprType {
|
||||
@@ -351,21 +381,7 @@ export class ContextKeyNotEqualsExpr implements ContextKeyExpr {
|
||||
/* tslint:enable:triple-equals */
|
||||
}
|
||||
|
||||
public normalize(): ContextKeyExpr {
|
||||
if (typeof this.value === 'boolean') {
|
||||
if (this.value) {
|
||||
return new ContextKeyNotExpr(this.key);
|
||||
}
|
||||
return new ContextKeyDefinedExpr(this.key);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
if (typeof this.value === 'boolean') {
|
||||
return this.normalize().serialize();
|
||||
}
|
||||
|
||||
return this.key + ' != \'' + this.value + '\'';
|
||||
}
|
||||
|
||||
@@ -376,10 +392,19 @@ export class ContextKeyNotEqualsExpr implements ContextKeyExpr {
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr {
|
||||
return mapFnc.mapNotEquals(this.key, this.value);
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
return ContextKeyEqualsExpr.create(this.key, this.value);
|
||||
}
|
||||
}
|
||||
|
||||
export class ContextKeyNotExpr implements ContextKeyExpr {
|
||||
constructor(private key: string) {
|
||||
|
||||
public static create(key: string): ContextKeyExpr {
|
||||
return new ContextKeyNotExpr(key);
|
||||
}
|
||||
|
||||
private constructor(private key: string) {
|
||||
}
|
||||
|
||||
public getType(): ContextKeyExprType {
|
||||
@@ -407,10 +432,6 @@ export class ContextKeyNotExpr implements ContextKeyExpr {
|
||||
return (!context.getValue(this.key));
|
||||
}
|
||||
|
||||
public normalize(): ContextKeyExpr {
|
||||
return this;
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
return '!' + this.key;
|
||||
}
|
||||
@@ -422,11 +443,19 @@ export class ContextKeyNotExpr implements ContextKeyExpr {
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr {
|
||||
return mapFnc.mapNot(this.key);
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
return ContextKeyDefinedExpr.create(this.key);
|
||||
}
|
||||
}
|
||||
|
||||
export class ContextKeyRegexExpr implements ContextKeyExpr {
|
||||
|
||||
constructor(private key: string, private regexp: RegExp | null) {
|
||||
public static create(key: string, regexp: RegExp | null): ContextKeyExpr {
|
||||
return new ContextKeyRegexExpr(key, regexp);
|
||||
}
|
||||
|
||||
private constructor(private key: string, private regexp: RegExp | null) {
|
||||
//
|
||||
}
|
||||
|
||||
@@ -466,10 +495,6 @@ export class ContextKeyRegexExpr implements ContextKeyExpr {
|
||||
return this.regexp ? this.regexp.test(value) : false;
|
||||
}
|
||||
|
||||
public normalize(): ContextKeyExpr {
|
||||
return this;
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
const value = this.regexp
|
||||
? `/${this.regexp.source}/${this.regexp.ignoreCase ? 'i' : ''}`
|
||||
@@ -481,22 +506,99 @@ export class ContextKeyRegexExpr implements ContextKeyExpr {
|
||||
return [this.key];
|
||||
}
|
||||
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr {
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyRegexExpr {
|
||||
return mapFnc.mapRegex(this.key, this.regexp);
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
return ContextKeyNotRegexExpr.create(this);
|
||||
}
|
||||
}
|
||||
|
||||
export class ContextKeyNotRegexExpr implements ContextKeyExpr {
|
||||
|
||||
public static create(actual: ContextKeyRegexExpr): ContextKeyExpr {
|
||||
return new ContextKeyNotRegexExpr(actual);
|
||||
}
|
||||
|
||||
private constructor(private readonly _actual: ContextKeyRegexExpr) {
|
||||
//
|
||||
}
|
||||
|
||||
public getType(): ContextKeyExprType {
|
||||
return ContextKeyExprType.NotRegex;
|
||||
}
|
||||
|
||||
public cmp(other: ContextKeyNotRegexExpr): number {
|
||||
return this._actual.cmp(other._actual);
|
||||
}
|
||||
|
||||
public equals(other: ContextKeyExpr): boolean {
|
||||
if (other instanceof ContextKeyNotRegexExpr) {
|
||||
return this._actual.equals(other._actual);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public evaluate(context: IContext): boolean {
|
||||
return !this._actual.evaluate(context);
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public keys(): string[] {
|
||||
return this._actual.keys();
|
||||
}
|
||||
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr {
|
||||
return new ContextKeyNotRegexExpr(this._actual.map(mapFnc));
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
return this._actual;
|
||||
}
|
||||
}
|
||||
|
||||
export class ContextKeyAndExpr implements ContextKeyExpr {
|
||||
public readonly expr: ContextKeyExpr[];
|
||||
|
||||
constructor(expr: Array<ContextKeyExpr | null | undefined>) {
|
||||
this.expr = ContextKeyAndExpr._normalizeArr(expr);
|
||||
public static create(_expr: Array<ContextKeyExpr | null | undefined>): ContextKeyExpr | undefined {
|
||||
const expr = ContextKeyAndExpr._normalizeArr(_expr);
|
||||
if (expr.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (expr.length === 1) {
|
||||
return expr[0];
|
||||
}
|
||||
|
||||
return new ContextKeyAndExpr(expr);
|
||||
}
|
||||
|
||||
private constructor(public readonly expr: ContextKeyExpr[]) {
|
||||
}
|
||||
|
||||
public getType(): ContextKeyExprType {
|
||||
return ContextKeyExprType.And;
|
||||
}
|
||||
|
||||
public cmp(other: ContextKeyAndExpr): number {
|
||||
if (this.expr.length < other.expr.length) {
|
||||
return -1;
|
||||
}
|
||||
if (this.expr.length > other.expr.length) {
|
||||
return 1;
|
||||
}
|
||||
for (let i = 0, len = this.expr.length; i < len; i++) {
|
||||
const r = cmp(this.expr[i], other.expr[i]);
|
||||
if (r !== 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public equals(other: ContextKeyExpr): boolean {
|
||||
if (other instanceof ContextKeyAndExpr) {
|
||||
if (this.expr.length !== other.expr.length) {
|
||||
@@ -531,16 +633,16 @@ export class ContextKeyAndExpr implements ContextKeyExpr {
|
||||
continue;
|
||||
}
|
||||
|
||||
e = e.normalize();
|
||||
if (!e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e instanceof ContextKeyAndExpr) {
|
||||
expr = expr.concat(e.expr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e instanceof ContextKeyOrExpr) {
|
||||
// Not allowed, because we don't have parens!
|
||||
throw new Error(`It is not allowed to have an or expression here due to lack of parens!`);
|
||||
}
|
||||
|
||||
expr.push(e);
|
||||
}
|
||||
|
||||
@@ -550,29 +652,7 @@ export class ContextKeyAndExpr implements ContextKeyExpr {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public normalize(): ContextKeyExpr | undefined {
|
||||
if (this.expr.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (this.expr.length === 1) {
|
||||
return this.expr[0];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
if (this.expr.length === 0) {
|
||||
return '';
|
||||
}
|
||||
if (this.expr.length === 1) {
|
||||
const normalized = this.normalize();
|
||||
if (!normalized) {
|
||||
return '';
|
||||
}
|
||||
return normalized.serialize();
|
||||
}
|
||||
return this.expr.map(e => e.serialize()).join(' && ');
|
||||
}
|
||||
|
||||
@@ -587,6 +667,132 @@ export class ContextKeyAndExpr implements ContextKeyExpr {
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr {
|
||||
return new ContextKeyAndExpr(this.expr.map(expr => expr.map(mapFnc)));
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
let result: ContextKeyExpr[] = [];
|
||||
for (let expr of this.expr) {
|
||||
result.push(expr.negate());
|
||||
}
|
||||
return ContextKeyOrExpr.create(result)!;
|
||||
}
|
||||
}
|
||||
|
||||
export class ContextKeyOrExpr implements ContextKeyExpr {
|
||||
|
||||
public static create(_expr: Array<ContextKeyExpr | null | undefined>): ContextKeyExpr | undefined {
|
||||
const expr = ContextKeyOrExpr._normalizeArr(_expr);
|
||||
if (expr.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (expr.length === 1) {
|
||||
return expr[0];
|
||||
}
|
||||
|
||||
return new ContextKeyOrExpr(expr);
|
||||
}
|
||||
|
||||
private constructor(public readonly expr: ContextKeyExpr[]) {
|
||||
}
|
||||
|
||||
public getType(): ContextKeyExprType {
|
||||
return ContextKeyExprType.Or;
|
||||
}
|
||||
|
||||
public equals(other: ContextKeyExpr): boolean {
|
||||
if (other instanceof ContextKeyOrExpr) {
|
||||
if (this.expr.length !== other.expr.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0, len = this.expr.length; i < len; i++) {
|
||||
if (!this.expr[i].equals(other.expr[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public evaluate(context: IContext): boolean {
|
||||
for (let i = 0, len = this.expr.length; i < len; i++) {
|
||||
if (this.expr[i].evaluate(context)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static _normalizeArr(arr: Array<ContextKeyExpr | null | undefined>): ContextKeyExpr[] {
|
||||
let expr: ContextKeyExpr[] = [];
|
||||
|
||||
if (arr) {
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
let e: ContextKeyExpr | null | undefined = arr[i];
|
||||
if (!e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e instanceof ContextKeyOrExpr) {
|
||||
expr = expr.concat(e.expr);
|
||||
continue;
|
||||
}
|
||||
|
||||
expr.push(e);
|
||||
}
|
||||
|
||||
expr.sort(cmp);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
return this.expr.map(e => e.serialize()).join(' || ');
|
||||
}
|
||||
|
||||
public keys(): string[] {
|
||||
const result: string[] = [];
|
||||
for (let expr of this.expr) {
|
||||
result.push(...expr.keys());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public map(mapFnc: IContextKeyExprMapper): ContextKeyExpr {
|
||||
return new ContextKeyOrExpr(this.expr.map(expr => expr.map(mapFnc)));
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
let result: ContextKeyExpr[] = [];
|
||||
for (let expr of this.expr) {
|
||||
result.push(expr.negate());
|
||||
}
|
||||
|
||||
const terminals = (node: ContextKeyExpr) => {
|
||||
if (node instanceof ContextKeyOrExpr) {
|
||||
return node.expr;
|
||||
}
|
||||
return [node];
|
||||
};
|
||||
|
||||
// We don't support parens, so here we distribute the AND over the OR terminals
|
||||
// We always take the first 2 AND pairs and distribute them
|
||||
while (result.length > 1) {
|
||||
const LEFT = result.shift()!;
|
||||
const RIGHT = result.shift()!;
|
||||
|
||||
const all: ContextKeyExpr[] = [];
|
||||
for (const left of terminals(LEFT)) {
|
||||
for (const right of terminals(RIGHT)) {
|
||||
all.push(ContextKeyExpr.and(left, right)!);
|
||||
}
|
||||
}
|
||||
result.unshift(ContextKeyExpr.or(...all)!);
|
||||
}
|
||||
|
||||
return result[0];
|
||||
}
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
@@ -621,6 +827,10 @@ export class ContextKeyGreaterThanEqualsExpr implements ContextKeyExpr {
|
||||
return false;
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
throw new Error('Method not implemented.'); // @TODO anthonydresser need to figure out what to do in this case
|
||||
}
|
||||
|
||||
public evaluate(context: IContext): boolean {
|
||||
const keyVal = context.getValue<string>(this.key);
|
||||
if (!keyVal) {
|
||||
@@ -694,6 +904,10 @@ export class ContextKeyLessThanEqualsExpr implements ContextKeyExpr {
|
||||
return this;
|
||||
}
|
||||
|
||||
public negate(): ContextKeyExpr {
|
||||
throw new Error('Method not implemented.'); // @TODO anthonydresser need to figure out what to do in this case
|
||||
}
|
||||
|
||||
public serialize(): string {
|
||||
return this.key + ' <= \'' + this.value + '\'';
|
||||
}
|
||||
|
||||
@@ -27,31 +27,28 @@ suite('ContextKeyExpr', () => {
|
||||
ContextKeyExpr.notEquals('c2', 'cc2'),
|
||||
ContextKeyExpr.not('d1'),
|
||||
ContextKeyExpr.not('d2'),
|
||||
// {{SQL CARBON EDIT}}
|
||||
ContextKeyExpr.greaterThanEquals('e1', 'ee1'),
|
||||
ContextKeyExpr.greaterThanEquals('e2', 'ee2'),
|
||||
ContextKeyExpr.lessThanEquals('f1', 'ff1'),
|
||||
ContextKeyExpr.lessThanEquals('f2', 'ff2')
|
||||
//
|
||||
);
|
||||
ContextKeyExpr.greaterThanEquals('e1', 'ee1'), // {{SQL CARBON EDIT}} add test case
|
||||
ContextKeyExpr.greaterThanEquals('e2', 'ee2'), // {{SQL CARBON EDIT}} add test case
|
||||
ContextKeyExpr.lessThanEquals('f1', 'ff1'), // {{SQL CARBON EDIT}} add test case
|
||||
ContextKeyExpr.lessThanEquals('f2', 'ff2'), // {{SQL CARBON EDIT}} add test case
|
||||
)!;
|
||||
let b = ContextKeyExpr.and(
|
||||
// {{SQL CARBON EDIT}}
|
||||
ContextKeyExpr.greaterThanEquals('e2', 'ee2'),
|
||||
ContextKeyExpr.lessThanEquals('f1', 'ff1'), // {{SQL CARBON EDIT}}
|
||||
ContextKeyExpr.lessThanEquals('f2', 'ff2'), // {{SQL CARBON EDIT}}
|
||||
ContextKeyExpr.greaterThanEquals('e2', 'ee2'), // {{SQL CARBON EDIT}}
|
||||
ContextKeyExpr.greaterThanEquals('e1', 'ee1'), // {{SQL CARBON EDIT}}
|
||||
ContextKeyExpr.equals('b2', 'bb2'),
|
||||
ContextKeyExpr.notEquals('c1', 'cc1'),
|
||||
ContextKeyExpr.not('d1'),
|
||||
ContextKeyExpr.lessThanEquals('f1', 'ff1'),
|
||||
ContextKeyExpr.regex('d4', /\*\*3*/),
|
||||
ContextKeyExpr.greaterThanEquals('e1', 'ee1'),
|
||||
ContextKeyExpr.notEquals('c2', 'cc2'),
|
||||
ContextKeyExpr.has('a2'),
|
||||
ContextKeyExpr.equals('b1', 'bb1'),
|
||||
ContextKeyExpr.regex('d3', /d.*/),
|
||||
ContextKeyExpr.has('a1'),
|
||||
ContextKeyExpr.lessThanEquals('f2', 'ff2'),
|
||||
ContextKeyExpr.and(ContextKeyExpr.equals('and.a', true)),
|
||||
ContextKeyExpr.not('d2')
|
||||
);
|
||||
)!;
|
||||
assert(a.equals(b), 'expressions should be equal');
|
||||
});
|
||||
|
||||
@@ -61,10 +58,10 @@ suite('ContextKeyExpr', () => {
|
||||
let key1IsFalse = ContextKeyExpr.equals('key1', false);
|
||||
let key1IsNotTrue = ContextKeyExpr.notEquals('key1', true);
|
||||
|
||||
assert.ok(key1IsTrue.normalize()!.equals(ContextKeyExpr.has('key1')));
|
||||
assert.ok(key1IsNotFalse.normalize()!.equals(ContextKeyExpr.has('key1')));
|
||||
assert.ok(key1IsFalse.normalize()!.equals(ContextKeyExpr.not('key1')));
|
||||
assert.ok(key1IsNotTrue.normalize()!.equals(ContextKeyExpr.not('key1')));
|
||||
assert.ok(key1IsTrue.equals(ContextKeyExpr.has('key1')));
|
||||
assert.ok(key1IsNotFalse.equals(ContextKeyExpr.has('key1')));
|
||||
assert.ok(key1IsFalse.equals(ContextKeyExpr.not('key1')));
|
||||
assert.ok(key1IsNotTrue.equals(ContextKeyExpr.not('key1')));
|
||||
});
|
||||
|
||||
test('evaluate', () => {
|
||||
@@ -108,5 +105,24 @@ suite('ContextKeyExpr', () => {
|
||||
testExpression('a && !b && c == 5', true && !false && '5' == '5');
|
||||
testExpression('d =~ /e.*/', false);
|
||||
/* tslint:enable:triple-equals */
|
||||
|
||||
// precedence test: false && true || true === true because && is evaluated first
|
||||
testExpression('b && a || a', true);
|
||||
|
||||
testExpression('a || b', true);
|
||||
testExpression('b || b', false);
|
||||
testExpression('b && a || a && b', false);
|
||||
});
|
||||
|
||||
test('negate', () => {
|
||||
function testNegate(expr: string, expected: string): void {
|
||||
const actual = ContextKeyExpr.deserialize(expr)!.negate().serialize();
|
||||
assert.strictEqual(actual, expected);
|
||||
}
|
||||
testNegate('a', '!a');
|
||||
testNegate('a && b || c', '!a && !c || !b && !c');
|
||||
testNegate('a && b || c || d', '!a && !c && !d || !b && !c && !d');
|
||||
testNegate('!a && !b || !c && !d', 'a && c || a && d || b && c || b && d');
|
||||
testNegate('!a && !b || !c && !d || !e && !f', 'a && c && e || a && c && f || a && d && e || a && d && f || b && c && e || b && c && f || b && d && e || b && d && f');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -206,7 +206,7 @@ class WindowDriver implements IWindowDriver {
|
||||
throw new Error(`Xterm not found: ${selector}`);
|
||||
}
|
||||
|
||||
xterm._core.handler(text);
|
||||
xterm._core._coreService.triggerDataEvent(text);
|
||||
}
|
||||
|
||||
async openDevTools(): Promise<void> {
|
||||
|
||||
@@ -47,6 +47,7 @@ export interface ParsedArgs {
|
||||
'disable-extension'?: string | string[];
|
||||
'list-extensions'?: boolean;
|
||||
'show-versions'?: boolean;
|
||||
'category'?: string;
|
||||
'install-extension'?: string | string[];
|
||||
'uninstall-extension'?: string | string[];
|
||||
'locate-extension'?: string | string[];
|
||||
|
||||
@@ -48,6 +48,7 @@ export const options: Option[] = [
|
||||
{ id: 'extensions-dir', type: 'string', deprecates: 'extensionHomePath', cat: 'e', args: 'dir', description: localize('extensionHomePath', "Set the root path for extensions.") },
|
||||
{ id: 'list-extensions', type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") },
|
||||
{ id: 'show-versions', type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") },
|
||||
{ id: 'category', type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") },
|
||||
{ id: 'install-extension', type: 'string', cat: 'e', args: 'extension-id | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. Use `--force` argument to avoid prompts.") },
|
||||
{ id: 'uninstall-extension', type: 'string', cat: 'e', args: 'extension-id', description: localize('uninstallExtension', "Uninstalls an extension.") },
|
||||
{ id: 'enable-proposed-api', type: 'string', cat: 'e', args: 'extension-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") },
|
||||
|
||||
@@ -27,6 +27,7 @@ import { joinPath } from 'vs/base/common/resources';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IProductService } from 'vs/platform/product/common/product';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { optional } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
interface IRawGalleryExtensionFile {
|
||||
assetType: string;
|
||||
@@ -389,7 +390,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@optional(IStorageService) private readonly storageService: IStorageService,
|
||||
) {
|
||||
const config = productService.extensionsGallery;
|
||||
this.extensionsGalleryUrl = config && config.serviceUrl;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyAndExpr, ContextKeyExpr, IContext } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ContextKeyExpr, IContext, ContextKeyOrExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
|
||||
@@ -171,7 +171,6 @@ export class KeybindingResolver {
|
||||
|
||||
/**
|
||||
* Returns true if it is provable `a` implies `b`.
|
||||
* **Precondition**: Assumes `a` and `b` are normalized!
|
||||
*/
|
||||
public static whenIsEntirelyIncluded(a: ContextKeyExpr | null | undefined, b: ContextKeyExpr | null | undefined): boolean {
|
||||
if (!b) {
|
||||
@@ -181,26 +180,35 @@ export class KeybindingResolver {
|
||||
return false;
|
||||
}
|
||||
|
||||
const aExpressions: ContextKeyExpr[] = ((a instanceof ContextKeyAndExpr) ? a.expr : [a]);
|
||||
const bExpressions: ContextKeyExpr[] = ((b instanceof ContextKeyAndExpr) ? b.expr : [b]);
|
||||
return this._implies(a, b);
|
||||
}
|
||||
|
||||
let aIndex = 0;
|
||||
for (const bExpr of bExpressions) {
|
||||
let bExprMatched = false;
|
||||
while (!bExprMatched && aIndex < aExpressions.length) {
|
||||
let aExpr = aExpressions[aIndex];
|
||||
if (aExpr.equals(bExpr)) {
|
||||
bExprMatched = true;
|
||||
}
|
||||
aIndex++;
|
||||
/**
|
||||
* Returns true if it is provable `p` implies `q`.
|
||||
*/
|
||||
private static _implies(p: ContextKeyExpr, q: ContextKeyExpr): boolean {
|
||||
const notP = p.negate();
|
||||
|
||||
const terminals = (node: ContextKeyExpr) => {
|
||||
if (node instanceof ContextKeyOrExpr) {
|
||||
return node.expr;
|
||||
}
|
||||
return [node];
|
||||
};
|
||||
|
||||
if (!bExprMatched) {
|
||||
return false;
|
||||
let expr = terminals(notP).concat(terminals(q));
|
||||
for (let i = 0; i < expr.length; i++) {
|
||||
const a = expr[i];
|
||||
const notA = a.negate();
|
||||
for (let j = i + 1; j < expr.length; j++) {
|
||||
const b = expr[j];
|
||||
if (notA.equals(b)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public getDefaultBoundCommands(): Map<string, boolean> {
|
||||
|
||||
@@ -121,6 +121,7 @@ suite('AbstractKeybindingService', () => {
|
||||
let commandService: ICommandService = {
|
||||
_serviceBrand: undefined,
|
||||
onWillExecuteCommand: () => ({ dispose: () => { } }),
|
||||
onDidExecuteCommand: () => ({ dispose: () => { } }),
|
||||
executeCommand: (commandId: string, ...args: any[]): Promise<any> => {
|
||||
executeCommandCalls.push({
|
||||
commandId: commandId,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { KeyChord, KeyCode, KeyMod, SimpleKeybinding, createKeybinding, createSimpleKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import { ContextKeyAndExpr, ContextKeyExpr, IContext } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ContextKeyExpr, IContext } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
@@ -20,13 +20,13 @@ function createContext(ctx: any) {
|
||||
|
||||
suite('KeybindingResolver', () => {
|
||||
|
||||
function kbItem(keybinding: number, command: string, commandArgs: any, when: ContextKeyExpr, isDefault: boolean): ResolvedKeybindingItem {
|
||||
function kbItem(keybinding: number, command: string, commandArgs: any, when: ContextKeyExpr | undefined, isDefault: boolean): ResolvedKeybindingItem {
|
||||
const resolvedKeybinding = (keybinding !== 0 ? new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS)!, OS) : undefined);
|
||||
return new ResolvedKeybindingItem(
|
||||
resolvedKeybinding,
|
||||
command,
|
||||
commandArgs,
|
||||
when ? when.normalize() : undefined,
|
||||
when,
|
||||
isDefault
|
||||
);
|
||||
}
|
||||
@@ -191,64 +191,41 @@ suite('KeybindingResolver', () => {
|
||||
});
|
||||
|
||||
test('contextIsEntirelyIncluded', () => {
|
||||
let assertIsIncluded = (a: ContextKeyExpr[], b: ContextKeyExpr[]) => {
|
||||
let tmpA = new ContextKeyAndExpr(a).normalize();
|
||||
let tmpB = new ContextKeyAndExpr(b).normalize();
|
||||
assert.equal(KeybindingResolver.whenIsEntirelyIncluded(tmpA, tmpB), true);
|
||||
const assertIsIncluded = (a: string | null, b: string | null) => {
|
||||
assert.equal(KeybindingResolver.whenIsEntirelyIncluded(ContextKeyExpr.deserialize(a), ContextKeyExpr.deserialize(b)), true);
|
||||
};
|
||||
let assertIsNotIncluded = (a: ContextKeyExpr[], b: ContextKeyExpr[]) => {
|
||||
let tmpA = new ContextKeyAndExpr(a).normalize();
|
||||
let tmpB = new ContextKeyAndExpr(b).normalize();
|
||||
assert.equal(KeybindingResolver.whenIsEntirelyIncluded(tmpA, tmpB), false);
|
||||
const assertIsNotIncluded = (a: string | null, b: string | null) => {
|
||||
assert.equal(KeybindingResolver.whenIsEntirelyIncluded(ContextKeyExpr.deserialize(a), ContextKeyExpr.deserialize(b)), false);
|
||||
};
|
||||
let key1IsTrue = ContextKeyExpr.equals('key1', true);
|
||||
let key1IsNotFalse = ContextKeyExpr.notEquals('key1', false);
|
||||
let key1IsFalse = ContextKeyExpr.equals('key1', false);
|
||||
let key1IsNotTrue = ContextKeyExpr.notEquals('key1', true);
|
||||
let key2IsTrue = ContextKeyExpr.equals('key2', true);
|
||||
let key2IsNotFalse = ContextKeyExpr.notEquals('key2', false);
|
||||
let key3IsTrue = ContextKeyExpr.equals('key3', true);
|
||||
let key4IsTrue = ContextKeyExpr.equals('key4', true);
|
||||
|
||||
assertIsIncluded([key1IsTrue], null!);
|
||||
assertIsIncluded([key1IsTrue], []);
|
||||
assertIsIncluded([key1IsTrue], [key1IsTrue]);
|
||||
assertIsIncluded([key1IsTrue], [key1IsNotFalse]);
|
||||
assertIsIncluded('key1', null);
|
||||
assertIsIncluded('key1', '');
|
||||
assertIsIncluded('key1', 'key1');
|
||||
assertIsIncluded('!key1', '');
|
||||
assertIsIncluded('!key1', '!key1');
|
||||
assertIsIncluded('key2', '');
|
||||
assertIsIncluded('key2', 'key2');
|
||||
assertIsIncluded('key1 && key1 && key2 && key2', 'key2');
|
||||
assertIsIncluded('key1 && key2', 'key2');
|
||||
assertIsIncluded('key1 && key2', 'key1');
|
||||
assertIsIncluded('key1 && key2', '');
|
||||
assertIsIncluded('key1', 'key1 || key2');
|
||||
assertIsIncluded('key1 || !key1', 'key2 || !key2');
|
||||
assertIsIncluded('key1', 'key1 || key2 && key3');
|
||||
|
||||
assertIsIncluded([key1IsFalse], []);
|
||||
assertIsIncluded([key1IsFalse], [key1IsFalse]);
|
||||
assertIsIncluded([key1IsFalse], [key1IsNotTrue]);
|
||||
|
||||
assertIsIncluded([key2IsNotFalse], []);
|
||||
assertIsIncluded([key2IsNotFalse], [key2IsNotFalse]);
|
||||
assertIsIncluded([key2IsNotFalse], [key2IsTrue]);
|
||||
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key2IsTrue]);
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key2IsNotFalse]);
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key1IsTrue]);
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], [key1IsNotFalse]);
|
||||
assertIsIncluded([key1IsTrue, key2IsNotFalse], []);
|
||||
|
||||
assertIsNotIncluded([key1IsTrue], [key1IsFalse]);
|
||||
assertIsNotIncluded([key1IsTrue], [key1IsNotTrue]);
|
||||
assertIsNotIncluded([key1IsNotFalse], [key1IsFalse]);
|
||||
assertIsNotIncluded([key1IsNotFalse], [key1IsNotTrue]);
|
||||
|
||||
assertIsNotIncluded([key1IsFalse], [key1IsTrue]);
|
||||
assertIsNotIncluded([key1IsFalse], [key1IsNotFalse]);
|
||||
assertIsNotIncluded([key1IsNotTrue], [key1IsTrue]);
|
||||
assertIsNotIncluded([key1IsNotTrue], [key1IsNotFalse]);
|
||||
|
||||
assertIsNotIncluded([key1IsTrue, key2IsNotFalse], [key3IsTrue]);
|
||||
assertIsNotIncluded([key1IsTrue, key2IsNotFalse], [key4IsTrue]);
|
||||
assertIsNotIncluded([key1IsTrue], [key2IsTrue]);
|
||||
assertIsNotIncluded([], [key2IsTrue]);
|
||||
assertIsNotIncluded(null!, [key2IsTrue]);
|
||||
assertIsNotIncluded('key1', '!key1');
|
||||
assertIsNotIncluded('!key1', 'key1');
|
||||
assertIsNotIncluded('key1 && key2', 'key3');
|
||||
assertIsNotIncluded('key1 && key2', 'key4');
|
||||
assertIsNotIncluded('key1', 'key2');
|
||||
assertIsNotIncluded('key1 || key2', 'key2');
|
||||
assertIsNotIncluded('', 'key2');
|
||||
assertIsNotIncluded(null, 'key2');
|
||||
});
|
||||
|
||||
test('resolve command', function () {
|
||||
|
||||
function _kbItem(keybinding: number, command: string, when: ContextKeyExpr): ResolvedKeybindingItem {
|
||||
function _kbItem(keybinding: number, command: string, when: ContextKeyExpr | undefined): ResolvedKeybindingItem {
|
||||
return kbItem(keybinding, command, null, when, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ export class WorkbenchList<T> extends List<T> {
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
delegate: IListVirtualDelegate<T>,
|
||||
renderers: IListRenderer<any /* TODO@joao */, any>[],
|
||||
renderers: IListRenderer<T, any>[],
|
||||
options: IListOptions<T>,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IListService listService: IListService,
|
||||
@@ -787,7 +787,7 @@ export class WorkbenchObjectTree<T extends NonNullable<any>, TFilterData = void>
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
delegate: IListVirtualDelegate<T>,
|
||||
renderers: ITreeRenderer<any /* TODO@joao */, TFilterData, any>[],
|
||||
renderers: ITreeRenderer<T, TFilterData, any>[],
|
||||
options: IObjectTreeOptions<T, TFilterData>,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IListService listService: IListService,
|
||||
@@ -813,7 +813,7 @@ export class WorkbenchDataTree<TInput, T, TFilterData = void> extends DataTree<T
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
delegate: IListVirtualDelegate<T>,
|
||||
renderers: ITreeRenderer<any /* TODO@joao */, TFilterData, any>[],
|
||||
renderers: ITreeRenderer<T, TFilterData, any>[],
|
||||
dataSource: IDataSource<TInput, T>,
|
||||
options: IDataTreeOptions<T, TFilterData>,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@@ -840,7 +840,7 @@ export class WorkbenchAsyncDataTree<TInput, T, TFilterData = void> extends Async
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
delegate: IListVirtualDelegate<T>,
|
||||
renderers: ITreeRenderer<any /* TODO@joao */, TFilterData, any>[],
|
||||
renderers: ITreeRenderer<T, TFilterData, any>[],
|
||||
dataSource: IAsyncDataSource<TInput, T>,
|
||||
options: IAsyncDataTreeOptions<T, TFilterData>,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
|
||||
@@ -39,6 +39,7 @@ export interface IRelatedInformation {
|
||||
|
||||
export const enum MarkerTag {
|
||||
Unnecessary = 1,
|
||||
Deprecated = 2
|
||||
}
|
||||
|
||||
export enum MarkerSeverity {
|
||||
|
||||
@@ -73,10 +73,9 @@ export interface IProductConfiguration {
|
||||
readonly recommendationsUrl: string;
|
||||
};
|
||||
extensionTips: { [id: string]: string; };
|
||||
// {{SQL CARBON EDIT}}
|
||||
recommendedExtensions: string[];
|
||||
extensionImportantTips: { [id: string]: { name: string; pattern: string; }; };
|
||||
readonly exeBasedExtensionTips: { [id: string]: { friendlyName: string, windowsPath?: string, recommendations: readonly string[] }; };
|
||||
recommendedExtensions: string[]; // {{SQL CARBON EDIT}}
|
||||
extensionImportantTips: { [id: string]: { name: string; pattern: string; isExtensionPack?: boolean }; };
|
||||
readonly exeBasedExtensionTips: { [id: string]: IExeBasedExtensionTip; };
|
||||
readonly extensionKeywords: { [extension: string]: readonly string[]; };
|
||||
readonly extensionAllowedBadgeProviders: readonly string[];
|
||||
readonly extensionAllowedProposedApi: readonly string[];
|
||||
@@ -125,6 +124,14 @@ export interface IProductConfiguration {
|
||||
readonly uiExtensions?: readonly string[];
|
||||
}
|
||||
|
||||
export interface IExeBasedExtensionTip {
|
||||
friendlyName: string;
|
||||
windowsPath?: string;
|
||||
recommendations: readonly string[];
|
||||
important?: boolean;
|
||||
exeFriendlyName?: string;
|
||||
}
|
||||
|
||||
export interface ISurveyData {
|
||||
surveyId: string;
|
||||
surveyUrl: string;
|
||||
|
||||
146
src/vs/platform/remote/browser/browserSocketFactory.ts
Normal file
146
src/vs/platform/remote/browser/browserSocketFactory.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ISocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { ISocket } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
|
||||
export interface IWebSocketFactory {
|
||||
create(url: string): IWebSocket;
|
||||
}
|
||||
|
||||
export interface IWebSocket {
|
||||
readonly onData: Event<ArrayBuffer>;
|
||||
readonly onOpen: Event<void>;
|
||||
readonly onClose: Event<void>;
|
||||
readonly onError: Event<any>;
|
||||
|
||||
send(data: ArrayBuffer | ArrayBufferView): void;
|
||||
close(): void;
|
||||
}
|
||||
|
||||
class BrowserWebSocket implements IWebSocket {
|
||||
|
||||
private readonly _onData = new Emitter<ArrayBuffer>();
|
||||
public readonly onData = this._onData.event;
|
||||
|
||||
public readonly onOpen: Event<void>;
|
||||
public readonly onClose: Event<void>;
|
||||
public readonly onError: Event<any>;
|
||||
|
||||
private readonly _socket: WebSocket;
|
||||
private readonly _fileReader: FileReader;
|
||||
private readonly _queue: Blob[];
|
||||
private _isReading: boolean;
|
||||
|
||||
private readonly _socketMessageListener: (ev: MessageEvent) => void;
|
||||
|
||||
constructor(socket: WebSocket) {
|
||||
this._socket = socket;
|
||||
this._fileReader = new FileReader();
|
||||
this._queue = [];
|
||||
this._isReading = false;
|
||||
|
||||
this._fileReader.onload = (event) => {
|
||||
this._isReading = false;
|
||||
const buff = <ArrayBuffer>(<any>event.target).result;
|
||||
|
||||
this._onData.fire(buff);
|
||||
|
||||
if (this._queue.length > 0) {
|
||||
enqueue(this._queue.shift()!);
|
||||
}
|
||||
};
|
||||
|
||||
const enqueue = (blob: Blob) => {
|
||||
if (this._isReading) {
|
||||
this._queue.push(blob);
|
||||
return;
|
||||
}
|
||||
this._isReading = true;
|
||||
this._fileReader.readAsArrayBuffer(blob);
|
||||
};
|
||||
|
||||
this._socketMessageListener = (ev: MessageEvent) => {
|
||||
enqueue(<Blob>ev.data);
|
||||
};
|
||||
this._socket.addEventListener('message', this._socketMessageListener);
|
||||
|
||||
this.onOpen = Event.fromDOMEventEmitter(this._socket, 'open');
|
||||
this.onClose = Event.fromDOMEventEmitter(this._socket, 'close');
|
||||
this.onError = Event.fromDOMEventEmitter(this._socket, 'error');
|
||||
}
|
||||
|
||||
send(data: ArrayBuffer | ArrayBufferView): void {
|
||||
this._socket.send(data);
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this._socket.close();
|
||||
this._socket.removeEventListener('message', this._socketMessageListener);
|
||||
}
|
||||
}
|
||||
|
||||
export const defaultWebSocketFactory = new class implements IWebSocketFactory {
|
||||
create(url: string): IWebSocket {
|
||||
return new BrowserWebSocket(new WebSocket(url));
|
||||
}
|
||||
};
|
||||
|
||||
class BrowserSocket implements ISocket {
|
||||
public readonly socket: IWebSocket;
|
||||
|
||||
constructor(socket: IWebSocket) {
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.socket.close();
|
||||
}
|
||||
|
||||
public onData(listener: (e: VSBuffer) => void): IDisposable {
|
||||
return this.socket.onData((data) => listener(VSBuffer.wrap(new Uint8Array(data))));
|
||||
}
|
||||
|
||||
public onClose(listener: () => void): IDisposable {
|
||||
return this.socket.onClose(listener);
|
||||
}
|
||||
|
||||
public onEnd(listener: () => void): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
public write(buffer: VSBuffer): void {
|
||||
this.socket.send(buffer.buffer);
|
||||
}
|
||||
|
||||
public end(): void {
|
||||
this.socket.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export class BrowserSocketFactory implements ISocketFactory {
|
||||
private readonly _webSocketFactory: IWebSocketFactory;
|
||||
|
||||
constructor(webSocketFactory: IWebSocketFactory | null | undefined) {
|
||||
this._webSocketFactory = webSocketFactory || defaultWebSocketFactory;
|
||||
}
|
||||
|
||||
connect(host: string, port: number, query: string, callback: IConnectCallback): void {
|
||||
const socket = this._webSocketFactory.create(`ws://${host}:${port}/?${query}&skipWebSocketFrames=false`);
|
||||
const errorListener = socket.onError((err) => callback(err, undefined));
|
||||
socket.onOpen(() => {
|
||||
errorListener.dispose();
|
||||
callback(undefined, new BrowserSocket(socket));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IWebSocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { ISocket } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
|
||||
class BrowserSocket implements ISocket {
|
||||
public readonly socket: WebSocket;
|
||||
|
||||
constructor(socket: WebSocket) {
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.socket.close();
|
||||
}
|
||||
|
||||
public onData(_listener: (e: VSBuffer) => void): IDisposable {
|
||||
const fileReader = new FileReader();
|
||||
const queue: Blob[] = [];
|
||||
let isReading = false;
|
||||
fileReader.onload = function (event) {
|
||||
isReading = false;
|
||||
const buff = <ArrayBuffer>(<any>event.target).result;
|
||||
|
||||
try {
|
||||
_listener(VSBuffer.wrap(new Uint8Array(buff)));
|
||||
} catch (err) {
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
|
||||
if (queue.length > 0) {
|
||||
enqueue(queue.shift()!);
|
||||
}
|
||||
};
|
||||
const enqueue = (blob: Blob) => {
|
||||
if (isReading) {
|
||||
queue.push(blob);
|
||||
return;
|
||||
}
|
||||
isReading = true;
|
||||
fileReader.readAsArrayBuffer(blob);
|
||||
};
|
||||
const listener = (e: MessageEvent) => {
|
||||
enqueue(<Blob>e.data);
|
||||
};
|
||||
this.socket.addEventListener('message', listener);
|
||||
return {
|
||||
dispose: () => this.socket.removeEventListener('message', listener)
|
||||
};
|
||||
}
|
||||
|
||||
public onClose(listener: () => void): IDisposable {
|
||||
this.socket.addEventListener('close', listener);
|
||||
return {
|
||||
dispose: () => this.socket.removeEventListener('close', listener)
|
||||
};
|
||||
}
|
||||
|
||||
public onEnd(listener: () => void): IDisposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
|
||||
public write(buffer: VSBuffer): void {
|
||||
this.socket.send(buffer.buffer);
|
||||
}
|
||||
|
||||
public end(): void {
|
||||
this.socket.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const browserWebSocketFactory = new class implements IWebSocketFactory {
|
||||
connect(host: string, port: number, query: string, callback: IConnectCallback): void {
|
||||
const errorListener = (err: any) => callback(err, undefined);
|
||||
const socket = new WebSocket(`ws://${host}:${port}/?${query}&skipWebSocketFrames=false`);
|
||||
socket.onopen = function (event) {
|
||||
socket.removeEventListener('error', errorListener);
|
||||
callback(undefined, new BrowserSocket(socket));
|
||||
};
|
||||
socket.addEventListener('error', errorListener);
|
||||
}
|
||||
};
|
||||
@@ -57,7 +57,7 @@ interface ISimpleConnectionOptions {
|
||||
port: number;
|
||||
reconnectionToken: string;
|
||||
reconnectionProtocol: PersistentProtocol | null;
|
||||
webSocketFactory: IWebSocketFactory;
|
||||
socketFactory: ISocketFactory;
|
||||
signService: ISignService;
|
||||
}
|
||||
|
||||
@@ -65,13 +65,13 @@ export interface IConnectCallback {
|
||||
(err: any | undefined, socket: ISocket | undefined): void;
|
||||
}
|
||||
|
||||
export interface IWebSocketFactory {
|
||||
export interface ISocketFactory {
|
||||
connect(host: string, port: number, query: string, callback: IConnectCallback): void;
|
||||
}
|
||||
|
||||
async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptions, connectionType: ConnectionType, args: any | undefined): Promise<PersistentProtocol> {
|
||||
const protocol = await new Promise<PersistentProtocol>((c, e) => {
|
||||
options.webSocketFactory.connect(
|
||||
options.socketFactory.connect(
|
||||
options.host,
|
||||
options.port,
|
||||
`reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`,
|
||||
@@ -202,7 +202,7 @@ async function doConnectRemoteAgentTunnel(options: ISimpleConnectionOptions, sta
|
||||
export interface IConnectionOptions {
|
||||
isBuilt: boolean;
|
||||
commit: string | undefined;
|
||||
webSocketFactory: IWebSocketFactory;
|
||||
socketFactory: ISocketFactory;
|
||||
addressProvider: IAddressProvider;
|
||||
signService: ISignService;
|
||||
}
|
||||
@@ -216,7 +216,7 @@ async function resolveConnectionOptions(options: IConnectionOptions, reconnectio
|
||||
port: port,
|
||||
reconnectionToken: reconnectionToken,
|
||||
reconnectionProtocol: reconnectionProtocol,
|
||||
webSocketFactory: options.webSocketFactory,
|
||||
socketFactory: options.socketFactory,
|
||||
signService: options.signService
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,4 +10,16 @@ export const REMOTE_HOST_SCHEME = Schemas.vscodeRemote;
|
||||
|
||||
export function getRemoteAuthority(uri: URI): string | undefined {
|
||||
return uri.scheme === REMOTE_HOST_SCHEME ? uri.authority : undefined;
|
||||
}
|
||||
|
||||
export function getRemoteName(authority: string | undefined): string | undefined {
|
||||
if (!authority) {
|
||||
return undefined;
|
||||
}
|
||||
const pos = authority.indexOf('+');
|
||||
if (pos < 0) {
|
||||
// funky? bad authority?
|
||||
return authority;
|
||||
}
|
||||
return authority.substr(0, pos);
|
||||
}
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
import * as net from 'net';
|
||||
import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import { IWebSocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { ISocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
|
||||
export const nodeWebSocketFactory = new class implements IWebSocketFactory {
|
||||
export const nodeSocketFactory = new class implements ISocketFactory {
|
||||
connect(host: string, port: number, query: string, callback: IConnectCallback): void {
|
||||
const errorListener = (err: any) => callback(err, undefined);
|
||||
|
||||
@@ -90,7 +90,7 @@ Registry.as<IConfigurationRegistry>(Extensions.Configuration)
|
||||
'http.proxy': {
|
||||
type: 'string',
|
||||
pattern: '^https?://([^:]*(:[^@]*)?@)?([^:]+)(:\\d+)?/?$|^$',
|
||||
description: localize('proxy', "The proxy setting to use. If not set will be taken from the http_proxy and https_proxy environment variables.")
|
||||
markdownDescription: localize('proxy', "The proxy setting to use. If not set, will be inherited from the `http_proxy` and `https_proxy` environment variables.")
|
||||
},
|
||||
'http.proxyStrictSSL': {
|
||||
type: 'boolean',
|
||||
@@ -100,7 +100,7 @@ Registry.as<IConfigurationRegistry>(Extensions.Configuration)
|
||||
'http.proxyAuthorization': {
|
||||
type: ['null', 'string'],
|
||||
default: null,
|
||||
description: localize('proxyAuthorization', "The value to send as the 'Proxy-Authorization' header for every network request.")
|
||||
markdownDescription: localize('proxyAuthorization', "The value to send as the `Proxy-Authorization` header for every network request.")
|
||||
},
|
||||
'http.proxySupport': {
|
||||
type: 'string',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
export interface IPropertyData {
|
||||
classification: 'SystemMetaData' | 'CallstackOrException' | 'CustomerContent' | 'PublicNonPersonalData';
|
||||
classification: 'SystemMetaData' | 'CallstackOrException' | 'CustomerContent' | 'PublicNonPersonalData' | 'EndUserPseudonymizedInformation';
|
||||
purpose: 'PerformanceAndHealth' | 'FeatureInsight' | 'BusinessInsight';
|
||||
endpoint?: string;
|
||||
isMeasurement?: boolean;
|
||||
|
||||
@@ -69,20 +69,16 @@ export class TelemetryService implements ITelemetryService {
|
||||
this._commonProperties.then(values => {
|
||||
const isHashedId = /^[a-f0-9]+$/i.test(values['common.machineId']);
|
||||
|
||||
/* __GDPR__
|
||||
"machineIdFallback" : {
|
||||
"usingFallbackGuid" : { "classification": "SystemMetaData", "purpose": "BusinessInsight", "isMeasurement": true }
|
||||
}
|
||||
*/
|
||||
this.publicLog('machineIdFallback', { usingFallbackGuid: !isHashedId });
|
||||
type MachineIdFallbackClassification = {
|
||||
usingFallbackGuid: { classification: 'SystemMetaData', purpose: 'BusinessInsight', isMeasurement: true };
|
||||
};
|
||||
this.publicLog2<{ usingFallbackGuid: boolean }, MachineIdFallbackClassification>('machineIdFallback', { usingFallbackGuid: !isHashedId });
|
||||
|
||||
if (config.trueMachineId) {
|
||||
/* __GDPR__
|
||||
"machineIdDisambiguation" : {
|
||||
"correctedMachineId" : { "endPoint": "MacAddressHash", "classification": "EndUserPseudonymizedInformation", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.publicLog('machineIdDisambiguation', { correctedMachineId: config.trueMachineId });
|
||||
type MachineIdDisambiguationClassification = {
|
||||
correctedMachineId: { endPoint: 'MacAddressHash', classification: 'EndUserPseudonymizedInformation', purpose: 'FeatureInsight' };
|
||||
};
|
||||
this.publicLog2<{ correctedMachineId: string }, MachineIdDisambiguationClassification>('machineIdDisambiguation', { correctedMachineId: config.trueMachineId });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,17 +33,17 @@ export const NullTelemetryService = new class implements ITelemetryService {
|
||||
|
||||
export interface ITelemetryAppender {
|
||||
log(eventName: string, data: any): void;
|
||||
dispose(): Promise<any> | undefined;
|
||||
flush(): Promise<any>;
|
||||
}
|
||||
|
||||
export function combinedAppender(...appenders: ITelemetryAppender[]): ITelemetryAppender {
|
||||
return {
|
||||
log: (e, d) => appenders.forEach(a => a.log(e, d)),
|
||||
dispose: () => Promise.all(appenders.map(a => a.dispose()))
|
||||
flush: () => Promise.all(appenders.map(a => a.flush()))
|
||||
};
|
||||
}
|
||||
|
||||
export const NullAppender: ITelemetryAppender = { log: () => null, dispose: () => Promise.resolve(null) };
|
||||
export const NullAppender: ITelemetryAppender = { log: () => null, flush: () => Promise.resolve(null) };
|
||||
|
||||
|
||||
export class LogAppender implements ITelemetryAppender {
|
||||
@@ -51,7 +51,7 @@ export class LogAppender implements ITelemetryAppender {
|
||||
private commonPropertiesRegex = /^sessionID$|^version$|^timestamp$|^commitHash$|^common\./;
|
||||
constructor(@ILogService private readonly _logService: ILogService) { }
|
||||
|
||||
dispose(): Promise<any> {
|
||||
flush(): Promise<any> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ export class AppInsightsAppender implements ITelemetryAppender {
|
||||
});
|
||||
}
|
||||
|
||||
dispose(): Promise<any> | undefined {
|
||||
flush(): Promise<any> | undefined {
|
||||
if (this._aiClient) {
|
||||
return new Promise(resolve => {
|
||||
this._aiClient!.flush({
|
||||
|
||||
@@ -37,7 +37,7 @@ export class TelemetryAppenderClient implements ITelemetryAppender {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
dispose(): any {
|
||||
flush(): any {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ suite('AIAdapter', () => {
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
adapter.dispose();
|
||||
adapter.flush();
|
||||
});
|
||||
|
||||
test('Simple event', () => {
|
||||
|
||||
@@ -30,7 +30,7 @@ class TestTelemetryAppender implements ITelemetryAppender {
|
||||
return this.events.length;
|
||||
}
|
||||
|
||||
public dispose(): Promise<any> {
|
||||
public flush(): Promise<any> {
|
||||
this.isDisposed = true;
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
@@ -115,12 +115,7 @@ export class Win32UpdateService extends AbstractUpdateService {
|
||||
const updateType = getUpdateType();
|
||||
|
||||
if (!update || !update.url || !update.version || !update.productVersion) {
|
||||
/* __GDPR__
|
||||
"update:notAvailable" : {
|
||||
"explicit" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('update:notAvailable', { explicit: !!context });
|
||||
this.telemetryService.publicLog2<{ explicit: boolean }, UpdateNotAvailableClassification>('update:notAvailable', { explicit: !!context });
|
||||
|
||||
this.setState(State.Idle(updateType));
|
||||
return Promise.resolve(null);
|
||||
|
||||
Reference in New Issue
Block a user