search: fix freezing ui on long lines
Fixes https://github.com/microsoft/vscode/issues/109902
This commit is contained in:
parent
e300dfcdd2
commit
df7fdd6515
5
.vscode/launch.json
vendored
5
.vscode/launch.json
vendored
|
@ -41,10 +41,7 @@
|
||||||
"port": 5876,
|
"port": 5876,
|
||||||
"outFiles": [
|
"outFiles": [
|
||||||
"${workspaceFolder}/out/**/*.js"
|
"${workspaceFolder}/out/**/*.js"
|
||||||
],
|
]
|
||||||
"presentation": {
|
|
||||||
"hidden": true,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "node",
|
"type": "node",
|
||||||
|
|
|
@ -24,6 +24,8 @@ export const VIEW_ID = 'workbench.view.search';
|
||||||
|
|
||||||
export const SEARCH_EXCLUDE_CONFIG = 'search.exclude';
|
export const SEARCH_EXCLUDE_CONFIG = 'search.exclude';
|
||||||
|
|
||||||
|
const SEARCH_SINGLE_RANGE_DIVIDER = '...';
|
||||||
|
|
||||||
export const ISearchService = createDecorator<ISearchService>('searchService');
|
export const ISearchService = createDecorator<ISearchService>('searchService');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,24 +262,31 @@ export class TextSearchMatch implements ITextSearchMatch {
|
||||||
// Trim preview if this is one match and a single-line match with a preview requested.
|
// Trim preview if this is one match and a single-line match with a preview requested.
|
||||||
// Otherwise send the full text, like for replace or for showing multiple previews.
|
// Otherwise send the full text, like for replace or for showing multiple previews.
|
||||||
// TODO this is fishy.
|
// TODO this is fishy.
|
||||||
if (previewOptions && previewOptions.matchLines === 1 && (!Array.isArray(range) || range.length === 1) && isSingleLineRange(range)) {
|
const ranges = Array.isArray(range) ? range : [range];
|
||||||
const oneRange = Array.isArray(range) ? range[0] : range;
|
if (previewOptions && previewOptions.matchLines === 1 && isSingleLineRangeList(ranges)) {
|
||||||
|
|
||||||
// 1 line preview requested
|
// 1 line preview requested
|
||||||
text = getNLines(text, previewOptions.matchLines);
|
text = getNLines(text, previewOptions.matchLines);
|
||||||
|
|
||||||
|
let result = '';
|
||||||
|
let shift = 0;
|
||||||
|
let lastEnd = 0;
|
||||||
const leadingChars = Math.floor(previewOptions.charsPerLine / 5);
|
const leadingChars = Math.floor(previewOptions.charsPerLine / 5);
|
||||||
const previewStart = Math.max(oneRange.startColumn - leadingChars, 0);
|
const matches: ISearchRange[] = [];
|
||||||
const previewText = text.substring(previewStart, previewOptions.charsPerLine + previewStart);
|
for (const range of ranges) {
|
||||||
|
const previewStart = Math.max(range.startColumn - leadingChars, 0);
|
||||||
|
const previewEnd = range.startColumn + previewOptions.charsPerLine;
|
||||||
|
if (previewStart > lastEnd + leadingChars) {
|
||||||
|
result += SEARCH_SINGLE_RANGE_DIVIDER + text.slice(previewStart, previewEnd);
|
||||||
|
shift += previewStart - (lastEnd + SEARCH_SINGLE_RANGE_DIVIDER.length);
|
||||||
|
} else {
|
||||||
|
result += text.slice(lastEnd, previewEnd);
|
||||||
|
}
|
||||||
|
|
||||||
const endColInPreview = (oneRange.endLineNumber - oneRange.startLineNumber + 1) <= previewOptions.matchLines ?
|
matches.push(new OneLineRange(0, range.startColumn - shift, range.endColumn - shift));
|
||||||
Math.min(previewText.length, oneRange.endColumn - previewStart) : // if number of match lines will not be trimmed by previewOptions
|
lastEnd = previewEnd;
|
||||||
previewText.length; // if number of lines is trimmed
|
}
|
||||||
|
|
||||||
const oneLineRange = new OneLineRange(0, oneRange.startColumn - previewStart, endColInPreview);
|
this.preview = { text: result, matches: matches.length === 1 ? matches[0] : matches };
|
||||||
this.preview = {
|
|
||||||
text: previewText,
|
|
||||||
matches: Array.isArray(range) ? [oneLineRange] : oneLineRange
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
const firstMatchLine = Array.isArray(range) ? range[0].startLineNumber : range.startLineNumber;
|
const firstMatchLine = Array.isArray(range) ? range[0].startLineNumber : range.startLineNumber;
|
||||||
|
|
||||||
|
@ -289,10 +298,15 @@ export class TextSearchMatch implements ITextSearchMatch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSingleLineRange(range: ISearchRange | ISearchRange[]): boolean {
|
function isSingleLineRangeList(ranges: ISearchRange[]): boolean {
|
||||||
return Array.isArray(range) ?
|
const line = ranges[0].startLineNumber;
|
||||||
range[0].startLineNumber === range[0].endLineNumber :
|
for (const r of ranges) {
|
||||||
range.startLineNumber === range.endLineNumber;
|
if (r.startLineNumber !== line || r.endLineNumber !== line) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SearchRange implements ISearchRange {
|
export class SearchRange implements ISearchRange {
|
||||||
|
|
|
@ -95,6 +95,20 @@ suite('TextSearchResult', () => {
|
||||||
assert.equal((<SearchRange>result.preview.matches).endColumn, 3);
|
assert.equal((<SearchRange>result.preview.matches).endColumn, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('compacts multiple ranges on long lines', () => {
|
||||||
|
const previewOptions: ITextSearchPreviewOptions = {
|
||||||
|
matchLines: 1,
|
||||||
|
charsPerLine: 10
|
||||||
|
};
|
||||||
|
|
||||||
|
const range1 = new SearchRange(5, 4, 5, 7);
|
||||||
|
const range2 = new SearchRange(5, 53, 5, 56);
|
||||||
|
const range3 = new SearchRange(5, 61, 5, 64);
|
||||||
|
const result = new TextSearchMatch('foo bar 1234567890123456789012345678901234567890 foo bar baz bar', [range1, range2, range3], previewOptions);
|
||||||
|
assert.deepEqual(result.preview.matches, [new SearchRange(0, 4, 0, 7), new SearchRange(0, 19, 0, 22), new SearchRange(0, 27, 0, 30)]);
|
||||||
|
assert.equal(result.preview.text, 'foo bar 123456...o bar baz bar');
|
||||||
|
});
|
||||||
|
|
||||||
// test('all lines of multiline match', () => {
|
// test('all lines of multiline match', () => {
|
||||||
// const previewOptions: ITextSearchPreviewOptions = {
|
// const previewOptions: ITextSearchPreviewOptions = {
|
||||||
// matchLines: 5,
|
// matchLines: 5,
|
||||||
|
|
Loading…
Reference in a new issue