Skip to content

Commit 2cb843b

Browse files
committed
refine regexp value, microsoft#26044
1 parent d5fda42 commit 2cb843b

2 files changed

Lines changed: 41 additions & 21 deletions

File tree

src/vs/platform/contextkey/common/contextkey.ts

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
88
import Event from 'vs/base/common/event';
9+
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
910

1011
export enum ContextKeyExprType {
1112
Defined = 1,
@@ -30,7 +31,7 @@ export abstract class ContextKeyExpr {
3031
return new ContextKeyNotEqualsExpr(key, value);
3132
}
3233

33-
public static regex(key: string, value: string): ContextKeyExpr {
34+
public static regex(key: string, value: RegExp): ContextKeyExpr {
3435
return new ContextKeyRegexExpr(key, value);
3536
}
3637

@@ -67,7 +68,7 @@ export abstract class ContextKeyExpr {
6768

6869
if (serializedOne.indexOf('=~') >= 0) {
6970
let pieces = serializedOne.split('=~');
70-
return new ContextKeyRegexExpr(pieces[0].trim(), this._deserializeValue(pieces[1]));
71+
return new ContextKeyRegexExpr(pieces[0].trim(), this._deserializeRegexValue(pieces[1]));
7172
}
7273

7374
if (/^\!\s*/.test(serializedOne)) {
@@ -96,6 +97,29 @@ export abstract class ContextKeyExpr {
9697
return serializedValue;
9798
}
9899

100+
private static _deserializeRegexValue(serializedValue: string): RegExp {
101+
102+
if (isFalsyOrWhitespace(serializedValue)) {
103+
console.warn('missing regexp-value for =~-expression');
104+
return null;
105+
}
106+
107+
let start = serializedValue.indexOf('/');
108+
let end = serializedValue.lastIndexOf('/');
109+
if (start === end || start < 0 /* || to < 0 */) {
110+
console.warn(`bad regexp-value '${serializedValue}', missing /-enclosure`);
111+
return null;
112+
}
113+
114+
let value = serializedValue.slice(start + 1, end);
115+
try {
116+
return new RegExp(value);
117+
} catch (e) {
118+
console.warn(`bad regexp-value '${serializedValue}', parse error: ${e}`);
119+
return null;
120+
}
121+
}
122+
99123
public abstract getType(): ContextKeyExprType;
100124
public abstract equals(other: ContextKeyExpr): boolean;
101125
public abstract evaluate(context: IContext): boolean;
@@ -334,15 +358,8 @@ export class ContextKeyNotExpr implements ContextKeyExpr {
334358

335359
export class ContextKeyRegexExpr implements ContextKeyExpr {
336360

337-
private regexp: { source: string, test(s: string): boolean };
338-
339-
constructor(private key: string, value: any) {
340-
try {
341-
this.regexp = new RegExp(value);
342-
} catch (e) {
343-
this.regexp = { source: '', test() { return false; } };
344-
console.warn(`Bad value for glob-context key expression: ${value}`);
345-
}
361+
constructor(private key: string, private regexp: RegExp) {
362+
//
346363
}
347364

348365
public getType(): ContextKeyExprType {
@@ -356,32 +373,34 @@ export class ContextKeyRegexExpr implements ContextKeyExpr {
356373
if (this.key > other.key) {
357374
return 1;
358375
}
359-
if (this.regexp.source < other.regexp.source) {
376+
const source = this.regexp ? this.regexp.source : undefined;
377+
if (source < other.regexp.source) {
360378
return -1;
361379
}
362-
if (this.regexp.source > other.regexp.source) {
380+
if (source > other.regexp.source) {
363381
return 1;
364382
}
365383
return 0;
366384
}
367385

368386
public equals(other: ContextKeyExpr): boolean {
369387
if (other instanceof ContextKeyRegexExpr) {
370-
return (this.key === other.key && this.regexp.source === other.regexp.source);
388+
const source = this.regexp ? this.regexp.source : undefined;
389+
return (this.key === other.key && source === other.regexp.source);
371390
}
372391
return false;
373392
}
374393

375394
public evaluate(context: IContext): boolean {
376-
return this.regexp.test(context.getValue(this.key));
395+
return this.regexp ? this.regexp.test(context.getValue(this.key)) : false;
377396
}
378397

379398
public normalize(): ContextKeyExpr {
380399
return this;
381400
}
382401

383402
public serialize(): string {
384-
return this.key + ' =~ \'' + this.regexp.source + '\'';
403+
return `${this.keys} =~ /${this.regexp ? this.regexp.source : '<invalid>'}/`;
385404
}
386405

387406
public keys(): string[] {

src/vs/platform/contextkey/test/common/contextkey.test.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ suite('ContextKeyExpr', () => {
2121
ContextKeyExpr.has('a1'),
2222
ContextKeyExpr.and(ContextKeyExpr.has('and.a')),
2323
ContextKeyExpr.has('a2'),
24-
ContextKeyExpr.regex('d3', 'd.*'),
25-
ContextKeyExpr.regex('d4', '\\*\\*/3*'),
24+
ContextKeyExpr.regex('d3', /d.*/),
25+
ContextKeyExpr.regex('d4', /\*\*3*/),
2626
ContextKeyExpr.equals('b1', 'bb1'),
2727
ContextKeyExpr.equals('b2', 'bb2'),
2828
ContextKeyExpr.notEquals('c1', 'cc1'),
@@ -34,11 +34,11 @@ suite('ContextKeyExpr', () => {
3434
ContextKeyExpr.equals('b2', 'bb2'),
3535
ContextKeyExpr.notEquals('c1', 'cc1'),
3636
ContextKeyExpr.not('d1'),
37-
ContextKeyExpr.regex('d4', '\\*\\*/3*'),
37+
ContextKeyExpr.regex('d4', /\*\*3*/),
3838
ContextKeyExpr.notEquals('c2', 'cc2'),
3939
ContextKeyExpr.has('a2'),
4040
ContextKeyExpr.equals('b1', 'bb1'),
41-
ContextKeyExpr.regex('d3', 'd.*'),
41+
ContextKeyExpr.regex('d3', /d.*/),
4242
ContextKeyExpr.has('a1'),
4343
ContextKeyExpr.and(ContextKeyExpr.equals('and.a', true)),
4444
ContextKeyExpr.not('d2')
@@ -80,7 +80,7 @@ suite('ContextKeyExpr', () => {
8080
testExpression(expr + ' == 5', value == <any>'5');
8181
testExpression(expr + ' != 5', value != <any>'5');
8282
testExpression('!' + expr, !value);
83-
testExpression(expr + ' =~ d.*', /d.*/.test(value));
83+
testExpression(expr + ' =~ /d.*/', /d.*/.test(value));
8484
}
8585

8686
testBatch('a', true);
@@ -92,6 +92,7 @@ suite('ContextKeyExpr', () => {
9292
testExpression('a && !b', true && !false);
9393
testExpression('a && b', true && false);
9494
testExpression('a && !b && c == 5', true && !false && '5' == '5');
95+
testExpression('dddd =~ d.*', false);
9596
/* tslint:enable:triple-equals */
9697
});
9798
});

0 commit comments

Comments
 (0)