From 08dfb9ce9c680c3bccc8d7f282c82b7c676350e3 Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 13 Jan 2025 13:53:33 +0000 Subject: [PATCH 1/7] fix tab indentation --- .../renderer/decorators/blockify.test.ts | 100 +++++++++++++++ .../autoedits/renderer/decorators/blockify.ts | 83 +++++++++++++ .../renderer/decorators/default-decorator.ts | 116 ++++++------------ 3 files changed, 222 insertions(+), 77 deletions(-) create mode 100644 vscode/src/autoedits/renderer/decorators/blockify.test.ts create mode 100644 vscode/src/autoedits/renderer/decorators/blockify.ts diff --git a/vscode/src/autoedits/renderer/decorators/blockify.test.ts b/vscode/src/autoedits/renderer/decorators/blockify.test.ts new file mode 100644 index 000000000000..b4c4d53e0e30 --- /dev/null +++ b/vscode/src/autoedits/renderer/decorators/blockify.test.ts @@ -0,0 +1,100 @@ +import { describe, expect, it } from 'vitest' +import { document } from '../../../completions/test-helpers' +import { blockify } from './blockify' +import { AddedLinesDecorationInfo } from './default-decorator' + +describe('blockify', () => { + describe('space indentation', () => { + // Content doesn't matter here, just the fact that this document uses spaces + const mockSpacesDocument = document(' hello world\n goodbye world') + + it('removes leading space-indended blocks', () => { + const mockAddedLines: AddedLinesDecorationInfo[] = [ + { + afterLine: 0, + lineText: ' hello world', + ranges: [[5, 10]] + }, + { + afterLine: 1, + lineText: ' goodbye world', + ranges: [[5, 12]] + } + ] + + const text = blockify(mockSpacesDocument, mockAddedLines).map(({ lineText }) => lineText).join('\n') + expect(text).toMatchInlineSnapshot(` + "hello world   + goodbye world" + `) + }) + + it('removes leading space-indended blocks whilst maintaining indentation levels', () => { + const mockAddedLines: AddedLinesDecorationInfo[] = [ + { + afterLine: 0, + lineText: ' hello world', + ranges: [[5, 10]] + }, + { + afterLine: 1, + lineText: ' goodbye world', + ranges: [[9, 14]] + } + ] + + const text = blockify(mockSpacesDocument, mockAddedLines).map(({ lineText }) => lineText).join('\n') + expect(text).toMatchInlineSnapshot(` + "hello world       +     goodbye world" + `) + }) + }) + + describe('space indentation', () => { + // Content doesn't matter here, just the fact that this document uses tabs + const mockSpacesDocument = document('\thello world\n\tgoodbye world') + + it('removes leading space-indended blocks', () => { + const mockAddedLines: AddedLinesDecorationInfo[] = [ + { + afterLine: 0, + lineText: '\thello world', + ranges: [[5, 10]] + }, + { + afterLine: 1, + lineText: '\tgoodbye world', + ranges: [[5, 12]] + } + ] + + const text = blockify(mockSpacesDocument, mockAddedLines).map(({ lineText }) => lineText).join('\n') + expect(text).toMatchInlineSnapshot(` + "hello world   + goodbye world" + `) + }) + + it('removes leading space-indended blocks whilst maintaining indentation levels', () => { + const mockAddedLines: AddedLinesDecorationInfo[] = [ + { + afterLine: 0, + lineText: '\thello world', + ranges: [[5, 10]] + }, + { + afterLine: 1, + lineText: '\t\tgoodbye world', + ranges: [[9, 14]] + } + ] + + const text = blockify(mockSpacesDocument, mockAddedLines).map(({ lineText }) => lineText).join('\n') + expect(text).toMatchInlineSnapshot(` + "hello world       +     goodbye world" + `) + }) + }) +}) diff --git a/vscode/src/autoedits/renderer/decorators/blockify.ts b/vscode/src/autoedits/renderer/decorators/blockify.ts new file mode 100644 index 000000000000..157f8f7fcf8a --- /dev/null +++ b/vscode/src/autoedits/renderer/decorators/blockify.ts @@ -0,0 +1,83 @@ +import * as vscode from 'vscode' +import { getEditorTabSize } from '@sourcegraph/cody-shared' +import { AddedLinesDecorationInfo } from './default-decorator' +import detectIndent from 'detect-indent' + +export const UNICODE_SPACE = '\u00A0' + +export function blockify(document: vscode.TextDocument, addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { + const spaceAdjusted = convertToSpaceIndentation(document, addedLines) + const leadingRemoved = removeLeadingWhitespaceBlock(spaceAdjusted) + const paddingAdded = padTrailingWhitespaceBlock(leadingRemoved) + return paddingAdded +} + +export function convertToSpaceIndentation(document: vscode.TextDocument, addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { + const incomingIndentation = detectIndent(addedLines.map((line) => line.lineText).join('\n')).type + if (incomingIndentation === 'space') { + // Convert regular spaces to unicode spaces + return addedLines.map(line => ({ + ...line, + lineText: line.lineText.replace(/^( +)/, match => UNICODE_SPACE.repeat(match.length)) + })) + } + + const tabSize = getEditorTabSize(document.uri, vscode.workspace, vscode.window) + const tabAsSpace = UNICODE_SPACE.repeat(tabSize) + return addedLines.map(line => ({ + ...line, + lineText: line.lineText.replace(/^(\t+)/, match => tabAsSpace.repeat(match.length)) + })) +} + + +function padTrailingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { + let maxLineWidth = 0 + for (const addedLine of addedLines) { + maxLineWidth = Math.max(maxLineWidth, addedLine.lineText.length) + } + return addedLines.map(line => ({ + ...line, + lineText: line.lineText.padEnd(maxLineWidth, UNICODE_SPACE) + })) +} +function removeLeadingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { + let leastCommonWhitespacePrefix: undefined | string = undefined + for (const addedLine of addedLines) { + const leadingWhitespaceMatch = addedLine.lineText.match(/^\s*/) + if (leadingWhitespaceMatch === null) { + leastCommonWhitespacePrefix = '' + break + } + const leadingWhitespace = leadingWhitespaceMatch[0] + if (leastCommonWhitespacePrefix === undefined) { + leastCommonWhitespacePrefix = leadingWhitespace + continue + } + // get common prefix of leastCommonWhitespacePrefix and leadingWhitespace + leastCommonWhitespacePrefix = getCommonPrefix(leastCommonWhitespacePrefix, leadingWhitespace) + } + if (!leastCommonWhitespacePrefix) { + return addedLines + } + return addedLines.map(line => ({ + ...line, + lineText: line.lineText.replace(leastCommonWhitespacePrefix, ''), + ranges: line.ranges.map(([start, end]) => [ + start - leastCommonWhitespacePrefix.length, + end - leastCommonWhitespacePrefix.length + ]) + })) +} +function getCommonPrefix(s1: string, s2: string): string { + const minLength = Math.min(s1.length, s2.length) + let commonPrefix = '' + for (let i = 0; i < minLength; i++) { + if (s1[i] === s2[i]) { + commonPrefix += s1[i] + } else { + break + } + } + return commonPrefix +} diff --git a/vscode/src/autoedits/renderer/decorators/default-decorator.ts b/vscode/src/autoedits/renderer/decorators/default-decorator.ts index 6035c935288d..f2200d3a7b75 100644 --- a/vscode/src/autoedits/renderer/decorators/default-decorator.ts +++ b/vscode/src/autoedits/renderer/decorators/default-decorator.ts @@ -4,8 +4,10 @@ import { GHOST_TEXT_COLOR } from '../../../commands/GhostHintDecorator' import type { AutoEditsDecorator, DecorationInfo, ModifiedLineInfo } from './base' import { cssPropertiesToString } from './utils' +import { getEditorInsertSpaces, getEditorTabSize } from '@sourcegraph/cody-shared' +import { blockify } from './blockify' -interface AddedLinesDecorationInfo { +export interface AddedLinesDecorationInfo { ranges: [number, number][] afterLine: number lineText: string @@ -155,21 +157,47 @@ export class DefaultDecorator implements AutoEditsDecorator { } // todo (hitesh): handle case when too many lines to fit in the editor const oldLines = addedLinesInfo.map(info => this.editor.document.lineAt(info.afterLine)) - const replacerCol = Math.max(...oldLines.map(line => line.range.end.character)) + const longestLineValue = Math.max(...oldLines.map(line => line.range.end.character)) + const longestLine = oldLines.find(line => line.range.end.character === longestLineValue) + const replacerCol = this.getColumnPositions(longestLine!) const startLine = Math.min(...oldLines.map(line => line.lineNumber)) - this.renderAddedLinesDecorations(addedLinesInfo, startLine, replacerCol) + this.renderAddedLinesDecorations(addedLinesInfo, startLine, replacerCol.endColumn) + } + + private getColumnPositions( + line: vscode.TextLine + ): { startColumn: number; endColumn: number } { + const insertSpaces = getEditorInsertSpaces(this.editor.document.uri, vscode.workspace, vscode.window) + if (insertSpaces) { + return { startColumn: line.firstNonWhitespaceCharacterIndex, endColumn: line.range.end.character } + } + + // For files using tab-based indentation, we need special handling + // VSCode's Range API doesn't account for tab display width + // We need to: + // 1. Convert tabs to spaces based on editor tab size + // 2. Calculate the visual width including both indentation and content + const tabSize = getEditorTabSize(this.editor.document.uri, vscode.workspace, vscode.window) + const tabAsSpace = '\u00A0'.repeat(tabSize) + const firstNonWhitespaceCharacterIndex = line.firstNonWhitespaceCharacterIndex + const indentationText = line.text.substring(0, firstNonWhitespaceCharacterIndex) + const spaceAdjustedEndCharacter = indentationText.replaceAll(/\t/g, tabAsSpace).length + + (line.text.length - firstNonWhitespaceCharacterIndex) + + return { startColumn: firstNonWhitespaceCharacterIndex * tabSize, endColumn: spaceAdjustedEndCharacter } } private renderAddedLinesDecorations( - addedLinesInfo: AddedLinesDecorationInfo[], + _addedLinesInfo: AddedLinesDecorationInfo[], startLine: number, replacerCol: number ): void { - blockify(addedLinesInfo) + const addedLinesInfo = blockify(this.editor.document, _addedLinesInfo) const replacerDecorations: vscode.DecorationOptions[] = [] for (let i = 0; i < addedLinesInfo.length; i++) { const j = i + startLine const line = this.editor.document.lineAt(j) + const { startColumn, endColumn } = this.getColumnPositions(line) const decoration = addedLinesInfo[i] const decorationStyle = cssPropertiesToString({ // Absolutely position the suggested code so that the cursor does not jump there @@ -187,22 +215,16 @@ export class DefaultDecorator implements AutoEditsDecorator { // the cursor does not jump there. before: { contentText: - '\u00A0'.repeat(3) + - _replaceLeadingTrailingChars(decoration.lineText, ' ', '\u00A0'), - margin: `0 0 0 ${replacerCol - line.range.end.character}ch`, + '\u00A0'.repeat(3) + decoration.lineText, + margin: `0 0 0 ${replacerCol - endColumn}ch`, textDecoration: `none;${decorationStyle}`, }, // Create an empty HTML element with the width required to show the suggested code. // Required to make the viewport scrollable to view the suggestion if it's outside. after: { contentText: - '\u00A0'.repeat(3) + - _replaceLeadingTrailingChars( - decoration.lineText.replace(/\S/g, '\u00A0'), - ' ', - '\u00A0' - ), - margin: `0 0 0 ${replacerCol - line.range.end.character}ch`, + '\u00A0'.repeat(3) + decoration.lineText.replace(/\S/g, '\u00A0'), + margin: `0 0 0 ${replacerCol - endColumn}ch`, }, }, }) @@ -211,19 +233,11 @@ export class DefaultDecorator implements AutoEditsDecorator { range: new vscode.Range(j, replacerCol, j, replacerCol), renderOptions: { before: { - contentText: - '\u00A0' + - _replaceLeadingTrailingChars(decoration.lineText, ' ', '\u00A0'), + contentText: '\u00A0' + decoration.lineText, textDecoration: `none;${decorationStyle}`, }, after: { - contentText: - '\u00A0'.repeat(3) + - _replaceLeadingTrailingChars( - decoration.lineText.replace(/\S/g, '\u00A0'), - ' ', - '\u00A0' - ), + contentText:'\u00A0'.repeat(3) + decoration.lineText.replace(/\S/g, '\u00A0'), }, }, }) @@ -302,58 +316,6 @@ export function _replaceLeadingTrailingChars(str: string, oldS: string, newS: st return str } -function blockify(addedLines: AddedLinesDecorationInfo[]) { - removeLeadingWhitespaceBlock(addedLines) - padTrailingWhitespaceBlock(addedLines) -} - -function padTrailingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]) { - let maxLineWidth = 0 - for (const addedLine of addedLines) { - maxLineWidth = Math.max(maxLineWidth, addedLine.lineText.length) - } - for (const addedLine of addedLines) { - addedLine.lineText = addedLine.lineText.padEnd(maxLineWidth, ' ') - } -} - -function removeLeadingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]) { - let leastCommonWhitespacePrefix: undefined | string = undefined - for (const addedLine of addedLines) { - const leadingWhitespaceMatch = addedLine.lineText.match(/^\s*/) - if (leadingWhitespaceMatch === null) { - leastCommonWhitespacePrefix = '' - break - } - const leadingWhitespace = leadingWhitespaceMatch[0] - if (leastCommonWhitespacePrefix === undefined) { - leastCommonWhitespacePrefix = leadingWhitespace - continue - } - // get common prefix of leastCommonWhitespacePrefix and leadingWhitespace - leastCommonWhitespacePrefix = getCommonPrefix(leastCommonWhitespacePrefix, leadingWhitespace) - } - if (!leastCommonWhitespacePrefix) { - return - } - for (const addedLine of addedLines) { - addedLine.lineText = addedLine.lineText.replace(leastCommonWhitespacePrefix, '') - } -} - -function getCommonPrefix(s1: string, s2: string): string { - const minLength = Math.min(s1.length, s2.length) - let commonPrefix = '' - for (let i = 0; i < minLength; i++) { - if (s1[i] === s2[i]) { - commonPrefix += s1[i] - } else { - break - } - } - return commonPrefix -} - /** * Checks if the only changes for modified lines are additions of text. */ From fac67886b89243e2bae27458ec441ba48b08fc90 Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 13 Jan 2025 13:58:11 +0000 Subject: [PATCH 2/7] clean --- .../renderer/decorators/default-decorator.ts | 66 +++++-------------- 1 file changed, 18 insertions(+), 48 deletions(-) diff --git a/vscode/src/autoedits/renderer/decorators/default-decorator.ts b/vscode/src/autoedits/renderer/decorators/default-decorator.ts index f2200d3a7b75..63558ee21cc1 100644 --- a/vscode/src/autoedits/renderer/decorators/default-decorator.ts +++ b/vscode/src/autoedits/renderer/decorators/default-decorator.ts @@ -5,7 +5,7 @@ import { GHOST_TEXT_COLOR } from '../../../commands/GhostHintDecorator' import type { AutoEditsDecorator, DecorationInfo, ModifiedLineInfo } from './base' import { cssPropertiesToString } from './utils' import { getEditorInsertSpaces, getEditorTabSize } from '@sourcegraph/cody-shared' -import { blockify } from './blockify' +import { blockify, UNICODE_SPACE } from './blockify' export interface AddedLinesDecorationInfo { ranges: [number, number][] @@ -159,32 +159,33 @@ export class DefaultDecorator implements AutoEditsDecorator { const oldLines = addedLinesInfo.map(info => this.editor.document.lineAt(info.afterLine)) const longestLineValue = Math.max(...oldLines.map(line => line.range.end.character)) const longestLine = oldLines.find(line => line.range.end.character === longestLineValue) - const replacerCol = this.getColumnPositions(longestLine!) + const replacerCol = this.getReplacerColumn(longestLine!) const startLine = Math.min(...oldLines.map(line => line.lineNumber)) - this.renderAddedLinesDecorations(addedLinesInfo, startLine, replacerCol.endColumn) + this.renderAddedLinesDecorations(addedLinesInfo, startLine, replacerCol) } - private getColumnPositions( + private getReplacerColumn( line: vscode.TextLine - ): { startColumn: number; endColumn: number } { + ): number { const insertSpaces = getEditorInsertSpaces(this.editor.document.uri, vscode.workspace, vscode.window) if (insertSpaces) { - return { startColumn: line.firstNonWhitespaceCharacterIndex, endColumn: line.range.end.character } + // We can reliably use the range position for files using space characters + return line.range.end.character } - // For files using tab-based indentation, we need special handling + // For files using tab-based indentation, we need special handling. // VSCode's Range API doesn't account for tab display width // We need to: // 1. Convert tabs to spaces based on editor tab size // 2. Calculate the visual width including both indentation and content const tabSize = getEditorTabSize(this.editor.document.uri, vscode.workspace, vscode.window) - const tabAsSpace = '\u00A0'.repeat(tabSize) + const tabAsSpace = UNICODE_SPACE.repeat(tabSize) const firstNonWhitespaceCharacterIndex = line.firstNonWhitespaceCharacterIndex const indentationText = line.text.substring(0, firstNonWhitespaceCharacterIndex) const spaceAdjustedEndCharacter = indentationText.replaceAll(/\t/g, tabAsSpace).length + (line.text.length - firstNonWhitespaceCharacterIndex) - return { startColumn: firstNonWhitespaceCharacterIndex * tabSize, endColumn: spaceAdjustedEndCharacter } + return spaceAdjustedEndCharacter } private renderAddedLinesDecorations( @@ -197,7 +198,7 @@ export class DefaultDecorator implements AutoEditsDecorator { for (let i = 0; i < addedLinesInfo.length; i++) { const j = i + startLine const line = this.editor.document.lineAt(j) - const { startColumn, endColumn } = this.getColumnPositions(line) + const lineReplacerCol = this.getReplacerColumn(line) const decoration = addedLinesInfo[i] const decorationStyle = cssPropertiesToString({ // Absolutely position the suggested code so that the cursor does not jump there @@ -215,16 +216,17 @@ export class DefaultDecorator implements AutoEditsDecorator { // the cursor does not jump there. before: { contentText: - '\u00A0'.repeat(3) + decoration.lineText, - margin: `0 0 0 ${replacerCol - endColumn}ch`, + UNICODE_SPACE.repeat(3) + decoration.lineText, + margin: `0 0 0 ${replacerCol - lineReplacerCol}ch`, textDecoration: `none;${decorationStyle}`, }, // Create an empty HTML element with the width required to show the suggested code. // Required to make the viewport scrollable to view the suggestion if it's outside. after: { contentText: - '\u00A0'.repeat(3) + decoration.lineText.replace(/\S/g, '\u00A0'), - margin: `0 0 0 ${replacerCol - endColumn}ch`, + // Creates a spacer element with the same width as the suggested code to ensure proper scrolling + UNICODE_SPACE.repeat(3) + decoration.lineText.replace(/\S/g, UNICODE_SPACE), + margin: `0 0 0 ${replacerCol - lineReplacerCol}ch`, }, }, }) @@ -233,11 +235,11 @@ export class DefaultDecorator implements AutoEditsDecorator { range: new vscode.Range(j, replacerCol, j, replacerCol), renderOptions: { before: { - contentText: '\u00A0' + decoration.lineText, + contentText: UNICODE_SPACE + decoration.lineText, textDecoration: `none;${decorationStyle}`, }, after: { - contentText:'\u00A0'.repeat(3) + decoration.lineText.replace(/\S/g, '\u00A0'), + contentText:UNICODE_SPACE.repeat(3) + decoration.lineText.replace(/\S/g, UNICODE_SPACE), }, }, }) @@ -284,38 +286,6 @@ export class DefaultDecorator implements AutoEditsDecorator { } } -/** - * Replaces leading and trailing occurrences of a character with another string - * @param str The input string to process - * @param oldS The character to replace - * @param newS The character/string to replace with - * @returns The string with leading and trailing characters replaced - */ -export function _replaceLeadingTrailingChars(str: string, oldS: string, newS: string): string { - let prefixLen = str.length - for (let i = 0; i < str.length; i++) { - if (str[i] !== oldS) { - // str = newS.repeat(i) + str.substring(i) - prefixLen = i - break - } - } - str = newS.repeat(prefixLen) + str.substring(prefixLen) - - let suffixLen = str.length - for (let i = 0; i < str.length; i++) { - const j = str.length - 1 - i - if (str[j] !== oldS) { - // str = str.substring(0, j + 1) + newS.repeat(i) - suffixLen = i - break - } - } - str = str.substring(0, str.length - suffixLen) + newS.repeat(suffixLen) - - return str -} - /** * Checks if the only changes for modified lines are additions of text. */ From aa415568700f599677949f1d3cb083023788ebae Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 13 Jan 2025 14:48:23 +0000 Subject: [PATCH 3/7] update --- .../autoedits/renderer/decorators/blockify.test.ts | 4 ++-- vscode/src/autoedits/renderer/decorators/blockify.ts | 12 ++++++++---- .../renderer/decorators/default-decorator.ts | 9 +++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/vscode/src/autoedits/renderer/decorators/blockify.test.ts b/vscode/src/autoedits/renderer/decorators/blockify.test.ts index b4c4d53e0e30..40fbd5f37545 100644 --- a/vscode/src/autoedits/renderer/decorators/blockify.test.ts +++ b/vscode/src/autoedits/renderer/decorators/blockify.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' import { document } from '../../../completions/test-helpers' import { blockify } from './blockify' -import { AddedLinesDecorationInfo } from './default-decorator' +import type { AddedLinesDecorationInfo } from './default-decorator' describe('blockify', () => { describe('space indentation', () => { @@ -51,7 +51,7 @@ describe('blockify', () => { }) }) - describe('space indentation', () => { + describe('tab indentation', () => { // Content doesn't matter here, just the fact that this document uses tabs const mockSpacesDocument = document('\thello world\n\tgoodbye world') diff --git a/vscode/src/autoedits/renderer/decorators/blockify.ts b/vscode/src/autoedits/renderer/decorators/blockify.ts index 157f8f7fcf8a..2d177728eb61 100644 --- a/vscode/src/autoedits/renderer/decorators/blockify.ts +++ b/vscode/src/autoedits/renderer/decorators/blockify.ts @@ -1,6 +1,6 @@ import * as vscode from 'vscode' import { getEditorTabSize } from '@sourcegraph/cody-shared' -import { AddedLinesDecorationInfo } from './default-decorator' +import type { AddedLinesDecorationInfo } from './default-decorator' import detectIndent from 'detect-indent' export const UNICODE_SPACE = '\u00A0' @@ -15,13 +15,16 @@ export function blockify(document: vscode.TextDocument, addedLines: AddedLinesDe export function convertToSpaceIndentation(document: vscode.TextDocument, addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { const incomingIndentation = detectIndent(addedLines.map((line) => line.lineText).join('\n')).type if (incomingIndentation === 'space') { - // Convert regular spaces to unicode spaces + // In order to reliably render spaces in VS Code decorations, we must convert them to + // their unicode equivalent return addedLines.map(line => ({ ...line, - lineText: line.lineText.replace(/^( +)/, match => UNICODE_SPACE.repeat(match.length)) + lineText: line.lineText.replace(/^\s+/, match => UNICODE_SPACE.repeat(match.length)) })) } + // The incoming indentation is tab-based, but this will not render correctly in VS COde decorations. + // We must convert it to space indentation that matches the editor's tab size const tabSize = getEditorTabSize(document.uri, vscode.workspace, vscode.window) const tabAsSpace = UNICODE_SPACE.repeat(tabSize) return addedLines.map(line => ({ @@ -30,7 +33,6 @@ export function convertToSpaceIndentation(document: vscode.TextDocument, addedLi })) } - function padTrailingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { let maxLineWidth = 0 for (const addedLine of addedLines) { @@ -41,6 +43,7 @@ function padTrailingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): Add lineText: line.lineText.padEnd(maxLineWidth, UNICODE_SPACE) })) } + function removeLeadingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { let leastCommonWhitespacePrefix: undefined | string = undefined for (const addedLine of addedLines) { @@ -69,6 +72,7 @@ function removeLeadingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): A ]) })) } + function getCommonPrefix(s1: string, s2: string): string { const minLength = Math.min(s1.length, s2.length) let commonPrefix = '' diff --git a/vscode/src/autoedits/renderer/decorators/default-decorator.ts b/vscode/src/autoedits/renderer/decorators/default-decorator.ts index 13d360795a05..b621ea085aaa 100644 --- a/vscode/src/autoedits/renderer/decorators/default-decorator.ts +++ b/vscode/src/autoedits/renderer/decorators/default-decorator.ts @@ -260,13 +260,15 @@ export class DefaultDecorator implements AutoEditsDecorator { startLine: number, replacerCol: number ): void { - const addedLinesInfo = blockify(this.editor.document, _addedLinesInfo) + // Blockify the added lines so they are suitable to be rendered together as a VS Code decoration + const blockifiedAddedLines = blockify(this.editor.document, _addedLinesInfo) const replacerDecorations: vscode.DecorationOptions[] = [] - for (let i = 0; i < addedLinesInfo.length; i++) { + + for (let i = 0; i < blockifiedAddedLines.length; i++) { const j = i + startLine const line = this.editor.document.lineAt(j) const lineReplacerCol = this.getReplacerColumn(line) - const decoration = addedLinesInfo[i] + const decoration = blockifiedAddedLines[i] const decorationStyle = cssPropertiesToString({ // Absolutely position the suggested code so that the cursor does not jump there position: 'absolute', @@ -291,7 +293,6 @@ export class DefaultDecorator implements AutoEditsDecorator { // Required to make the viewport scrollable to view the suggestion if it's outside. after: { contentText: - // Creates a spacer element with the same width as the suggested code to ensure proper scrolling UNICODE_SPACE.repeat(3) + decoration.lineText.replace(/\S/g, UNICODE_SPACE), margin: `0 0 0 ${replacerCol - lineReplacerCol}ch`, }, From 78053290039e6e57609faffbe169c0b6dde19d8d Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 13 Jan 2025 15:00:46 +0000 Subject: [PATCH 4/7] format --- .../renderer/decorators/blockify.test.ts | 40 +++++++++++-------- .../autoedits/renderer/decorators/blockify.ts | 30 +++++++++----- .../renderer/decorators/default-decorator.ts | 27 ++++++++----- 3 files changed, 59 insertions(+), 38 deletions(-) diff --git a/vscode/src/autoedits/renderer/decorators/blockify.test.ts b/vscode/src/autoedits/renderer/decorators/blockify.test.ts index 40fbd5f37545..d9bb96c863e6 100644 --- a/vscode/src/autoedits/renderer/decorators/blockify.test.ts +++ b/vscode/src/autoedits/renderer/decorators/blockify.test.ts @@ -13,16 +13,18 @@ describe('blockify', () => { { afterLine: 0, lineText: ' hello world', - ranges: [[5, 10]] + ranges: [[5, 10]], }, { afterLine: 1, lineText: ' goodbye world', - ranges: [[5, 12]] - } + ranges: [[5, 12]], + }, ] - const text = blockify(mockSpacesDocument, mockAddedLines).map(({ lineText }) => lineText).join('\n') + const text = blockify(mockSpacesDocument, mockAddedLines) + .map(({ lineText }) => lineText) + .join('\n') expect(text).toMatchInlineSnapshot(` "hello world   goodbye world" @@ -34,16 +36,18 @@ describe('blockify', () => { { afterLine: 0, lineText: ' hello world', - ranges: [[5, 10]] + ranges: [[5, 10]], }, { afterLine: 1, lineText: ' goodbye world', - ranges: [[9, 14]] - } + ranges: [[9, 14]], + }, ] - const text = blockify(mockSpacesDocument, mockAddedLines).map(({ lineText }) => lineText).join('\n') + const text = blockify(mockSpacesDocument, mockAddedLines) + .map(({ lineText }) => lineText) + .join('\n') expect(text).toMatchInlineSnapshot(` "hello world           goodbye world" @@ -60,16 +64,18 @@ describe('blockify', () => { { afterLine: 0, lineText: '\thello world', - ranges: [[5, 10]] + ranges: [[5, 10]], }, { afterLine: 1, lineText: '\tgoodbye world', - ranges: [[5, 12]] - } + ranges: [[5, 12]], + }, ] - const text = blockify(mockSpacesDocument, mockAddedLines).map(({ lineText }) => lineText).join('\n') + const text = blockify(mockSpacesDocument, mockAddedLines) + .map(({ lineText }) => lineText) + .join('\n') expect(text).toMatchInlineSnapshot(` "hello world   goodbye world" @@ -81,16 +87,18 @@ describe('blockify', () => { { afterLine: 0, lineText: '\thello world', - ranges: [[5, 10]] + ranges: [[5, 10]], }, { afterLine: 1, lineText: '\t\tgoodbye world', - ranges: [[9, 14]] - } + ranges: [[9, 14]], + }, ] - const text = blockify(mockSpacesDocument, mockAddedLines).map(({ lineText }) => lineText).join('\n') + const text = blockify(mockSpacesDocument, mockAddedLines) + .map(({ lineText }) => lineText) + .join('\n') expect(text).toMatchInlineSnapshot(` "hello world           goodbye world" diff --git a/vscode/src/autoedits/renderer/decorators/blockify.ts b/vscode/src/autoedits/renderer/decorators/blockify.ts index 2d177728eb61..fa8625a92dd8 100644 --- a/vscode/src/autoedits/renderer/decorators/blockify.ts +++ b/vscode/src/autoedits/renderer/decorators/blockify.ts @@ -1,25 +1,31 @@ -import * as vscode from 'vscode' import { getEditorTabSize } from '@sourcegraph/cody-shared' -import type { AddedLinesDecorationInfo } from './default-decorator' import detectIndent from 'detect-indent' +import * as vscode from 'vscode' +import type { AddedLinesDecorationInfo } from './default-decorator' export const UNICODE_SPACE = '\u00A0' -export function blockify(document: vscode.TextDocument, addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { +export function blockify( + document: vscode.TextDocument, + addedLines: AddedLinesDecorationInfo[] +): AddedLinesDecorationInfo[] { const spaceAdjusted = convertToSpaceIndentation(document, addedLines) const leadingRemoved = removeLeadingWhitespaceBlock(spaceAdjusted) const paddingAdded = padTrailingWhitespaceBlock(leadingRemoved) return paddingAdded } -export function convertToSpaceIndentation(document: vscode.TextDocument, addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { - const incomingIndentation = detectIndent(addedLines.map((line) => line.lineText).join('\n')).type +export function convertToSpaceIndentation( + document: vscode.TextDocument, + addedLines: AddedLinesDecorationInfo[] +): AddedLinesDecorationInfo[] { + const incomingIndentation = detectIndent(addedLines.map(line => line.lineText).join('\n')).type if (incomingIndentation === 'space') { // In order to reliably render spaces in VS Code decorations, we must convert them to // their unicode equivalent return addedLines.map(line => ({ ...line, - lineText: line.lineText.replace(/^\s+/, match => UNICODE_SPACE.repeat(match.length)) + lineText: line.lineText.replace(/^\s+/, match => UNICODE_SPACE.repeat(match.length)), })) } @@ -29,7 +35,7 @@ export function convertToSpaceIndentation(document: vscode.TextDocument, addedLi const tabAsSpace = UNICODE_SPACE.repeat(tabSize) return addedLines.map(line => ({ ...line, - lineText: line.lineText.replace(/^(\t+)/, match => tabAsSpace.repeat(match.length)) + lineText: line.lineText.replace(/^(\t+)/, match => tabAsSpace.repeat(match.length)), })) } @@ -40,11 +46,13 @@ function padTrailingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): Add } return addedLines.map(line => ({ ...line, - lineText: line.lineText.padEnd(maxLineWidth, UNICODE_SPACE) + lineText: line.lineText.padEnd(maxLineWidth, UNICODE_SPACE), })) } -function removeLeadingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] { +function removeLeadingWhitespaceBlock( + addedLines: AddedLinesDecorationInfo[] +): AddedLinesDecorationInfo[] { let leastCommonWhitespacePrefix: undefined | string = undefined for (const addedLine of addedLines) { const leadingWhitespaceMatch = addedLine.lineText.match(/^\s*/) @@ -68,8 +76,8 @@ function removeLeadingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): A lineText: line.lineText.replace(leastCommonWhitespacePrefix, ''), ranges: line.ranges.map(([start, end]) => [ start - leastCommonWhitespacePrefix.length, - end - leastCommonWhitespacePrefix.length - ]) + end - leastCommonWhitespacePrefix.length, + ]), })) } diff --git a/vscode/src/autoedits/renderer/decorators/default-decorator.ts b/vscode/src/autoedits/renderer/decorators/default-decorator.ts index b621ea085aaa..a0e849e66637 100644 --- a/vscode/src/autoedits/renderer/decorators/default-decorator.ts +++ b/vscode/src/autoedits/renderer/decorators/default-decorator.ts @@ -2,10 +2,10 @@ import * as vscode from 'vscode' import { GHOST_TEXT_COLOR } from '../../../commands/GhostHintDecorator' +import { getEditorInsertSpaces, getEditorTabSize } from '@sourcegraph/cody-shared' import type { AutoEditsDecorator, DecorationInfo, ModifiedLineInfo } from './base' +import { UNICODE_SPACE, blockify } from './blockify' import { cssPropertiesToString } from './utils' -import { getEditorInsertSpaces, getEditorTabSize } from '@sourcegraph/cody-shared' -import { blockify, UNICODE_SPACE } from './blockify' export interface AddedLinesDecorationInfo { ranges: [number, number][] @@ -231,10 +231,12 @@ export class DefaultDecorator implements AutoEditsDecorator { } } - private getReplacerColumn( - line: vscode.TextLine - ): number { - const insertSpaces = getEditorInsertSpaces(this.editor.document.uri, vscode.workspace, vscode.window) + private getReplacerColumn(line: vscode.TextLine): number { + const insertSpaces = getEditorInsertSpaces( + this.editor.document.uri, + vscode.workspace, + vscode.window + ) if (insertSpaces) { // We can reliably use the range position for files using space characters return line.range.end.character @@ -249,7 +251,8 @@ export class DefaultDecorator implements AutoEditsDecorator { const tabAsSpace = UNICODE_SPACE.repeat(tabSize) const firstNonWhitespaceCharacterIndex = line.firstNonWhitespaceCharacterIndex const indentationText = line.text.substring(0, firstNonWhitespaceCharacterIndex) - const spaceAdjustedEndCharacter = indentationText.replaceAll(/\t/g, tabAsSpace).length + + const spaceAdjustedEndCharacter = + indentationText.replaceAll(/\t/g, tabAsSpace).length + (line.text.length - firstNonWhitespaceCharacterIndex) return spaceAdjustedEndCharacter @@ -284,8 +287,7 @@ export class DefaultDecorator implements AutoEditsDecorator { // Show the suggested code but keep it positioned absolute to ensure // the cursor does not jump there. before: { - contentText: - UNICODE_SPACE.repeat(3) + decoration.lineText, + contentText: UNICODE_SPACE.repeat(3) + decoration.lineText, margin: `0 0 0 ${replacerCol - lineReplacerCol}ch`, textDecoration: `none;${decorationStyle}`, }, @@ -293,7 +295,8 @@ export class DefaultDecorator implements AutoEditsDecorator { // Required to make the viewport scrollable to view the suggestion if it's outside. after: { contentText: - UNICODE_SPACE.repeat(3) + decoration.lineText.replace(/\S/g, UNICODE_SPACE), + UNICODE_SPACE.repeat(3) + + decoration.lineText.replace(/\S/g, UNICODE_SPACE), margin: `0 0 0 ${replacerCol - lineReplacerCol}ch`, }, }, @@ -307,7 +310,9 @@ export class DefaultDecorator implements AutoEditsDecorator { textDecoration: `none;${decorationStyle}`, }, after: { - contentText:UNICODE_SPACE.repeat(3) + decoration.lineText.replace(/\S/g, UNICODE_SPACE), + contentText: + UNICODE_SPACE.repeat(3) + + decoration.lineText.replace(/\S/g, UNICODE_SPACE), }, }, }) From 7e9234cb963560f66543d1c67d11ffec21901edd Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 13 Jan 2025 15:54:28 +0000 Subject: [PATCH 5/7] handle bug where replacerCol is also calculated incorrectly --- .../renderer/decorators/default-decorator.ts | 9 +++--- ...s-suffix-decoration-tab-indentation-23.png | Bin 0 -> 95350 bytes vscode/test/e2e/auto-edits.test.ts | 14 +++++++++ .../auto-edits/suffix-decoration-example-3.go | 28 ++++++++++++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 vscode/test/e2e/__snapshots__/auto-edits.test.ts/macos/autoedits-suffix-decoration-tab-indentation-23.png create mode 100644 vscode/test/fixtures/workspace/auto-edits/suffix-decoration-example-3.go diff --git a/vscode/src/autoedits/renderer/decorators/default-decorator.ts b/vscode/src/autoedits/renderer/decorators/default-decorator.ts index a0e849e66637..6e88613080b2 100644 --- a/vscode/src/autoedits/renderer/decorators/default-decorator.ts +++ b/vscode/src/autoedits/renderer/decorators/default-decorator.ts @@ -216,9 +216,8 @@ export class DefaultDecorator implements AutoEditsDecorator { const oldLines = addedLinesInfo .filter(info => info.afterLine < this.editor.document.lineCount) .map(info => this.editor.document.lineAt(info.afterLine)) - const longestLineValue = Math.max(...oldLines.map(line => line.range.end.character)) - const longestLine = oldLines.find(line => line.range.end.character === longestLineValue) - const replacerCol = this.getReplacerColumn(longestLine!) + + const replacerCol = Math.max(...oldLines.map(line => this.getEndColumn(line))) const startLine = Math.min(...oldLines.map(line => line.lineNumber)) return { @@ -231,7 +230,7 @@ export class DefaultDecorator implements AutoEditsDecorator { } } - private getReplacerColumn(line: vscode.TextLine): number { + private getEndColumn(line: vscode.TextLine): number { const insertSpaces = getEditorInsertSpaces( this.editor.document.uri, vscode.workspace, @@ -270,7 +269,7 @@ export class DefaultDecorator implements AutoEditsDecorator { for (let i = 0; i < blockifiedAddedLines.length; i++) { const j = i + startLine const line = this.editor.document.lineAt(j) - const lineReplacerCol = this.getReplacerColumn(line) + const lineReplacerCol = this.getEndColumn(line) const decoration = blockifiedAddedLines[i] const decorationStyle = cssPropertiesToString({ // Absolutely position the suggested code so that the cursor does not jump there diff --git a/vscode/test/e2e/__snapshots__/auto-edits.test.ts/macos/autoedits-suffix-decoration-tab-indentation-23.png b/vscode/test/e2e/__snapshots__/auto-edits.test.ts/macos/autoedits-suffix-decoration-tab-indentation-23.png new file mode 100644 index 0000000000000000000000000000000000000000..cff0d407b46f393a740d7edfb4cae5358b507295 GIT binary patch literal 95350 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

Xmrhae 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ŒPD@N8(E1W_>#m%qw=|bz_+fJGTjv^55Gyd{-oO) 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�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 literal 0 HcmV?d00001 diff --git a/vscode/test/e2e/auto-edits.test.ts b/vscode/test/e2e/auto-edits.test.ts index 945d37450dac..57eb0becee93 100644 --- a/vscode/test/e2e/auto-edits.test.ts +++ b/vscode/test/e2e/auto-edits.test.ts @@ -231,6 +231,20 @@ test('autoedits: triggers inline decorations when multiple separate insertions a }) }) +test('autoedits: triggers a suffix decoration and renders correctly in files that use tab based indentation', async ({ + page, + sidebar, +}) => { + const lineOptions: LineOptions[] = [{ line: 23 }] + await autoeditsTestHelper({ + page, + sidebar, + fileName: 'suffix-decoration-example-3.go', + testCaseName: 'autoedits-suffix-decoration-tab-indentation', + lineOptions, + }) +}) + /** * BUG: We need to fix our logic to display decorations at the end of a file. * Linear issue: https://linear.app/sourcegraph/issue/CODY-4650/fix-rendering-issues-with-suffix-suggestions-at-the-end-of-a-file diff --git a/vscode/test/fixtures/workspace/auto-edits/suffix-decoration-example-3.go b/vscode/test/fixtures/workspace/auto-edits/suffix-decoration-example-3.go new file mode 100644 index 000000000000..451532b80c48 --- /dev/null +++ b/vscode/test/fixtures/workspace/auto-edits/suffix-decoration-example-3.go @@ -0,0 +1,28 @@ +/* +<<<< +func parseArgs(arguments []string) (args, error) { + if len(arguments) < 2 { + return args{}, errors.New("missing arguments") + } else if len(arguments) > 2 { + return args{}, errors.New("too many arguments") + } +} +==== +func parseArgs(args []string) (args, error) { + if len(args) < 2 { + return args{}, errors.New("missing arguments") + } else if len(args) > 2 { + return args{}, errors.New("too many arguments") + } +} +>>>> +*/ + + +func parseArgs(arguments []string) (args, error) { + if len(arguments) < 2 { + return args{}, errors.New("missing arguments") + } else if len(arguments) > 2 { + return args{}, errors.New("too many arguments") + } +} From af36dfe789708008b0889cc90cd959d14baad78c Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Mon, 13 Jan 2025 15:58:08 +0000 Subject: [PATCH 6/7] rm another use of line.range.end --- vscode/src/autoedits/renderer/decorators/default-decorator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vscode/src/autoedits/renderer/decorators/default-decorator.ts b/vscode/src/autoedits/renderer/decorators/default-decorator.ts index 6e88613080b2..34aa2e448ce7 100644 --- a/vscode/src/autoedits/renderer/decorators/default-decorator.ts +++ b/vscode/src/autoedits/renderer/decorators/default-decorator.ts @@ -279,7 +279,7 @@ export class DefaultDecorator implements AutoEditsDecorator { 'backdrop-filter': 'blur(5px)', }) - if (replacerCol >= line.range.end.character) { + if (replacerCol >= lineReplacerCol) { replacerDecorations.push({ range: new vscode.Range(j, line.range.end.character, j, line.range.end.character), renderOptions: { From a73608b59f5aa47271acd07104e4efc800b0dffc Mon Sep 17 00:00:00 2001 From: Tom Ross Date: Tue, 14 Jan 2025 15:03:48 +0000 Subject: [PATCH 7/7] clean --- .../src/autoedits/renderer/decorators/blockify.ts | 13 +++++++++++++ .../renderer/decorators/default-decorator.ts | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/vscode/src/autoedits/renderer/decorators/blockify.ts b/vscode/src/autoedits/renderer/decorators/blockify.ts index fa8625a92dd8..8361265a3be6 100644 --- a/vscode/src/autoedits/renderer/decorators/blockify.ts +++ b/vscode/src/autoedits/renderer/decorators/blockify.ts @@ -5,6 +5,19 @@ import type { AddedLinesDecorationInfo } from './default-decorator' export const UNICODE_SPACE = '\u00A0' +/** + * Given a list of added lines, blockify them to make them suitable for rendering as a VS Code decoration. + * + * For example, given the code block: + * " hello + * world" + * We blockify it like so: + * "hello + * world" + * + * Notice that the start indentation is adjusted left, and each line is padded to match the length of the longest line. + * We also convert any "normal" spaces to unicode spaces. This is also to improve rendering as a VS Code decoration. + */ export function blockify( document: vscode.TextDocument, addedLines: AddedLinesDecorationInfo[] diff --git a/vscode/src/autoedits/renderer/decorators/default-decorator.ts b/vscode/src/autoedits/renderer/decorators/default-decorator.ts index 34aa2e448ce7..20ab23673a1d 100644 --- a/vscode/src/autoedits/renderer/decorators/default-decorator.ts +++ b/vscode/src/autoedits/renderer/decorators/default-decorator.ts @@ -258,12 +258,12 @@ export class DefaultDecorator implements AutoEditsDecorator { } private renderAddedLinesDecorations( - _addedLinesInfo: AddedLinesDecorationInfo[], + addedLinesInfo: AddedLinesDecorationInfo[], startLine: number, replacerCol: number ): void { // Blockify the added lines so they are suitable to be rendered together as a VS Code decoration - const blockifiedAddedLines = blockify(this.editor.document, _addedLinesInfo) + const blockifiedAddedLines = blockify(this.editor.document, addedLinesInfo) const replacerDecorations: vscode.DecorationOptions[] = [] for (let i = 0; i < blockifiedAddedLines.length; i++) {