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,
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"presentation": {
|
||||
"hidden": true,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
|
|
|
@ -24,6 +24,8 @@ export const VIEW_ID = 'workbench.view.search';
|
|||
|
||||
export const SEARCH_EXCLUDE_CONFIG = 'search.exclude';
|
||||
|
||||
const SEARCH_SINGLE_RANGE_DIVIDER = '...';
|
||||
|
||||
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.
|
||||
// Otherwise send the full text, like for replace or for showing multiple previews.
|
||||
// TODO this is fishy.
|
||||
if (previewOptions && previewOptions.matchLines === 1 && (!Array.isArray(range) || range.length === 1) && isSingleLineRange(range)) {
|
||||
const oneRange = Array.isArray(range) ? range[0] : range;
|
||||
|
||||
const ranges = Array.isArray(range) ? range : [range];
|
||||
if (previewOptions && previewOptions.matchLines === 1 && isSingleLineRangeList(ranges)) {
|
||||
// 1 line preview requested
|
||||
text = getNLines(text, previewOptions.matchLines);
|
||||
|
||||
let result = '';
|
||||
let shift = 0;
|
||||
let lastEnd = 0;
|
||||
const leadingChars = Math.floor(previewOptions.charsPerLine / 5);
|
||||
const previewStart = Math.max(oneRange.startColumn - leadingChars, 0);
|
||||
const previewText = text.substring(previewStart, previewOptions.charsPerLine + previewStart);
|
||||
const matches: ISearchRange[] = [];
|
||||
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 ?
|
||||
Math.min(previewText.length, oneRange.endColumn - previewStart) : // if number of match lines will not be trimmed by previewOptions
|
||||
previewText.length; // if number of lines is trimmed
|
||||
matches.push(new OneLineRange(0, range.startColumn - shift, range.endColumn - shift));
|
||||
lastEnd = previewEnd;
|
||||
}
|
||||
|
||||
const oneLineRange = new OneLineRange(0, oneRange.startColumn - previewStart, endColInPreview);
|
||||
this.preview = {
|
||||
text: previewText,
|
||||
matches: Array.isArray(range) ? [oneLineRange] : oneLineRange
|
||||
};
|
||||
this.preview = { text: result, matches: matches.length === 1 ? matches[0] : matches };
|
||||
} else {
|
||||
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 {
|
||||
return Array.isArray(range) ?
|
||||
range[0].startLineNumber === range[0].endLineNumber :
|
||||
range.startLineNumber === range.endLineNumber;
|
||||
function isSingleLineRangeList(ranges: ISearchRange[]): boolean {
|
||||
const line = ranges[0].startLineNumber;
|
||||
for (const r of ranges) {
|
||||
if (r.startLineNumber !== line || r.endLineNumber !== line) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export class SearchRange implements ISearchRange {
|
||||
|
|
|
@ -95,6 +95,20 @@ suite('TextSearchResult', () => {
|
|||
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', () => {
|
||||
// const previewOptions: ITextSearchPreviewOptions = {
|
||||
// matchLines: 5,
|
||||
|
|
Loading…
Reference in a new issue