Skip to content

Commit

Permalink
speed up getWordAtPosSlow, #2312
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Jan 7, 2017
1 parent 3887f75 commit 443d914
Showing 1 changed file with 35 additions and 33 deletions.
68 changes: 35 additions & 33 deletions src/vs/editor/common/model/wordHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ function reverse(str: string): string {
}

function getWordAtPosFast(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition {
// matches at the desired column, once to right
// and once to the left. The latter is achived
// by reversing the string. Falls back to getWordAtPosSlow
// when a word is longer than 100 characters. Will
// not work with regular expressions that check the
// shape of a word, like /aabb/

let pos = column - 1 - textOffset;
wordDefinition.lastIndex = pos;
Expand All @@ -83,13 +89,10 @@ function getWordAtPosFast(column: number, wordDefinition: RegExp, text: string,

} else if (wordDefinition.lastIndex === 100) {
// |W*100 -> very long word
wordDefinition.lastIndex = 0; // reset!
return getWordAtTextSlow(column, wordDefinition, text, textOffset);
return getWordAtPosSlow(column, wordDefinition, text, textOffset);
}
}

wordDefinition.lastIndex = 0; //reset!

if (!rightMatch && !leftMatch) {
// nothing matched
return null;
Expand Down Expand Up @@ -118,40 +121,39 @@ function getWordAtPosFast(column: number, wordDefinition: RegExp, text: string,
};
}

export function getWordAtTextSlow(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition {

var words = text.match(wordDefinition),
k: number,
startWord: number,
endWord: number,
startColumn: number,
endColumn: number,
word: string;

if (words) {
for (k = 0; k < words.length; k++) {
word = words[k].trim();
if (word.length > 0) {
startWord = text.indexOf(word, endWord);
endWord = startWord + word.length;

startColumn = textOffset + startWord + 1;
endColumn = textOffset + endWord + 1;

if (startColumn <= column && column <= endColumn) {
return {
word: word,
startColumn: startColumn,
endColumn: endColumn
};
}
}
function getWordAtPosSlow(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition {
// matches all words starting at the beginning
// of the input until it finds a match that encloses
// the desired column. slow but correct

let pos = column - 1 - textOffset;
wordDefinition.lastIndex = 0;

let match: RegExpMatchArray;
while (match = wordDefinition.exec(text)) {

if (match.index > pos) {
// |nW -> matched only after the pos
return null;

} else if (wordDefinition.lastIndex >= pos) {
// W|W -> match encloses pos
return {
word: match[0],
startColumn: textOffset + 1 + match.index,
endColumn: textOffset + 1 + wordDefinition.lastIndex
};
}
}

return null;
}

export function getWordAtText(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition {
return getWordAtPosFast(column, wordDefinition, text, textOffset);
const result = getWordAtPosFast(column, wordDefinition, text, textOffset);
// both (getWordAtPosFast and getWordAtPosSlow) leave the wordDefinition-RegExp
// in an undefined state and to not confuse other users of the wordDefinition
// we reset the lastIndex
wordDefinition.lastIndex = 0;
return result;
}

0 comments on commit 443d914

Please sign in to comment.