diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index af01d2aed55..babe28e9273 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -231,6 +231,10 @@ export function regExpLeadsToEndlessLoop(regexp: RegExp): boolean { return (match && regexp.lastIndex === 0); } +export function regExpContainsBackreference(regexpValue: string): boolean { + return !!regexpValue.match(/([^\\]|^)(\\\\)*\\\d+/); +} + /** * The normalize() method returns the Unicode Normalization Form of a given string. The form will be * the Normalization Form Canonical Composition. diff --git a/src/vs/base/test/common/strings.test.ts b/src/vs/base/test/common/strings.test.ts index d9530ec5d48..53e4a534c07 100644 --- a/src/vs/base/test/common/strings.test.ts +++ b/src/vs/base/test/common/strings.test.ts @@ -312,6 +312,22 @@ suite('Strings', () => { assert(regExpWithFlags.multiline); }); + test('regExpContainsBackreference', () => { + assert(strings.regExpContainsBackreference('foo \\5 bar')); + assert(strings.regExpContainsBackreference('\\2')); + assert(strings.regExpContainsBackreference('(\\d)(\\n)(\\1)')); + assert(strings.regExpContainsBackreference('(A).*?\\1')); + assert(strings.regExpContainsBackreference('\\\\\\1')); + assert(strings.regExpContainsBackreference('foo \\\\\\1')); + + assert(!strings.regExpContainsBackreference('')); + assert(!strings.regExpContainsBackreference('\\\\1')); + assert(!strings.regExpContainsBackreference('foo \\\\1')); + assert(!strings.regExpContainsBackreference('(A).*?\\\\1')); + assert(!strings.regExpContainsBackreference('foo \\d1 bar')); + assert(!strings.regExpContainsBackreference('123')); + }); + test('getLeadingWhitespace', () => { assert.equal(strings.getLeadingWhitespace(' foo'), ' '); assert.equal(strings.getLeadingWhitespace(' foo', 2), ''); diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index 11dcc232e23..69d02912f25 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -11,7 +11,7 @@ import { Widget } from 'vs/base/browser/ui/widget'; import { Action } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { FindInput, IFindInputOptions } from 'vs/base/browser/ui/findinput/findInput'; -import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; +import { InputBox, IMessage } from 'vs/base/browser/ui/inputbox/inputBox'; import { Button } from 'vs/base/browser/ui/button/button'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -220,7 +220,7 @@ export class SearchWidget extends Widget { private renderSearchInput(parent: HTMLElement, options: ISearchWidgetOptions): void { let inputOptions: IFindInputOptions = { label: nls.localize('label.Search', 'Search: Type Search Term and press Enter to search or Escape to cancel'), - validation: (value: string) => this.validatSearchInput(value), + validation: (value: string) => this.validateSearchInput(value), placeholder: nls.localize('search.placeHolder', "Search"), appendCaseSensitiveLabel: appendKeyBindingLabel('', this.keyBindingService2.lookupKeybinding(Constants.ToggleCaseSensitiveActionId), this.keyBindingService2), appendWholeWordsLabel: appendKeyBindingLabel('', this.keyBindingService2.lookupKeybinding(Constants.ToggleWholeWordActionId), this.keyBindingService2), @@ -309,7 +309,7 @@ export class SearchWidget extends Widget { } } - private validatSearchInput(value: string): any { + private validateSearchInput(value: string): IMessage { if (value.length === 0) { return null; } @@ -325,6 +325,12 @@ export class SearchWidget extends Widget { if (strings.regExpLeadsToEndlessLoop(regExp)) { return { content: nls.localize('regexp.validationFailure', "Expression matches everything") }; } + + if (strings.regExpContainsBackreference(value)) { + return { content: nls.localize('regexp.backreferenceValidationFailure', "Backreferences are not supported") }; + } + + return null; } private onSearchInputChanged(): void {