Skip to content

Commit 1cac8b1

Browse files
committed
Fixes microsoft#50304: Tweaks to visible ranges queries for lines > 10k chars
1 parent 615d640 commit 1cac8b1

9 files changed

Lines changed: 75 additions & 78 deletions

File tree

src/vs/editor/browser/controller/mouseHandler.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/v
1717
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
1818
import { Position } from 'vs/editor/common/core/position';
1919
import { Selection } from 'vs/editor/common/core/selection';
20-
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
20+
import { HorizontalPosition } from 'vs/editor/common/view/renderingContext';
2121
import { ViewContext } from 'vs/editor/common/view/viewContext';
2222
import * as viewEvents from 'vs/editor/common/view/viewEvents';
2323
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
2424
import { EditorOption } from 'vs/editor/common/config/editorOptions';
2525

26-
2726
/**
2827
* Merges mouse events when mouse move events are throttled
2928
*/
@@ -59,7 +58,7 @@ export interface IPointerHandlerHelper {
5958
*/
6059
getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position | null;
6160

62-
visibleRangeForPosition2(lineNumber: number, column: number): HorizontalRange | null;
61+
visibleRangeForPosition(lineNumber: number, column: number): HorizontalPosition | null;
6362
getLineWidth(lineNumber: number): number;
6463
}
6564

src/vs/editor/browser/controller/mouseTarget.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/v
1313
import { EditorLayoutInfo, EditorOption } from 'vs/editor/common/config/editorOptions';
1414
import { Position } from 'vs/editor/common/core/position';
1515
import { Range as EditorRange } from 'vs/editor/common/core/range';
16-
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
16+
import { HorizontalPosition } from 'vs/editor/common/view/renderingContext';
1717
import { ViewContext } from 'vs/editor/common/view/viewContext';
1818
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
1919
import { CursorColumns } from 'vs/editor/common/controller/cursorCommon';
@@ -346,8 +346,8 @@ export class HitTestContext {
346346
return this._viewHelper.getLineWidth(lineNumber);
347347
}
348348

349-
public visibleRangeForPosition2(lineNumber: number, column: number): HorizontalRange | null {
350-
return this._viewHelper.visibleRangeForPosition2(lineNumber, column);
349+
public visibleRangeForPosition(lineNumber: number, column: number): HorizontalPosition | null {
350+
return this._viewHelper.visibleRangeForPosition(lineNumber, column);
351351
}
352352

353353
public getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position | null {
@@ -743,7 +743,7 @@ export class MouseTargetFactory {
743743
return request.fulfill(MouseTargetType.CONTENT_EMPTY, pos, undefined, detail);
744744
}
745745

746-
const visibleRange = ctx.visibleRangeForPosition2(lineNumber, column);
746+
const visibleRange = ctx.visibleRangeForPosition(lineNumber, column);
747747

748748
if (!visibleRange) {
749749
return request.fulfill(MouseTargetType.UNKNOWN, pos);
@@ -761,14 +761,14 @@ export class MouseTargetFactory {
761761
const points: OffsetColumn[] = [];
762762
points.push({ offset: visibleRange.left, column: column });
763763
if (column > 1) {
764-
const visibleRange = ctx.visibleRangeForPosition2(lineNumber, column - 1);
764+
const visibleRange = ctx.visibleRangeForPosition(lineNumber, column - 1);
765765
if (visibleRange) {
766766
points.push({ offset: visibleRange.left, column: column - 1 });
767767
}
768768
}
769769
const lineMaxColumn = ctx.model.getLineMaxColumn(lineNumber);
770770
if (column < lineMaxColumn) {
771-
const visibleRange = ctx.visibleRangeForPosition2(lineNumber, column + 1);
771+
const visibleRange = ctx.visibleRangeForPosition(lineNumber, column + 1);
772772
if (visibleRange) {
773773
points.push({ offset: visibleRange.left, column: column + 1 });
774774
}

src/vs/editor/browser/controller/textAreaHandler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ import { Range } from 'vs/editor/common/core/range';
2525
import { Selection } from 'vs/editor/common/core/selection';
2626
import { ScrollType } from 'vs/editor/common/editorCommon';
2727
import { EndOfLinePreference } from 'vs/editor/common/model';
28-
import { HorizontalRange, RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
28+
import { RenderingContext, RestrictedRenderingContext, HorizontalPosition } from 'vs/editor/common/view/renderingContext';
2929
import { ViewContext } from 'vs/editor/common/view/viewContext';
3030
import * as viewEvents from 'vs/editor/common/view/viewEvents';
3131
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
3232

3333
export interface ITextAreaHandlerHelper {
34-
visibleRangeForPositionRelativeToEditor(lineNumber: number, column: number): HorizontalRange | null;
34+
visibleRangeForPositionRelativeToEditor(lineNumber: number, column: number): HorizontalPosition | null;
3535
}
3636

3737
class VisibleTextAreaData {
@@ -408,7 +408,7 @@ export class TextAreaHandler extends ViewPart {
408408

409409
// --- end view API
410410

411-
private _primaryCursorVisibleRange: HorizontalRange | null = null;
411+
private _primaryCursorVisibleRange: HorizontalPosition | null = null;
412412

413413
public prepareRender(ctx: RenderingContext): void {
414414
const primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);

src/vs/editor/browser/view/viewImpl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ export class View extends ViewEventHandler {
261261
return this.viewLines.getPositionFromDOMInfo(spanNode, offset);
262262
},
263263

264-
visibleRangeForPosition2: (lineNumber: number, column: number) => {
264+
visibleRangeForPosition: (lineNumber: number, column: number) => {
265265
this._flushAccumulatedAndRenderNow();
266266
return this.viewLines.visibleRangeForPosition(new Position(lineNumber, column));
267267
},

src/vs/editor/browser/viewParts/decorations/decorations.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ export class DecorationsOverlay extends DynamicViewOverlay {
195195

196196
for (let j = 0, lenJ = linesVisibleRanges.length; j < lenJ; j++) {
197197
const lineVisibleRanges = linesVisibleRanges[j];
198+
if (lineVisibleRanges.outsideRenderedLine) {
199+
continue;
200+
}
198201
const lineIndex = lineVisibleRanges.lineNumber - visibleStartLineNumber;
199202

200203
if (showIfCollapsed && lineVisibleRanges.ranges.length === 1) {

src/vs/editor/browser/viewParts/lines/viewLine.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { IVisibleLine } from 'vs/editor/browser/view/viewLayer';
1010
import { RangeUtil } from 'vs/editor/browser/viewParts/lines/rangeUtil';
1111
import { IStringBuilder } from 'vs/editor/common/core/stringBuilder';
1212
import { IConfiguration } from 'vs/editor/common/editorCommon';
13-
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
13+
import { HorizontalRange, VisibleRanges } from 'vs/editor/common/view/renderingContext';
1414
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
1515
import { CharacterMapping, ForeignElementType, RenderLineInput, renderViewLine, LineRange } from 'vs/editor/common/viewLayout/viewLineRenderer';
1616
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
@@ -295,7 +295,7 @@ export class ViewLine implements IVisibleLine {
295295
return this._renderedViewLine.getWidthIsFast();
296296
}
297297

298-
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
298+
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): VisibleRanges | null {
299299
if (!this._renderedViewLine) {
300300
return null;
301301
}
@@ -306,21 +306,27 @@ export class ViewLine implements IVisibleLine {
306306
endColumn = Math.min(this._renderedViewLine.input.lineContent.length + 1, Math.max(1, endColumn));
307307

308308
const stopRenderingLineAfter = this._renderedViewLine.input.stopRenderingLineAfter | 0; // @perf
309+
let outsideRenderedLine = false;
309310

310-
if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter && endColumn > stopRenderingLineAfter) {
311+
if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter + 1 && endColumn > stopRenderingLineAfter + 1) {
311312
// This range is obviously not visible
312-
return null;
313+
outsideRenderedLine = true;
313314
}
314315

315-
if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter) {
316-
startColumn = stopRenderingLineAfter;
316+
if (stopRenderingLineAfter !== -1 && startColumn > stopRenderingLineAfter + 1) {
317+
startColumn = stopRenderingLineAfter + 1;
317318
}
318319

319-
if (stopRenderingLineAfter !== -1 && endColumn > stopRenderingLineAfter) {
320-
endColumn = stopRenderingLineAfter;
320+
if (stopRenderingLineAfter !== -1 && endColumn > stopRenderingLineAfter + 1) {
321+
endColumn = stopRenderingLineAfter + 1;
321322
}
322323

323-
return this._renderedViewLine.getVisibleRangesForRange(startColumn, endColumn, context);
324+
const horizontalRanges = this._renderedViewLine.getVisibleRangesForRange(startColumn, endColumn, context);
325+
if (horizontalRanges && horizontalRanges.length > 0) {
326+
return new VisibleRanges(outsideRenderedLine, horizontalRanges);
327+
}
328+
329+
return null;
324330
}
325331

326332
public getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number {

src/vs/editor/browser/viewParts/lines/viewLines.ts

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { Position } from 'vs/editor/common/core/position';
1414
import { Range } from 'vs/editor/common/core/range';
1515
import { Selection } from 'vs/editor/common/core/selection';
1616
import { ScrollType } from 'vs/editor/common/editorCommon';
17-
import { HorizontalRange, IViewLines, LineVisibleRanges } from 'vs/editor/common/view/renderingContext';
17+
import { IViewLines, LineVisibleRanges, VisibleRanges, HorizontalPosition } from 'vs/editor/common/view/renderingContext';
1818
import { ViewContext } from 'vs/editor/common/view/viewContext';
1919
import * as viewEvents from 'vs/editor/common/view/viewEvents';
2020
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
@@ -390,7 +390,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
390390
const endColumn = lineNumber === range.endLineNumber ? range.endColumn : this._context.model.getLineMaxColumn(lineNumber);
391391
const visibleRangesForLine = this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(startColumn, endColumn, domReadingContext);
392392

393-
if (!visibleRangesForLine || visibleRangesForLine.length === 0) {
393+
if (!visibleRangesForLine) {
394394
continue;
395395
}
396396

@@ -399,11 +399,11 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
399399
nextLineModelLineNumber = this._context.model.coordinatesConverter.convertViewPositionToModelPosition(new Position(lineNumber + 1, 1)).lineNumber;
400400

401401
if (currentLineModelLineNumber !== nextLineModelLineNumber) {
402-
visibleRangesForLine[visibleRangesForLine.length - 1].width += this._typicalHalfwidthCharacterWidth;
402+
visibleRangesForLine.ranges[visibleRangesForLine.ranges.length - 1].width += this._typicalHalfwidthCharacterWidth;
403403
}
404404
}
405405

406-
visibleRanges[visibleRangesLen++] = new LineVisibleRanges(lineNumber, visibleRangesForLine);
406+
visibleRanges[visibleRangesLen++] = new LineVisibleRanges(visibleRangesForLine.outsideRenderedLine, lineNumber, visibleRangesForLine.ranges);
407407
}
408408

409409
if (visibleRangesLen === 0) {
@@ -413,54 +413,26 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
413413
return visibleRanges;
414414
}
415415

416-
private visibleRangesForRange2(_range: Range): HorizontalRange[] | null {
417-
416+
private _visibleRangesForLineRange(lineNumber: number, startColumn: number, endColumn: number): VisibleRanges | null {
418417
if (this.shouldRender()) {
419418
// Cannot read from the DOM because it is dirty
420419
// i.e. the model & the dom are out of sync, so I'd be reading something stale
421420
return null;
422421
}
423422

424-
const range = Range.intersectRanges(_range, this._lastRenderedData.getCurrentVisibleRange());
425-
if (!range) {
426-
return null;
427-
}
428-
429-
let result: HorizontalRange[] = [];
430-
const domReadingContext = new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot);
431-
432-
const rendStartLineNumber = this._visibleLines.getStartLineNumber();
433-
const rendEndLineNumber = this._visibleLines.getEndLineNumber();
434-
for (let lineNumber = range.startLineNumber; lineNumber <= range.endLineNumber; lineNumber++) {
435-
436-
if (lineNumber < rendStartLineNumber || lineNumber > rendEndLineNumber) {
437-
continue;
438-
}
439-
440-
const startColumn = lineNumber === range.startLineNumber ? range.startColumn : 1;
441-
const endColumn = lineNumber === range.endLineNumber ? range.endColumn : this._context.model.getLineMaxColumn(lineNumber);
442-
const visibleRangesForLine = this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(startColumn, endColumn, domReadingContext);
443-
444-
if (!visibleRangesForLine || visibleRangesForLine.length === 0) {
445-
continue;
446-
}
447-
448-
result = result.concat(visibleRangesForLine);
449-
}
450-
451-
if (result.length === 0) {
423+
if (lineNumber < this._visibleLines.getStartLineNumber() || lineNumber > this._visibleLines.getEndLineNumber()) {
452424
return null;
453425
}
454426

455-
return result;
427+
return this._visibleLines.getVisibleLine(lineNumber).getVisibleRangesForRange(startColumn, endColumn, new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot));
456428
}
457429

458-
public visibleRangeForPosition(position: Position): HorizontalRange | null {
459-
const visibleRanges = this.visibleRangesForRange2(new Range(position.lineNumber, position.column, position.lineNumber, position.column));
430+
public visibleRangeForPosition(position: Position): HorizontalPosition | null {
431+
const visibleRanges = this._visibleRangesForLineRange(position.lineNumber, position.column, position.column);
460432
if (!visibleRanges) {
461433
return null;
462434
}
463-
return visibleRanges[0];
435+
return new HorizontalPosition(visibleRanges.outsideRenderedLine, visibleRanges.ranges[0].left);
464436
}
465437

466438
// --- implementation
@@ -641,7 +613,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
641613
const viewportStartX = viewport.left;
642614
const viewportEndX = viewportStartX + viewport.width;
643615

644-
const visibleRanges = this.visibleRangesForRange2(new Range(lineNumber, startColumn, lineNumber, endColumn));
616+
const visibleRanges = this._visibleRangesForLineRange(lineNumber, startColumn, endColumn);
645617
let boxStartX = Constants.MAX_SAFE_SMALL_INTEGER;
646618
let boxEndX = 0;
647619

@@ -653,7 +625,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
653625
};
654626
}
655627

656-
for (const visibleRange of visibleRanges) {
628+
for (const visibleRange of visibleRanges.ranges) {
657629
if (visibleRange.left < boxStartX) {
658630
boxStartX = visibleRange.left;
659631
}

src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export class ViewCursor {
121121

122122
if (this._cursorStyle === TextEditorCursorStyle.Line || this._cursorStyle === TextEditorCursorStyle.LineThin) {
123123
const visibleRange = ctx.visibleRangeForPosition(this._position);
124-
if (!visibleRange) {
124+
if (!visibleRange || visibleRange.outsideRenderedLine) {
125125
// Outside viewport
126126
return null;
127127
}
@@ -151,13 +151,18 @@ export class ViewCursor {
151151
const lineContent = this._context.model.getLineContent(this._position.lineNumber);
152152
const nextCharLength = strings.nextCharLength(lineContent, this._position.column - 1);
153153
const visibleRangeForCharacter = ctx.linesVisibleRangesForRange(new Range(this._position.lineNumber, this._position.column, this._position.lineNumber, this._position.column + nextCharLength), false);
154+
if (!visibleRangeForCharacter || visibleRangeForCharacter.length === 0) {
155+
// Outside viewport
156+
return null;
157+
}
154158

155-
if (!visibleRangeForCharacter || visibleRangeForCharacter.length === 0 || visibleRangeForCharacter[0].ranges.length === 0) {
159+
const firstVisibleRangeForCharacter = visibleRangeForCharacter[0];
160+
if (firstVisibleRangeForCharacter.outsideRenderedLine || firstVisibleRangeForCharacter.ranges.length === 0) {
156161
// Outside viewport
157162
return null;
158163
}
159164

160-
const range = visibleRangeForCharacter[0].ranges[0];
165+
const range = firstVisibleRangeForCharacter.ranges[0];
161166
const width = range.width < 1 ? this._typicalHalfwidthCharacterWidth : range.width;
162167

163168
let textContentClassName = '';

src/vs/editor/common/view/renderingContext.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { IViewLayout, ViewModelDecoration } from 'vs/editor/common/viewModel/vie
1010

1111
export interface IViewLines {
1212
linesVisibleRangesForRange(range: Range, includeNewLines: boolean): LineVisibleRanges[] | null;
13-
visibleRangeForPosition(position: Position): HorizontalRange | null;
13+
visibleRangeForPosition(position: Position): HorizontalPosition | null;
1414
}
1515

1616
export abstract class RestrictedRenderingContext {
@@ -77,26 +77,20 @@ export class RenderingContext extends RestrictedRenderingContext {
7777
return this._viewLines.linesVisibleRangesForRange(range, includeNewLines);
7878
}
7979

80-
public visibleRangeForPosition(position: Position): HorizontalRange | null {
80+
public visibleRangeForPosition(position: Position): HorizontalPosition | null {
8181
return this._viewLines.visibleRangeForPosition(position);
8282
}
8383
}
8484

8585
export class LineVisibleRanges {
86-
_lineVisibleRangesBrand: void;
87-
88-
public lineNumber: number;
89-
public ranges: HorizontalRange[];
90-
91-
constructor(lineNumber: number, ranges: HorizontalRange[]) {
92-
this.lineNumber = lineNumber;
93-
this.ranges = ranges;
94-
}
86+
constructor(
87+
public readonly outsideRenderedLine: boolean,
88+
public readonly lineNumber: number,
89+
public readonly ranges: HorizontalRange[]
90+
) { }
9591
}
9692

9793
export class HorizontalRange {
98-
_horizontalRangeBrand: void;
99-
10094
public left: number;
10195
public width: number;
10296

@@ -109,3 +103,21 @@ export class HorizontalRange {
109103
return `[${this.left},${this.width}]`;
110104
}
111105
}
106+
107+
export class HorizontalPosition {
108+
public outsideRenderedLine: boolean;
109+
public left: number;
110+
111+
constructor(outsideRenderedLine: boolean, left: number) {
112+
this.outsideRenderedLine = outsideRenderedLine;
113+
this.left = Math.round(left);
114+
}
115+
}
116+
117+
export class VisibleRanges {
118+
constructor(
119+
public readonly outsideRenderedLine: boolean,
120+
public readonly ranges: HorizontalRange[]
121+
) {
122+
}
123+
}

0 commit comments

Comments
 (0)