fix #11572
This commit is contained in:
parent
97ddcf6220
commit
c6b3f39c63
8 changed files with 219 additions and 133 deletions
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
|
@ -9,7 +9,9 @@
|
|||
"stopOnEntry": false,
|
||||
"args": [
|
||||
"--timeout",
|
||||
"999999"
|
||||
"999999",
|
||||
"-g",
|
||||
"Editor Model - Find"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"runtimeArgs": [],
|
||||
|
|
|
@ -174,14 +174,21 @@ export function endsWith(haystack: string, needle: string): boolean {
|
|||
}
|
||||
}
|
||||
|
||||
export function createRegExp(searchString: string, isRegex: boolean, matchCase: boolean, wholeWord: boolean, global:boolean): RegExp {
|
||||
export interface RegExpOptions {
|
||||
matchCase?: boolean;
|
||||
wholeWord?: boolean;
|
||||
multiline?: boolean;
|
||||
global?: boolean;
|
||||
}
|
||||
|
||||
export function createRegExp(searchString: string, isRegex: boolean, options: RegExpOptions = {}): RegExp {
|
||||
if (searchString === '') {
|
||||
throw new Error('Cannot create regex from empty string');
|
||||
}
|
||||
if (!isRegex) {
|
||||
searchString = searchString.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&');
|
||||
}
|
||||
if (wholeWord) {
|
||||
if (options.wholeWord) {
|
||||
if (!/\B/.test(searchString.charAt(0))) {
|
||||
searchString = '\\b' + searchString;
|
||||
}
|
||||
|
@ -190,12 +197,15 @@ export function createRegExp(searchString: string, isRegex: boolean, matchCase:
|
|||
}
|
||||
}
|
||||
let modifiers = '';
|
||||
if (global) {
|
||||
if (options.global) {
|
||||
modifiers += 'g';
|
||||
}
|
||||
if (!matchCase) {
|
||||
if (!options.matchCase) {
|
||||
modifiers += 'i';
|
||||
}
|
||||
if (options.multiline) {
|
||||
modifiers += 'm';
|
||||
}
|
||||
|
||||
return new RegExp(searchString, modifiers);
|
||||
}
|
||||
|
|
|
@ -18,11 +18,6 @@ import {IndentRange, computeRanges} from 'vs/editor/common/model/indentRanges';
|
|||
const LIMIT_FIND_COUNT = 999;
|
||||
export const LONG_LINE_BOUNDARY = 1000;
|
||||
|
||||
export interface IParsedSearchRequest {
|
||||
regex: RegExp;
|
||||
isMultiline: boolean;
|
||||
}
|
||||
|
||||
export class TextModel extends OrderGuaranteeEventEmitter implements editorCommon.ITextModel {
|
||||
private static MODEL_SYNC_LIMIT = 5 * 1024 * 1024; // 5 MB
|
||||
private static MODEL_TOKENIZATION_LIMIT = 20 * 1024 * 1024; // 20 MB
|
||||
|
@ -764,15 +759,16 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
|||
return false;
|
||||
}
|
||||
|
||||
public static parseSearchRequest(searchString:string, isRegex:boolean, matchCase:boolean, wholeWord:boolean): IParsedSearchRequest {
|
||||
public static parseSearchRequest(searchString:string, isRegex:boolean, matchCase:boolean, wholeWord:boolean): RegExp {
|
||||
if (searchString === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Try to create a RegExp out of the params
|
||||
var regex:RegExp = null;
|
||||
var regex: RegExp = null;
|
||||
var multiline = isRegex && TextModel._isMultiline(searchString);
|
||||
try {
|
||||
regex = strings.createRegExp(searchString, isRegex, matchCase, wholeWord, true);
|
||||
regex = strings.createRegExp(searchString, isRegex, {matchCase, wholeWord, multiline, global: true});
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
|
@ -781,15 +777,12 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
|||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
regex: regex,
|
||||
isMultiline: isRegex && TextModel._isMultiline(searchString)
|
||||
};
|
||||
return regex;
|
||||
}
|
||||
|
||||
public findMatches(searchString:string, rawSearchScope:any, isRegex:boolean, matchCase:boolean, wholeWord:boolean, limitResultCount:number = LIMIT_FIND_COUNT): Range[] {
|
||||
let r = TextModel.parseSearchRequest(searchString, isRegex, matchCase, wholeWord);
|
||||
if (!r) {
|
||||
let regex = TextModel.parseSearchRequest(searchString, isRegex, matchCase, wholeWord);
|
||||
if (!regex) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -800,10 +793,10 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
|||
searchRange = this.getFullModelRange();
|
||||
}
|
||||
|
||||
if (r.isMultiline) {
|
||||
return this._doFindMatchesMultiline(searchRange, r.regex, limitResultCount);
|
||||
if (regex.multiline) {
|
||||
return this._doFindMatchesMultiline(searchRange, regex, limitResultCount);
|
||||
}
|
||||
return this._doFindMatchesLineByLine(searchRange, r.regex, limitResultCount);
|
||||
return this._doFindMatchesLineByLine(searchRange, regex, limitResultCount);
|
||||
}
|
||||
|
||||
private _doFindMatchesMultiline(searchRange:Range, searchRegex:RegExp, limitResultCount:number): Range[] {
|
||||
|
@ -871,16 +864,16 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
|||
}
|
||||
|
||||
public findNextMatch(searchString:string, rawSearchStart:editorCommon.IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): Range {
|
||||
let r = TextModel.parseSearchRequest(searchString, isRegex, matchCase, wholeWord);
|
||||
if (!r) {
|
||||
let regex = TextModel.parseSearchRequest(searchString, isRegex, matchCase, wholeWord);
|
||||
if (!regex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let searchStart = this.validatePosition(rawSearchStart);
|
||||
if (r.isMultiline) {
|
||||
return this._doFindNextMatchMultiline(searchStart, r.regex);
|
||||
if (regex.multiline) {
|
||||
return this._doFindNextMatchMultiline(searchStart, regex);
|
||||
}
|
||||
return this._doFindNextMatchLineByLine(searchStart, r.regex);
|
||||
return this._doFindNextMatchLineByLine(searchStart, regex);
|
||||
|
||||
}
|
||||
|
||||
|
@ -932,16 +925,16 @@ export class TextModel extends OrderGuaranteeEventEmitter implements editorCommo
|
|||
}
|
||||
|
||||
public findPreviousMatch(searchString:string, rawSearchStart:editorCommon.IPosition, isRegex:boolean, matchCase:boolean, wholeWord:boolean): Range {
|
||||
let r = TextModel.parseSearchRequest(searchString, isRegex, matchCase, wholeWord);
|
||||
if (!r) {
|
||||
let regex = TextModel.parseSearchRequest(searchString, isRegex, matchCase, wholeWord);
|
||||
if (!regex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let searchStart = this.validatePosition(rawSearchStart);
|
||||
if (r.isMultiline) {
|
||||
return this._doFindPreviousMatchMultiline(searchStart, r.regex);
|
||||
if (regex.multiline) {
|
||||
return this._doFindPreviousMatchMultiline(searchStart, regex);
|
||||
}
|
||||
return this._doFindPreviousMatchLineByLine(searchStart, r.regex);
|
||||
return this._doFindPreviousMatchLineByLine(searchStart, regex);
|
||||
}
|
||||
|
||||
private _doFindPreviousMatchMultiline(searchStart:Position, searchRegex:RegExp): Range {
|
||||
|
|
|
@ -101,7 +101,7 @@ var getReversedRegexForBrackets = once<ISimpleInternalBracket[],RegExp>(
|
|||
|
||||
function createOrRegex(pieces:string[]): RegExp {
|
||||
let regexStr = `(${pieces.map(strings.escapeRegExpCharacters).join(')|(')})`;
|
||||
return strings.createRegExp(regexStr, true, false, false, false);
|
||||
return strings.createRegExp(regexStr, true);
|
||||
}
|
||||
|
||||
function toReversedString(str:string): string {
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
IModelContentChangedLinesDeletedEvent, IModelContentChangedLinesInsertedEvent
|
||||
} from 'vs/editor/common/editorCommon';
|
||||
import {Model} from 'vs/editor/common/model/model';
|
||||
import {TextModel, IParsedSearchRequest} from 'vs/editor/common/model/textModel';
|
||||
import {TextModel} from 'vs/editor/common/model/textModel';
|
||||
|
||||
// --------- utils
|
||||
|
||||
|
@ -599,6 +599,77 @@ suite('Editor Model - Find', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('multiline find with line beginning regex', () => {
|
||||
assertFindMatches(
|
||||
[
|
||||
'if',
|
||||
'else',
|
||||
'',
|
||||
'if',
|
||||
'else'
|
||||
].join('\n'),
|
||||
'^if\\nelse', true, false, false,
|
||||
[
|
||||
[1, 1, 2, 5],
|
||||
[4, 1, 5, 5]
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('matching empty lines using boundary expression', () => {
|
||||
assertFindMatches(
|
||||
[
|
||||
'if',
|
||||
'',
|
||||
'else',
|
||||
' ',
|
||||
'if',
|
||||
' ',
|
||||
'else'
|
||||
].join('\n'),
|
||||
'^\\s*$\\n', true, false, false,
|
||||
[
|
||||
[2, 1, 3, 1],
|
||||
[4, 1, 5, 1],
|
||||
[6, 1, 7, 1]
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('matching lines starting with A and ending with B', () => {
|
||||
assertFindMatches(
|
||||
[
|
||||
'a if b',
|
||||
'a',
|
||||
'ab',
|
||||
'eb'
|
||||
].join('\n'),
|
||||
'^a.*b$', true, false, false,
|
||||
[
|
||||
[1, 1, 1, 7],
|
||||
[3, 1, 3, 3]
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('multiline find with line ending regex', () => {
|
||||
assertFindMatches(
|
||||
[
|
||||
'if',
|
||||
'else',
|
||||
'',
|
||||
'if',
|
||||
'elseif',
|
||||
'else'
|
||||
].join('\n'),
|
||||
'if\\nelse$', true, false, false,
|
||||
[
|
||||
[1, 1, 2, 5],
|
||||
[5, 5, 6, 5]
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('issue #4836 - ^.*$', () => {
|
||||
assertFindMatches(
|
||||
[
|
||||
|
@ -619,7 +690,97 @@ suite('Editor Model - Find', () => {
|
|||
);
|
||||
});
|
||||
|
||||
function assertParseSearchResult(searchString:string, isRegex:boolean, matchCase:boolean, wholeWord:boolean, expected:IParsedSearchRequest): void {
|
||||
test('findNextMatch without regex', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('line line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('line', { lineNumber: 1, column: 1 }, false, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line', actual.getEndPosition(), false, false, false);
|
||||
assert.equal(new Range(1, 6, 1, 10).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line', {lineNumber: 1, column: 3}, false, false, false);
|
||||
assert.equal(new Range(1, 6, 1, 10).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line', actual.getEndPosition(), false, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line', actual.getEndPosition(), false, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
testObject.dispose();
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary regex', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('^line', { lineNumber: 1, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', { lineNumber: 1, column: 3 }, true, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
testObject.dispose();
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary regex and line has repetitive beginnings', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('line line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('^line', { lineNumber: 1, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', { lineNumber: 1, column: 3 }, true, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
testObject.dispose();
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary multiline regex and line has repetitive beginnings', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('line line one\nline two\nline three\nline four', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('^line.*\\nline', { lineNumber: 1, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(1, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line.*\\nline', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(3, 1, 4, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line.*\\nline', { lineNumber: 2, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(2, 1, 3, 5).toString(), actual.toString());
|
||||
|
||||
testObject.dispose();
|
||||
});
|
||||
|
||||
test('findNextMatch with ending boundary regex', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('line$', { lineNumber: 1, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(1, 10, 1, 14).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line$', { lineNumber: 1, column: 4 }, true, false, false);
|
||||
assert.equal(new Range(1, 10, 1, 14).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line$', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(2, 5, 2, 9).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line$', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(1, 10, 1, 14).toString(), actual.toString());
|
||||
|
||||
testObject.dispose();
|
||||
});
|
||||
|
||||
function assertParseSearchResult(searchString:string, isRegex:boolean, matchCase:boolean, wholeWord:boolean, expected:RegExp): void {
|
||||
let actual = TextModel.parseSearchRequest(searchString, isRegex, matchCase, wholeWord);
|
||||
assert.deepEqual(actual, expected);
|
||||
}
|
||||
|
@ -631,24 +792,24 @@ suite('Editor Model - Find', () => {
|
|||
});
|
||||
|
||||
test('parseSearchRequest non regex', () => {
|
||||
assertParseSearchResult('foo', false, false, false, { regex: /foo/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo', false, false, true, { regex: /\bfoo\b/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo', false, true, false, { regex: /foo/g, isMultiline: false });
|
||||
assertParseSearchResult('foo', false, true, true, { regex: /\bfoo\b/g, isMultiline: false });
|
||||
assertParseSearchResult('foo\\n', false, false, false, { regex: /foo\\n/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo\\\\n', false, false, false, { regex: /foo\\\\n/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo\\r', false, false, false, { regex: /foo\\r/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo\\\\r', false, false, false, { regex: /foo\\\\r/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo', false, false, false, /foo/gi);
|
||||
assertParseSearchResult('foo', false, false, true, /\bfoo\b/gi);
|
||||
assertParseSearchResult('foo', false, true, false, /foo/g);
|
||||
assertParseSearchResult('foo', false, true, true, /\bfoo\b/g);
|
||||
assertParseSearchResult('foo\\n', false, false, false, /foo\\n/gi);
|
||||
assertParseSearchResult('foo\\\\n', false, false, false, /foo\\\\n/gi);
|
||||
assertParseSearchResult('foo\\r', false, false, false, /foo\\r/gi);
|
||||
assertParseSearchResult('foo\\\\r', false, false, false, /foo\\\\r/gi);
|
||||
});
|
||||
|
||||
test('parseSearchRequest regex', () => {
|
||||
assertParseSearchResult('foo', true, false, false, { regex: /foo/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo', true, false, true, { regex: /\bfoo\b/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo', true, true, false, { regex: /foo/g, isMultiline: false });
|
||||
assertParseSearchResult('foo', true, true, true, { regex: /\bfoo\b/g, isMultiline: false });
|
||||
assertParseSearchResult('foo\\n', true, false, false, { regex: /foo\n/gi, isMultiline: true });
|
||||
assertParseSearchResult('foo\\\\n', true, false, false, { regex: /foo\\n/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo\\r', true, false, false, { regex: /foo\r/gi, isMultiline: true });
|
||||
assertParseSearchResult('foo\\\\r', true, false, false, { regex: /foo\\r/gi, isMultiline: false });
|
||||
assertParseSearchResult('foo', true, false, false, /foo/gi);
|
||||
assertParseSearchResult('foo', true, false, true, /\bfoo\b/gi);
|
||||
assertParseSearchResult('foo', true, true, false, /foo/g);
|
||||
assertParseSearchResult('foo', true, true, true, /\bfoo\b/g);
|
||||
assertParseSearchResult('foo\\n', true, false, false, /foo\n/gim);
|
||||
assertParseSearchResult('foo\\\\n', true, false, false, /foo\\n/gi);
|
||||
assertParseSearchResult('foo\\r', true, false, false, /foo\r/gim);
|
||||
assertParseSearchResult('foo\\\\r', true, false, false, /foo\\r/gi);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -555,86 +555,6 @@ suite('Editor Model - TextModel', () => {
|
|||
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('findNextMatch without regex', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('line line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('line', { lineNumber: 1, column: 1 }, false, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line', actual.getEndPosition(), false, false, false);
|
||||
assert.equal(new Range(1, 6, 1, 10).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line', {lineNumber: 1, column: 3}, false, false, false);
|
||||
assert.equal(new Range(1, 6, 1, 10).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line', actual.getEndPosition(), false, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line', actual.getEndPosition(), false, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary regex', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('^line', { lineNumber: 1, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', { lineNumber: 1, column: 3 }, true, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary regex and line has repetitive beginnings', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('line line one\nline two\nthree', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('^line', { lineNumber: 1, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', { lineNumber: 1, column: 3 }, true, false, false);
|
||||
assert.equal(new Range(2, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(1, 1, 1, 5).toString(), actual.toString());
|
||||
});
|
||||
|
||||
test('findNextMatch with beginning boundary multiline regex and line has repetitive beginnings', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('line line one\nline two\nline three', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('^line.*\\nline', { lineNumber: 1, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(1, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line.*\\nline', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(1, 1, 2, 5).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('^line.*\\nline', { lineNumber: 2, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(2, 1, 3, 5).toString(), actual.toString());
|
||||
});
|
||||
|
||||
test('findNextMatch with ending boundary regex', () => {
|
||||
var testObject = new TextModel([], TextModel.toRawText('one line line\ntwo line\nthree', TextModel.DEFAULT_CREATION_OPTIONS));
|
||||
|
||||
let actual = testObject.findNextMatch('line$', { lineNumber: 1, column: 1 }, true, false, false);
|
||||
assert.equal(new Range(1, 10, 1, 14).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line$', { lineNumber: 1, column: 4 }, true, false, false);
|
||||
assert.equal(new Range(1, 10, 1, 14).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line$', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(2, 5, 2, 9).toString(), actual.toString());
|
||||
|
||||
actual = testObject.findNextMatch('line$', actual.getEndPosition(), true, false, false);
|
||||
assert.equal(new Range(1, 10, 1, 14).toString(), actual.toString());
|
||||
});
|
||||
});
|
||||
|
||||
suite('TextModel.getLineIndentGuide', () => {
|
||||
|
|
|
@ -26,7 +26,7 @@ export class ReplacePattern {
|
|||
constructor(private replaceString: string, private searchPatternInfo: IPatternInfo) {
|
||||
this._replacePattern= replaceString;
|
||||
if (searchPatternInfo.isRegExp) {
|
||||
this._searchRegExp= strings.createRegExp(searchPatternInfo.pattern, searchPatternInfo.isRegExp, searchPatternInfo.isCaseSensitive, searchPatternInfo.isWordMatch, true);
|
||||
this._searchRegExp= strings.createRegExp(searchPatternInfo.pattern, searchPatternInfo.isRegExp, {matchCase: searchPatternInfo.isCaseSensitive, wholeWord: searchPatternInfo.isWordMatch, multiline: false, global: true});
|
||||
this.parseReplaceString(replaceString);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
|
|||
this.rootFolders = config.rootFolders;
|
||||
this.extraFiles = config.extraFiles;
|
||||
this.walker = walker;
|
||||
this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, config.contentPattern.isCaseSensitive, config.contentPattern.isWordMatch, true);
|
||||
this.contentPattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, {matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true});
|
||||
this.isCanceled = false;
|
||||
this.limitReached = false;
|
||||
this.maxResults = config.maxResults;
|
||||
|
|
Loading…
Reference in a new issue