diff --git a/src/vs/editor/browser/standalone/colorizer.ts b/src/vs/editor/browser/standalone/colorizer.ts index f6ee43ac3c337201a2f562afa871806d546decb0..2351deff158e7bad7dfa471026cb8dfd697938b8 100644 --- a/src/vs/editor/browser/standalone/colorizer.ts +++ b/src/vs/editor/browser/standalone/colorizer.ts @@ -106,6 +106,7 @@ export class Colorizer { 0, -1, 'none', + false, false )); return renderResult.html; @@ -147,6 +148,7 @@ function _fakeColorize(lines: string[], tabSize: number): string { 0, -1, 'none', + false, false )); @@ -176,6 +178,7 @@ function _actualColorize(lines: string[], tabSize: number, tokenizationSupport: 0, -1, 'none', + false, false )); diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index fa86a5736bd006bbb5b8e4b08cfcd2596531c5ab..ce0129686467ebad262894de8b65925e094d7f18 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -72,6 +72,7 @@ export class ViewLineOptions { public readonly useMonospaceOptimizations: boolean; public readonly lineHeight: number; public readonly stopRenderingLineAfter: number; + public readonly fontLigatures: boolean; constructor(config: IConfiguration) { this.renderWhitespace = config.editor.viewInfo.renderWhitespace; @@ -83,6 +84,7 @@ export class ViewLineOptions { ); this.lineHeight = config.editor.lineHeight; this.stopRenderingLineAfter = config.editor.viewInfo.stopRenderingLineAfter; + this.fontLigatures = config.editor.viewInfo.fontLigatures; } public equals(other: ViewLineOptions): boolean { @@ -93,6 +95,7 @@ export class ViewLineOptions { && this.useMonospaceOptimizations === other.useMonospaceOptimizations && this.lineHeight === other.lineHeight && this.stopRenderingLineAfter === other.stopRenderingLineAfter + && this.fontLigatures === other.fontLigatures ); } } @@ -161,7 +164,8 @@ export class ViewLine implements IVisibleLine { options.spaceWidth, options.stopRenderingLineAfter, options.renderWhitespace, - options.renderControlCharacters + options.renderControlCharacters, + options.fontLigatures ); if (this._renderedViewLine && this._renderedViewLine.input.equals(renderLineInput)) { diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 6756bd1d61066ff620a8419b7584df282cab3e73..0258ad23dc9fe11a4b53b7a5323111b4ced62ca8 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -1930,7 +1930,8 @@ class InlineViewZonesComputer extends ViewZonesComputer { config.fontInfo.spaceWidth, config.viewInfo.stopRenderingLineAfter, config.viewInfo.renderWhitespace, - config.viewInfo.renderControlCharacters + config.viewInfo.renderControlCharacters, + config.viewInfo.fontLigatures )); let myResult: string[] = []; diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 607a21568943b9cff853003ead4607302ff7b27b..20e48152f1ab86b8a0383f6233ea5e3606dec3cf 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -290,6 +290,7 @@ class InternalEditorOptionsHelper { stopRenderingLineAfter: stopRenderingLineAfter, renderWhitespace: renderWhitespace, renderControlCharacters: toBoolean(opts.renderControlCharacters), + fontLigatures: toBoolean(opts.fontLigatures), renderIndentGuides: toBoolean(opts.renderIndentGuides), renderLineHighlight: renderLineHighlight, scrollbar: scrollbar, diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 036352e35dd3e49bbc3359d6981dcde7896516ed..a0008d9be6dbd043ad86c9563add42a925c248be 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -788,6 +788,7 @@ export class InternalEditorViewOptions { readonly stopRenderingLineAfter: number; readonly renderWhitespace: 'none' | 'boundary' | 'all'; readonly renderControlCharacters: boolean; + readonly fontLigatures: boolean; readonly renderIndentGuides: boolean; readonly renderLineHighlight: 'none' | 'gutter' | 'line' | 'all'; readonly scrollbar: InternalEditorScrollbarOptions; @@ -822,6 +823,7 @@ export class InternalEditorViewOptions { stopRenderingLineAfter: number; renderWhitespace: 'none' | 'boundary' | 'all'; renderControlCharacters: boolean; + fontLigatures: boolean; renderIndentGuides: boolean; renderLineHighlight: 'none' | 'gutter' | 'line' | 'all'; scrollbar: InternalEditorScrollbarOptions; @@ -852,6 +854,7 @@ export class InternalEditorViewOptions { this.stopRenderingLineAfter = source.stopRenderingLineAfter | 0; this.renderWhitespace = source.renderWhitespace; this.renderControlCharacters = Boolean(source.renderControlCharacters); + this.fontLigatures = Boolean(source.fontLigatures); this.renderIndentGuides = Boolean(source.renderIndentGuides); this.renderLineHighlight = source.renderLineHighlight; this.scrollbar = source.scrollbar.clone(); @@ -916,6 +919,7 @@ export class InternalEditorViewOptions { && this.stopRenderingLineAfter === other.stopRenderingLineAfter && this.renderWhitespace === other.renderWhitespace && this.renderControlCharacters === other.renderControlCharacters + && this.fontLigatures === other.fontLigatures && this.renderIndentGuides === other.renderIndentGuides && this.renderLineHighlight === other.renderLineHighlight && this.scrollbar.equals(other.scrollbar) @@ -953,6 +957,7 @@ export class InternalEditorViewOptions { stopRenderingLineAfter: this.stopRenderingLineAfter !== newOpts.stopRenderingLineAfter, renderWhitespace: this.renderWhitespace !== newOpts.renderWhitespace, renderControlCharacters: this.renderControlCharacters !== newOpts.renderControlCharacters, + fontLigatures: this.fontLigatures !== newOpts.fontLigatures, renderIndentGuides: this.renderIndentGuides !== newOpts.renderIndentGuides, renderLineHighlight: this.renderLineHighlight !== newOpts.renderLineHighlight, scrollbar: (!this.scrollbar.equals(newOpts.scrollbar)), @@ -994,6 +999,7 @@ export interface IViewConfigurationChangedEvent { readonly stopRenderingLineAfter: boolean; readonly renderWhitespace: boolean; readonly renderControlCharacters: boolean; + readonly fontLigatures: boolean; readonly renderIndentGuides: boolean; readonly renderLineHighlight: boolean; readonly scrollbar: boolean; diff --git a/src/vs/editor/common/viewLayout/viewLineRenderer.ts b/src/vs/editor/common/viewLayout/viewLineRenderer.ts index aee872058b313455ae68d74f07dc7fc1d483e23b..a710a13fe006e2c5868481b83b6c446e7053060c 100644 --- a/src/vs/editor/common/viewLayout/viewLineRenderer.ts +++ b/src/vs/editor/common/viewLayout/viewLineRenderer.ts @@ -43,6 +43,7 @@ export class RenderLineInput { public readonly stopRenderingLineAfter: number; public readonly renderWhitespace: RenderWhitespace; public readonly renderControlCharacters: boolean; + public readonly fontLigatures: boolean; constructor( useMonospaceOptimizations: boolean, @@ -56,6 +57,7 @@ export class RenderLineInput { stopRenderingLineAfter: number, renderWhitespace: 'none' | 'boundary' | 'all', renderControlCharacters: boolean, + fontLigatures: boolean ) { this.useMonospaceOptimizations = useMonospaceOptimizations; this.lineContent = lineContent; @@ -74,6 +76,7 @@ export class RenderLineInput { : RenderWhitespace.None ); this.renderControlCharacters = renderControlCharacters; + this.fontLigatures = fontLigatures; } public equals(other: RenderLineInput): boolean { @@ -87,6 +90,7 @@ export class RenderLineInput { && this.stopRenderingLineAfter === other.stopRenderingLineAfter && this.renderWhitespace === other.renderWhitespace && this.renderControlCharacters === other.renderControlCharacters + && this.fontLigatures === other.fontLigatures && LineDecoration.equalsArr(this.lineDecorations, other.lineDecorations) && ViewLineToken.equalsArr(this.lineTokens, other.lineTokens) ); @@ -297,7 +301,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput if (input.mightContainRTL) { containsRTL = strings.containsRTL(lineContent); } - if (!containsRTL) { + if (!containsRTL && !input.fontLigatures) { tokens = splitLargeTokens(lineContent, tokens); } diff --git a/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts b/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts index ad4532369772184fdd10372e113a884fa45c1aa4..af3b6e1b8f963edfbef88cf7942565cedfb10a1a 100644 --- a/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts +++ b/src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts @@ -31,6 +31,7 @@ suite('viewLineRenderer.renderLine', () => { 0, -1, 'none', + false, false )); @@ -78,6 +79,7 @@ suite('viewLineRenderer.renderLine', () => { 0, -1, 'none', + false, false )); @@ -127,6 +129,7 @@ suite('viewLineRenderer.renderLine', () => { 10, 6, 'boundary', + false, false )); @@ -212,6 +215,7 @@ suite('viewLineRenderer.renderLine', () => { 10, -1, 'boundary', + false, false )); @@ -271,6 +275,7 @@ suite('viewLineRenderer.renderLine', () => { 10, -1, 'none', + false, false )); @@ -330,6 +335,7 @@ suite('viewLineRenderer.renderLine', () => { 10, -1, 'none', + false, false )); @@ -366,6 +372,7 @@ suite('viewLineRenderer.renderLine', () => { 10, -1, 'none', + false, false )); @@ -392,6 +399,7 @@ suite('viewLineRenderer.renderLine', () => { 10, -1, 'none', + false, false )); assert.equal(actual.html, '' + expectedOutput.join('') + '', message); @@ -469,6 +477,43 @@ suite('viewLineRenderer.renderLine', () => { } }); + test('issue #21476: Does not split large tokens when ligatures are on', () => { + // 1 1 1 + // 1 2 3 4 5 6 7 8 9 0 1 2 + // 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 + let _lineText = 'This is just a long line that contains very interesting text. This is just a long line that contains very interesting text.'; + + function assertSplitsTokens(message: string, lineText: string, expectedOutput: string[]): void { + let lineParts = [createPart(lineText.length, 1)]; + let actual = renderViewLine(new RenderLineInput( + false, + lineText, + false, + 0, + lineParts, + [], + 4, + 10, + -1, + 'none', + false, + true + )); + assert.equal(actual.html, '' + expectedOutput.join('') + '', message); + } + + // A token with 101 chars + { + assertSplitsTokens( + '101 chars', + _lineText.substr(0, 101), + [ + 'This is just a long line that contains very interesting text. This is just a long line that contains ', + ] + ); + } + }); + test('issue #20624: Unaligned surrogate pairs are corrupted at multiples of 50 columns', () => { let lineText = 'a𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷'; @@ -484,6 +529,7 @@ suite('viewLineRenderer.renderLine', () => { 10, -1, 'none', + false, false )); let expectedOutput = [ @@ -513,6 +559,7 @@ suite('viewLineRenderer.renderLine', () => { 10, -1, 'none', + false, false )); assert.equal(actual.html, '' + expectedOutput.join('') + ''); @@ -555,6 +602,7 @@ suite('viewLineRenderer.renderLine', () => { 10, -1, 'none', + false, false )); @@ -623,6 +671,7 @@ suite('viewLineRenderer.renderLine 2', () => { 10, -1, renderWhitespace, + false, false )); @@ -644,6 +693,7 @@ suite('viewLineRenderer.renderLine 2', () => { 10, -1, 'none', + false, false )); @@ -679,6 +729,7 @@ suite('viewLineRenderer.renderLine 2', () => { 10, -1, 'none', + false, false )); @@ -938,6 +989,7 @@ suite('viewLineRenderer.renderLine 2', () => { 10, -1, 'none', + false, false )); @@ -971,6 +1023,7 @@ suite('viewLineRenderer.renderLine 2', () => { 10, -1, 'none', + false, false )); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 0771928b6118ed52c10fa87cb18393cbac8ea17e..33e3dbe07e56da70134418f1b6254004528218f7 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1564,6 +1564,7 @@ declare module monaco.editor { readonly stopRenderingLineAfter: number; readonly renderWhitespace: 'none' | 'boundary' | 'all'; readonly renderControlCharacters: boolean; + readonly fontLigatures: boolean; readonly renderIndentGuides: boolean; readonly renderLineHighlight: 'none' | 'gutter' | 'line' | 'all'; readonly scrollbar: InternalEditorScrollbarOptions; @@ -1596,6 +1597,7 @@ declare module monaco.editor { readonly stopRenderingLineAfter: boolean; readonly renderWhitespace: boolean; readonly renderControlCharacters: boolean; + readonly fontLigatures: boolean; readonly renderIndentGuides: boolean; readonly renderLineHighlight: boolean; readonly scrollbar: boolean;