Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(autoedits): Correctly produce decorations for files that use Tab indentation #6617

Merged
merged 9 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
update
  • Loading branch information
umpox committed Jan 13, 2025
commit aa415568700f599677949f1d3cb083023788ebae
4 changes: 2 additions & 2 deletions vscode/src/autoedits/renderer/decorators/blockify.test.ts
Original file line number Diff line number Diff line change
@@ -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', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙌

describe('space indentation', () => {
Expand Down Expand Up @@ -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')

Expand Down
12 changes: 8 additions & 4 deletions vscode/src/autoedits/renderer/decorators/blockify.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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 => ({
Expand All @@ -30,7 +33,6 @@ export function convertToSpaceIndentation(document: vscode.TextDocument, addedLi
}))
}


function padTrailingWhitespaceBlock(addedLines: AddedLinesDecorationInfo[]): AddedLinesDecorationInfo[] {
let maxLineWidth = 0
for (const addedLine of addedLines) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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 = ''
Expand Down
9 changes: 5 additions & 4 deletions vscode/src/autoedits/renderer/decorators/default-decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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`,
},
Expand Down
Loading