viewLineRenderer.ts ×22

Frontier kind: Code frontier

unlabeled · c_50f5bfdad743

68 tests · 8953 LOC · 43 files · introduces 0 tests · 167 LOC · 4 files

Introduces — evidence that enters the hierarchy at this concept

Code
27 ranges167 lines · 4 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1105 ranges8953 lines · 43 files · Browse complete extent
All tests (intent)
68 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

4 files ranked by introduced lines: 167 introduced LOC across 27 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/editor/common/viewLayout/viewLineRenderer.ts 149 introduced LOC · 22 ranges

Open complete file

421 );
422 }
424 > return _renderLine(resolveRenderLineInput(input), sb);
425 > }
426
427 export class RenderLineOutput2 {
442 class ResolvedRenderLineInput {
443 constructor(
444 > public readonly fontIsMonospace: boolean, viewLineRenderer.ts
445 > public readonly canUseHalfwidthRightwardsArrow: boolean,
446 > public readonly lineContent: string,
447 > public readonly len: number,
448 > public readonly isOverflowing: boolean,
449 > public readonly overflowingCharCount: number,
450 > public readonly parts: LinePart[],
451 > public readonly containsForeignElements: ForeignElementType,
452 > public readonly fauxIndentLength: number,
453 > public readonly tabSize: number,
454 > public readonly startVisibleColumn: number,
455 > public readonly spaceWidth: number,
456 > public readonly renderSpaceCharCode: number,
457 > public readonly renderWhitespace: RenderWhitespace,
458 > public readonly renderControlCharacters: boolean,
459 > ) {
460 > //
461 > }
462 }
463
464 > function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput { viewLineRenderer.ts
465 > const lineContent = input.lineContent;
466 >
467 > let isOverflowing: boolean;
468 > let overflowingCharCount: number;
469 > let len: number;
470 >
471 > if (input.stopRenderingLineAfter !== -1 && input.stopRenderingLineAfter < lineContent.length) {
472 isOverflowing = true;
473 overflowingCharCount = lineContent.length - input.stopRenderingLineAfter;
474 len = input.stopRenderingLineAfter;
475 > } else { viewLineRenderer.ts
476 isOverflowing = false;
477 overflowingCharCount = 0;
478 len = lineContent.length;
479 }
481 > let tokens = transformAndRemoveOverflowing(lineContent, input.containsRTL, input.lineTokens, input.fauxIndentLength, len);
482 > if (input.renderControlCharacters && !input.isBasicASCII) {
483 // Calling `extractControlCharacters` before adding (possibly empty) line parts
484 // for inline decorations. `extractControlCharacters` removes empty line parts.
485 tokens = extractControlCharacters(lineContent, tokens);
486 }
487 > if (input.renderWhitespace === RenderWhitespace.All || viewLineRenderer.ts
488 input.renderWhitespace === RenderWhitespace.Boundary ||
489 (input.renderWhitespace === RenderWhitespace.Selection && !!input.selectionsOnLine) ||
490 (input.renderWhitespace === RenderWhitespace.Trailing && !input.continuesWithWrappedLine)
492 tokens = _applyRenderWhitespace(input, lineContent, len, tokens);
493 }
494 > let containsForeignElements = ForeignElementType.None; viewLineRenderer.ts
495 > if (input.lineDecorations.length > 0) {
496 for (let i = 0, len = input.lineDecorations.length; i < len; i++) {
497 const lineDecoration = input.lineDecorations[i];
507 tokens = _applyInlineDecorations(lineContent, len, tokens, input.lineDecorations);
508 }
509 > if (!input.containsRTL) { viewLineRenderer.ts
510 // We can never split RTL text, as it ruins the rendering
511 tokens = splitLargeTokens(lineContent, tokens, !input.isBasicASCII || input.fontLigatures);
512 > } else { viewLineRenderer.ts
513 // Split the first token if it contains both leading whitespace and RTL text
514 tokens = splitLeadingWhitespaceFromRTL(lineContent, tokens);
515 }
517 > return new ResolvedRenderLineInput(
518 > input.useMonospaceOptimizations,
519 > input.canUseHalfwidthRightwardsArrow,
520 > lineContent,
521 > len,
522 > isOverflowing,
523 > overflowingCharCount,
524 > tokens,
525 > containsForeignElements,
526 > input.fauxIndentLength,
527 > input.tabSize,
528 > input.startVisibleColumn,
529 > input.spaceWidth,
530 > input.renderSpaceCharCode,
531 > input.renderWhitespace,
532 > input.renderControlCharacters
533 > );
534 > }
535
536 /**
538 * Ensure that all tokens end before `len` and the last one ends precisely at `len`.
539 */
540 > function transformAndRemoveOverflowing(lineContent: string, lineContainsRTL: boolean, tokens: IViewLineTokens, fauxIndentLength: number, len: number): LinePart[] { viewLineRenderer.ts
541 > const result: LinePart[] = [];
542 > let resultLen = 0;
543 >
544 > // The faux indent part of the line should have no token type
545 > if (fauxIndentLength > 0) {
546 result[resultLen++] = new LinePart(fauxIndentLength, '', 0, false);
547 }
548 > let startOffset = fauxIndentLength; viewLineRenderer.ts
549 > for (let tokenIndex = 0, tokensLen = tokens.getCount(); tokenIndex < tokensLen; tokenIndex++) {
550 > const endIndex = tokens.getEndOffset(tokenIndex);
551 > if (endIndex <= fauxIndentLength) {
552 // The faux indent part of the line should have no token type
553 continue;
554 }
555 > const type = tokens.getClassName(tokenIndex); viewLineRenderer.ts
556 > if (endIndex >= len) {
557 > const tokenContainsRTL = (lineContainsRTL ? strings.containsRTL(lineContent.substring(startOffset, len)) : false);
558 > result[resultLen++] = new LinePart(len, type, 0, tokenContainsRTL);
559 > break;
560 > }
561 > const tokenContainsRTL = (lineContainsRTL ? strings.containsRTL(lineContent.substring(startOffset, endIndex)) : false);
562 > result[resultLen++] = new LinePart(endIndex, type, 0, tokenContainsRTL);
563 > startOffset = endIndex;
564 > }
565 >
566 > return result;
567 > }
568
569 /**
977 * Notice how all the needed data is fully resolved and passed in (i.e. no other calls).
978 */
979 > function _renderLine(input: ResolvedRenderLineInput, sb: StringBuilder): RenderLineOutput { viewLineRenderer.ts
980 > const fontIsMonospace = input.fontIsMonospace;
981 > const canUseHalfwidthRightwardsArrow = input.canUseHalfwidthRightwardsArrow;
982 > const containsForeignElements = input.containsForeignElements;
983 > const lineContent = input.lineContent;
984 > const len = input.len;
985 > const isOverflowing = input.isOverflowing;
986 > const overflowingCharCount = input.overflowingCharCount;
987 > const parts = input.parts;
988 > const fauxIndentLength = input.fauxIndentLength;
989 > const tabSize = input.tabSize;
990 > const startVisibleColumn = input.startVisibleColumn;
991 > const spaceWidth = input.spaceWidth;
992 > const renderSpaceCharCode = input.renderSpaceCharCode;
993 > const renderWhitespace = input.renderWhitespace;
994 > const renderControlCharacters = input.renderControlCharacters;
995 >
996 > const characterMapping = new CharacterMapping(len + 1, parts.length);
997 > let lastCharacterMappingDefined = false;
998 >
999 > let charIndex = 0;
1000 > let visibleColumn = startVisibleColumn;
1001 > let charOffsetInPart = 0; // the character offset in the current part
1002 > let charHorizontalOffset = 0; // the character horizontal position in terms of chars relative to line start
1003 >
1004 > let partDisplacement = 0;
1005 >
1006 > sb.appendString('<span>');
1007 >
1008 > for (let partIndex = 0, tokensLen = parts.length; partIndex < tokensLen; partIndex++) {
1009 >
1010 > const part = parts[partIndex];
1011 > const partEndIndex = part.endIndex;
1012 > const partType = part.type;
1013 > const partContainsRTL = part.containsRTL;
1014 > const partRendersWhitespace = (renderWhitespace !== RenderWhitespace.None && part.isWhitespace());
1015 > const partRendersWhitespaceWithWidth = partRendersWhitespace && !fontIsMonospace && (partType === 'mtkw'/*only whitespace*/ || !containsForeignElements);
1016 > const partIsEmptyAndHasPseudoAfter = (charIndex === partEndIndex && part.isPseudoAfter());
1017 > charOffsetInPart = 0;
1018 >
1019 > sb.appendString('<span ');
1020 > if (partContainsRTL) {
1021 sb.appendString('style="unicode-bidi:isolate" ');
1022 }
1023 > sb.appendString('class="'); viewLineRenderer.ts
1024 > sb.appendString(partRendersWhitespaceWithWidth ? 'mtkz' : partType);
1025 > sb.appendASCIICharCode(CharCode.DoubleQuote);
1026 >
1027 > if (partRendersWhitespace) {
1028
1029 let partWidth = 0;
1085 }
1086
1087 > } else { viewLineRenderer.ts
1088
1089 sb.appendASCIICharCode(CharCode.GreaterThan);
1166 }
1167 }
1169 > if (partIsEmptyAndHasPseudoAfter) {
1170 partDisplacement++;
1171 > } else { viewLineRenderer.ts
1172 > partDisplacement = 0;
1173 > }
1174 >
1175 > if (charIndex >= len && !lastCharacterMappingDefined && part.isPseudoAfter()) {
1176 lastCharacterMappingDefined = true;
1177 characterMapping.setColumnInfo(charIndex + 1, partIndex, charOffsetInPart, charHorizontalOffset);
1178 }
1180 > sb.appendString('</span>');
1181 >
1182 > }
1183 >
1184 > if (!lastCharacterMappingDefined) {
1185 // When getting client rects for the last character, we will position the
1186 // text range at the end of the span, insteaf of at the beginning of next span
1187 characterMapping.setColumnInfo(len + 1, parts.length - 1, charOffsetInPart, charHorizontalOffset);
1188 }
1190 > if (isOverflowing) {
1191 sb.appendString('<span class="mtkoverflow">');
1192 sb.appendString(nls.localize('showMore', "Show more ({0})", renderOverflowingCharCount(overflowingCharCount)));
1193 sb.appendString('</span>');
1194 }
1196 > sb.appendString('</span>');
1197 >
1198 > return new RenderLineOutput(characterMapping, containsForeignElements);
1199 > }
1200
1201 function to4CharHex(n: number): string {
src/vs/editor/common/viewLayout/linePart.ts 10 introduced LOC · 2 ranges

Open complete file

18
19 constructor(
20 > /** linePart.ts
21 > * last char index of this token (not inclusive).
22 > */
23 > public readonly endIndex: number,
24 > public readonly type: string,
25 > public readonly metadata: number,
26 > public readonly containsRTL: boolean
27 > ) { }
28
29 public isWhitespace(): boolean {
32
33 public isPseudoAfter(): boolean {
34 > return (this.metadata & LinePartMetadata.PSEUDO_AFTER_MASK ? true : false); linePart.ts
35 > }
36 }
src/vs/editor/common/core/stringBuilder.ts 6 introduced LOC · 2 ranges

Open complete file

107 */
108 public appendCharCode(charCode: number): void {
109 > const remainingSpace = this._capacity - this._bufferLength; stringBuilder.ts
110 >
111 > if (remainingSpace <= 1) {
112 if (remainingSpace === 0 || strings.isHighSurrogate(charCode)) {
113 this._flushBuffer();
114 }
115 }
117 > this._buffer[this._bufferLength++] = charCode;
118 > }
119
120 /**
src/vs/editor/test/common/core/testLineToken.ts 2 introduced LOC · 1 range

Open complete file

98
99 public getClassName(tokenIndex: number): string {
100 > return this._actual[tokenIndex].getType(); testLineToken.ts
101 > }
102
103 public getInlineStyle(tokenIndex: number, colorMap: string[]): string {