提交 0a975359 编写于 作者: A Alex Dima

Fixes #38123

上级 9eef194c
......@@ -191,6 +191,7 @@ export class ViewLine implements IVisibleLine {
let renderLineInput = new RenderLineInput(
options.useMonospaceOptimizations,
lineData.content,
lineData.continuesWithWrappedLine,
lineData.isBasicASCII,
lineData.containsRTL,
lineData.minColumn - 1,
......@@ -230,7 +231,7 @@ export class ViewLine implements IVisibleLine {
// Another rounding error has been observed on Linux in VSCode, where <span> width
// rounding errors add up to an observable large number...
// ---
// Also see another example of rounding errors on Windows in
// Also see another example of rounding errors on Windows in
// https://github.com/Microsoft/vscode/issues/33178
renderedViewLine = new FastRenderedViewLine(
this._renderedViewLine ? this._renderedViewLine.domNode : null,
......
......@@ -1989,6 +1989,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
const output = renderViewLine(new RenderLineInput(
(config.fontInfo.isMonospace && !config.viewInfo.disableMonospaceOptimizations),
lineContent,
false,
isBasicASCII,
containsRTL,
0,
......
......@@ -769,6 +769,7 @@ export class DiffReview extends Disposable {
const r = renderViewLine(new RenderLineInput(
(config.fontInfo.isMonospace && !config.viewInfo.disableMonospaceOptimizations),
lineContent,
false,
isBasicASCII,
containsRTL,
0,
......
......@@ -36,6 +36,7 @@ export class RenderLineInput {
public readonly useMonospaceOptimizations: boolean;
public readonly lineContent: string;
public readonly continuesWithWrappedLine: boolean;
public readonly isBasicASCII: boolean;
public readonly containsRTL: boolean;
public readonly fauxIndentLength: number;
......@@ -51,6 +52,7 @@ export class RenderLineInput {
constructor(
useMonospaceOptimizations: boolean,
lineContent: string,
continuesWithWrappedLine: boolean,
isBasicASCII: boolean,
containsRTL: boolean,
fauxIndentLength: number,
......@@ -65,6 +67,7 @@ export class RenderLineInput {
) {
this.useMonospaceOptimizations = useMonospaceOptimizations;
this.lineContent = lineContent;
this.continuesWithWrappedLine = continuesWithWrappedLine;
this.isBasicASCII = isBasicASCII;
this.containsRTL = containsRTL;
this.fauxIndentLength = fauxIndentLength;
......@@ -88,6 +91,7 @@ export class RenderLineInput {
return (
this.useMonospaceOptimizations === other.useMonospaceOptimizations
&& this.lineContent === other.lineContent
&& this.continuesWithWrappedLine === other.continuesWithWrappedLine
&& this.isBasicASCII === other.isBasicASCII
&& this.containsRTL === other.containsRTL
&& this.fauxIndentLength === other.fauxIndentLength
......@@ -331,7 +335,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
let tokens = transformAndRemoveOverflowing(input.lineTokens, input.fauxIndentLength, len);
if (input.renderWhitespace === RenderWhitespace.All || input.renderWhitespace === RenderWhitespace.Boundary) {
tokens = _applyRenderWhitespace(lineContent, len, tokens, input.fauxIndentLength, input.tabSize, useMonospaceOptimizations, input.renderWhitespace === RenderWhitespace.Boundary);
tokens = _applyRenderWhitespace(lineContent, len, input.continuesWithWrappedLine, tokens, input.fauxIndentLength, input.tabSize, useMonospaceOptimizations, input.renderWhitespace === RenderWhitespace.Boundary);
}
let containsForeignElements = ForeignElementType.None;
if (input.lineDecorations.length > 0) {
......@@ -437,7 +441,7 @@ function splitLargeTokens(lineContent: string, tokens: LinePart[]): LinePart[] {
* Moreover, a token is created for every visual indent because on some fonts the glyphs used for rendering whitespace (&rarr; or &middot;) do not have the same width as &nbsp;.
* The rendering phase will generate `style="width:..."` for these tokens.
*/
function _applyRenderWhitespace(lineContent: string, len: number, tokens: LinePart[], fauxIndentLength: number, tabSize: number, useMonospaceOptimizations: boolean, onlyBoundary: boolean): LinePart[] {
function _applyRenderWhitespace(lineContent: string, len: number, continuesWithWrappedLine: boolean, tokens: LinePart[], fauxIndentLength: number, tabSize: number, useMonospaceOptimizations: boolean, onlyBoundary: boolean): LinePart[] {
let result: LinePart[] = [], resultLen = 0;
let tokenIndex = 0;
......@@ -527,14 +531,23 @@ function _applyRenderWhitespace(lineContent: string, len: number, tokens: LinePa
}
}
let generateWhitespace = false;
if (wasInWhitespace) {
// was in whitespace token
result[resultLen++] = new LinePart(len, 'vs-whitespace');
} else {
// was in regular token
result[resultLen++] = new LinePart(len, tokenType);
if (continuesWithWrappedLine && onlyBoundary) {
let lastCharCode = (len > 0 ? lineContent.charCodeAt(len - 1) : CharCode.Null);
let prevCharCode = (len > 1 ? lineContent.charCodeAt(len - 2) : CharCode.Null);
let isSingleTrailingSpace = (lastCharCode === CharCode.Space && (prevCharCode !== CharCode.Space && prevCharCode !== CharCode.Tab));
if (!isSingleTrailingSpace) {
generateWhitespace = true;
}
} else {
generateWhitespace = true;
}
}
result[resultLen++] = new LinePart(len, generateWhitespace ? 'vs-whitespace' : tokenType);
return result;
}
......
......@@ -884,6 +884,7 @@ class VisibleIdentitySplitLine implements ISplitLine {
let lineContent = lineTokens.getLineContent();
return new ViewLineData(
lineContent,
false,
1,
lineContent.length + 1,
lineTokens.inflate()
......@@ -1087,6 +1088,8 @@ export class SplitLine implements ISplitLine {
let minColumn = (outputLineIndex > 0 ? this.wrappedIndentLength + 1 : 1);
let maxColumn = lineContent.length + 1;
let continuesWithWrappedLine = (outputLineIndex + 1 < this.getViewLineCount());
let deltaStartIndex = 0;
if (outputLineIndex > 0) {
deltaStartIndex = this.wrappedIndentLength;
......@@ -1095,6 +1098,7 @@ export class SplitLine implements ISplitLine {
return new ViewLineData(
lineContent,
continuesWithWrappedLine,
minColumn,
maxColumn,
lineTokens.sliceAndInflate(startOffset, endOffset, deltaStartIndex)
......@@ -1318,6 +1322,7 @@ export class IdentityLinesCollection implements IViewModelLinesCollection {
let lineContent = lineTokens.getLineContent();
return new ViewLineData(
lineContent,
false,
1,
lineContent.length + 1,
lineTokens.inflate()
......
......@@ -172,6 +172,10 @@ export class ViewLineData {
* The content at this view line.
*/
public readonly content: string;
/**
* Does this line continue with a wrapped line?
*/
public readonly continuesWithWrappedLine: boolean;
/**
* The minimum allowed column at this view line.
*/
......@@ -187,11 +191,13 @@ export class ViewLineData {
constructor(
content: string,
continuesWithWrappedLine: boolean,
minColumn: number,
maxColumn: number,
tokens: IViewLineTokens
) {
this.content = content;
this.continuesWithWrappedLine = continuesWithWrappedLine;
this.minColumn = minColumn;
this.maxColumn = maxColumn;
this.tokens = tokens;
......@@ -211,6 +217,10 @@ export class ViewLineRenderingData {
* The content at this view line.
*/
public readonly content: string;
/**
* Does this line continue with a wrapped line?
*/
public readonly continuesWithWrappedLine: boolean;
/**
* Describes if `content` contains RTL characters.
*/
......@@ -236,6 +246,7 @@ export class ViewLineRenderingData {
minColumn: number,
maxColumn: number,
content: string,
continuesWithWrappedLine: boolean,
mightContainRTL: boolean,
mightContainNonBasicASCII: boolean,
tokens: IViewLineTokens,
......@@ -245,6 +256,7 @@ export class ViewLineRenderingData {
this.minColumn = minColumn;
this.maxColumn = maxColumn;
this.content = content;
this.continuesWithWrappedLine = continuesWithWrappedLine;
this.isBasicASCII = ViewLineRenderingData.isBasicASCII(content, mightContainNonBasicASCII);
this.containsRTL = ViewLineRenderingData.containsRTL(content, this.isBasicASCII, mightContainRTL);
......
......@@ -508,6 +508,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
lineData.minColumn,
lineData.maxColumn,
lineData.content,
lineData.continuesWithWrappedLine,
mightContainRTL,
mightContainNonBasicASCII,
lineData.tokens,
......
......@@ -100,6 +100,7 @@ export class Colorizer {
let renderResult = renderViewLine(new RenderLineInput(
false,
line,
false,
isBasicASCII,
containsRTL,
0,
......@@ -152,6 +153,7 @@ function _fakeColorize(lines: string[], tabSize: number): string {
let renderResult = renderViewLine(new RenderLineInput(
false,
line,
false,
isBasicASCII,
containsRTL,
0,
......@@ -186,6 +188,7 @@ function _actualColorize(lines: string[], tabSize: number, tokenizationSupport:
let renderResult = renderViewLine(new RenderLineInput(
false,
line,
false,
isBasicASCII,
containsRTL,
0,
......
......@@ -30,6 +30,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
false,
lineContent,
false,
strings.isBasicASCII(lineContent),
false,
0,
......@@ -77,6 +78,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
false,
lineContent,
false,
true,
false,
0,
......@@ -114,6 +116,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
false,
'Hello world!',
false,
true,
false,
0,
......@@ -216,6 +219,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
false,
lineText,
false,
true,
false,
0,
......@@ -276,6 +280,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
false,
lineText,
false,
true,
false,
0,
......@@ -336,6 +341,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
false,
lineText,
false,
true,
false,
0,
......@@ -374,6 +380,7 @@ suite('viewLineRenderer.renderLine', () => {
false,
lineText,
false,
false,
true,
0,
lineParts,
......@@ -401,6 +408,7 @@ suite('viewLineRenderer.renderLine', () => {
let actual = renderViewLine(new RenderLineInput(
false,
lineText,
false,
true,
false,
0,
......@@ -499,6 +507,7 @@ suite('viewLineRenderer.renderLine', () => {
let actual = renderViewLine(new RenderLineInput(
false,
lineText,
false,
true,
false,
0,
......@@ -535,6 +544,7 @@ suite('viewLineRenderer.renderLine', () => {
lineText,
false,
false,
false,
0,
lineParts,
[],
......@@ -561,6 +571,7 @@ suite('viewLineRenderer.renderLine', () => {
false,
lineText,
false,
false,
true,
0,
lineParts,
......@@ -604,6 +615,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
true,
lineText,
false,
true,
false,
4,
......@@ -685,6 +697,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
fontIsMonospace,
lineContent,
false,
true,
false,
fauxIndentLength,
......@@ -708,6 +721,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
false,
lineContent,
false,
true,
false,
0,
......@@ -737,6 +751,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
true,
lineContent,
false,
true,
false,
0,
......@@ -1002,6 +1017,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
false,
'Hello world',
false,
true,
false,
0,
......@@ -1044,6 +1060,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
false,
lineContent,
false,
true,
false,
0,
......@@ -1074,6 +1091,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
false,
lineContent,
false,
true,
false,
0,
......@@ -1105,6 +1123,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
false,
lineContent,
false,
true,
false,
0,
......@@ -1134,6 +1153,7 @@ suite('viewLineRenderer.renderLine 2', () => {
' 1. 🙏',
false,
false,
false,
0,
createViewLineTokens([createPart(7, 3)]),
[new LineDecoration(7, 8, 'inline-folded', InlineDecorationType.After)],
......@@ -1160,6 +1180,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
true,
'',
false,
true,
false,
0,
......@@ -1190,6 +1211,7 @@ suite('viewLineRenderer.renderLine 2', () => {
let actual = renderViewLine(new RenderLineInput(
true,
'\t}',
false,
true,
false,
0,
......@@ -1223,6 +1245,7 @@ suite('viewLineRenderer.renderLine 2', () => {
'asd = "擦"\t\t#asd',
false,
false,
false,
0,
createViewLineTokens([createPart(15, 3)]),
[],
......@@ -1250,6 +1273,7 @@ suite('viewLineRenderer.renderLine 2', () => {
'asd = "擦"\t\t#asd',
false,
false,
false,
0,
createViewLineTokens([createPart(15, 3)]),
[],
......@@ -1283,6 +1307,7 @@ suite('viewLineRenderer.renderLine 2', () => {
'12345689012345678901234568901234567890123456890abába',
false,
false,
false,
0,
createViewLineTokens([createPart(53, 3)]),
[],
......@@ -1310,6 +1335,7 @@ suite('viewLineRenderer.renderLine 2', () => {
' JoyShareல் பின்தொடர்ந்து, விடீயோ, ஜோக்குகள், அனிமேசன், நகைச்சுவை படங்கள் மற்றும் செய்திகளை பெறுவீர்',
false,
false,
false,
0,
createViewLineTokens([createPart(100, 3)]),
[],
......@@ -1341,6 +1367,7 @@ suite('viewLineRenderer.renderLine 2', () => {
' वो ऐसा क्या है जो हमारे अंदर भी है और बाहर भी है। जिसकी वजह से हम सब हैं। जिसने इस सृष्टि की रचना की है।',
false,
false,
false,
0,
createViewLineTokens([createPart(105, 3)]),
[],
......@@ -1361,10 +1388,38 @@ suite('viewLineRenderer.renderLine 2', () => {
assert.deepEqual(actual.html, expected);
});
test('issue #38123: editor.renderWhitespace: "boundary" renders whitespace at line wrap point when line is wrapped', () => {
let actual = renderViewLine(new RenderLineInput(
true,
'This is a long line which never uses more than two spaces. ',
true,
true,
false,
0,
createViewLineTokens([createPart(59, 3)]),
[],
4,
10,
10000,
'boundary',
false,
false
));
let expected = [
'<span>',
'<span class="mtk3">This\u00a0is\u00a0a\u00a0long\u00a0line\u00a0which\u00a0never\u00a0uses\u00a0more\u00a0than\u00a0two</span><span class="mtk3">\u00a0spaces.</span><span class="mtk3">\u00a0</span>',
'</span>'
].join('');
assert.deepEqual(actual.html, expected);
});
function createTestGetColumnOfLinePartOffset(lineContent: string, tabSize: number, parts: ViewLineToken[], expectedPartLengths: number[]): (partIndex: number, partLength: number, offset: number, expected: number) => void {
let renderLineOutput = renderViewLine(new RenderLineInput(
false,
lineContent,
false,
true,
false,
0,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册