mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
diffArea works. Need to fix highlighting
This commit is contained in:
parent
b07842ec3f
commit
11baebdf54
4 changed files with 112 additions and 53 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { SuggestedEdit } from './getDiffedLines';
|
||||
import { getDiffedLines, SuggestedDiff } from './getDiffedLines';
|
||||
import { Diff, DiffArea } from './shared_types';
|
||||
|
||||
|
||||
|
|
@ -24,7 +24,6 @@ export class ApplyChangesProvider implements vscode.CodeLensProvider {
|
|||
private _onDidChangeCodeLenses: vscode.EventEmitter<void> = new vscode.EventEmitter<void>(); // signals a UI refresh on .fire() events
|
||||
public readonly onDidChangeCodeLenses: vscode.Event<void> = this._onDidChangeCodeLenses.event;
|
||||
|
||||
|
||||
// used internally by vscode
|
||||
public provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CodeLens[]> {
|
||||
const docUriStr = document.uri.toString()
|
||||
|
|
@ -33,6 +32,9 @@ export class ApplyChangesProvider implements vscode.CodeLensProvider {
|
|||
|
||||
// declared by us, registered with vscode.languages.registerCodeLensProvider()
|
||||
constructor() {
|
||||
|
||||
console.log('Creating DisplayChangesProvider')
|
||||
|
||||
// this acts as a useEffect. Every time text changes, clear the diffs in this editor
|
||||
vscode.workspace.onDidChangeTextDocument((e) => {
|
||||
const editor = vscode.window.activeTextEditor
|
||||
|
|
@ -43,25 +45,82 @@ export class ApplyChangesProvider implements vscode.CodeLensProvider {
|
|||
return
|
||||
|
||||
const docUri = editor.document.uri
|
||||
const docUriStr = docUri.toString()
|
||||
this._diffsOfDocument[docUriStr].splice(0) // clear diffs
|
||||
editor.setDecorations(greenDecoration, []) // clear decorations
|
||||
this.refreshDiffAreas(docUri)
|
||||
|
||||
// const docUriStr = docUri.toString()
|
||||
// this._diffAreasOfDocument[docUriStr].splice(0) // clear diff areas
|
||||
// this._diffsOfDocument[docUriStr].splice(0) // clear diffs
|
||||
// editor.setDecorations(greenDecoration, []) // clear decorations
|
||||
// this._onDidChangeCodeLenses.fire() // rerender codelenses
|
||||
|
||||
|
||||
this._onDidChangeCodeLenses.fire() // rerender codelenses
|
||||
})
|
||||
}
|
||||
|
||||
// used by us only
|
||||
private refreshLenses = (editor: vscode.TextEditor, docUriStr: string) => {
|
||||
editor.setDecorations(greenDecoration, this._diffsOfDocument[docUriStr].map(diff => diff.greenRange)) // refresh highlighting
|
||||
|
||||
this._onDidChangeCodeLenses.fire() // fire event for vscode to refresh lenses
|
||||
// used by us only
|
||||
public addDiffArea(uri: vscode.Uri, diffArea: DiffArea) {
|
||||
|
||||
const uriStr = uri.toString()
|
||||
|
||||
// make sure array is defined
|
||||
if (!this._diffAreasOfDocument[uriStr])
|
||||
this._diffAreasOfDocument[uriStr] = []
|
||||
|
||||
// TODO!!! replace all areas that it is overlapping with
|
||||
|
||||
|
||||
|
||||
// add diffArea to storage
|
||||
this._diffAreasOfDocument[uriStr].push(diffArea)
|
||||
|
||||
}
|
||||
|
||||
|
||||
// used by us only
|
||||
public refreshDiffAreas(docUri: vscode.Uri) {
|
||||
|
||||
const editor = vscode.window.activeTextEditor // TODO the editor should be that of `docUri` and not necessarily the current editor
|
||||
if (!editor) {
|
||||
console.log('Error: No active editor!')
|
||||
return;
|
||||
}
|
||||
|
||||
const docUriStr = docUri.toString()
|
||||
const diffAreas = this._diffAreasOfDocument[docUriStr] || []
|
||||
|
||||
// reset all diffs (we update them below)
|
||||
this._diffsOfDocument[docUriStr] = []
|
||||
|
||||
// for each diffArea
|
||||
console.log('diffAreas.length:', diffAreas.length)
|
||||
for (const diffArea of diffAreas) {
|
||||
|
||||
// get code inside of diffArea
|
||||
const currentCode = editor.document.getText(new vscode.Range(diffArea.startLine, 0, diffArea.endLine, Number.MAX_SAFE_INTEGER))
|
||||
|
||||
// compute the diffs
|
||||
const diffs = getDiffedLines(diffArea.originalCode, currentCode)
|
||||
|
||||
console.log('originalCode:', diffArea.originalCode)
|
||||
console.log('currentCode:', currentCode)
|
||||
|
||||
// add the diffs to `this._diffsOfDocument[docUriStr]`
|
||||
this.addDiffs(editor.document.uri, diffs)
|
||||
|
||||
}
|
||||
|
||||
// update highlighting
|
||||
editor.setDecorations(greenDecoration, this._diffsOfDocument[docUriStr].map(diff => diff.greenRange))
|
||||
|
||||
// update code lenses
|
||||
this._onDidChangeCodeLenses.fire()
|
||||
|
||||
}
|
||||
|
||||
// used by us only
|
||||
public async addNewChanges(editor: vscode.TextEditor, suggestedEdits: SuggestedEdit[]) {
|
||||
public addDiffs(docUri: vscode.Uri, diffs: SuggestedDiff[]) {
|
||||
|
||||
const docUri = editor.document.uri
|
||||
const docUriStr = docUri.toString()
|
||||
|
||||
// if no diffs, set diffs to []
|
||||
|
|
@ -69,39 +128,39 @@ export class ApplyChangesProvider implements vscode.CodeLensProvider {
|
|||
this._diffsOfDocument[docUriStr] = []
|
||||
|
||||
|
||||
// 1. convert suggested edits (which are described using line numbers) into actual edits (described using vscode.Range, vscode.Uri)
|
||||
// 1. convert suggested diffs (which are described using line numbers) into actual diffs (described using vscode.Range, vscode.Uri)
|
||||
// must do this before adding codelenses or highlighting so that codelens and highlights will apply to the fresh code and not the old code
|
||||
// apply changes in reverse order so additions don't push down the line numbers of the next edit
|
||||
let workspaceEdit = new vscode.WorkspaceEdit();
|
||||
for (let i = suggestedEdits.length - 1; i > -1; i -= 1) {
|
||||
let suggestedEdit = suggestedEdits[i]
|
||||
for (let i = diffs.length - 1; i > -1; i -= 1) {
|
||||
let suggestedDiff = diffs[i]
|
||||
|
||||
let greenRange: vscode.Range
|
||||
|
||||
// INSERTIONS (e.g. {originalStartLine: 0, originalEndLine: -1})
|
||||
if (suggestedEdit.originalStartLine > suggestedEdit.originalEndLine) {
|
||||
const originalPosition = new vscode.Position(suggestedEdit.originalStartLine, 0)
|
||||
workspaceEdit.insert(docUri, originalPosition, suggestedEdit.afterCode + '\n') // add back in the line we deleted when we made the startline->endline range go negative
|
||||
greenRange = new vscode.Range(suggestedEdit.startLine, 0, suggestedEdit.endLine + 1, 0)
|
||||
if (suggestedDiff.originalStartLine > suggestedDiff.originalEndLine) {
|
||||
const originalPosition = new vscode.Position(suggestedDiff.originalStartLine, 0)
|
||||
workspaceEdit.insert(docUri, originalPosition, suggestedDiff.afterCode + '\n') // add back in the line we deleted when we made the startline->endline range go negative
|
||||
greenRange = new vscode.Range(suggestedDiff.startLine, 0, suggestedDiff.endLine + 1, 0)
|
||||
}
|
||||
// DELETIONS
|
||||
else if (suggestedEdit.startLine > suggestedEdit.endLine) {
|
||||
const deleteRange = new vscode.Range(suggestedEdit.originalStartLine, 0, suggestedEdit.originalEndLine + 1, 0)
|
||||
else if (suggestedDiff.startLine > suggestedDiff.endLine) {
|
||||
const deleteRange = new vscode.Range(suggestedDiff.originalStartLine, 0, suggestedDiff.originalEndLine + 1, 0)
|
||||
workspaceEdit.delete(docUri, deleteRange)
|
||||
greenRange = new vscode.Range(suggestedEdit.startLine, 0, suggestedEdit.startLine, 0)
|
||||
suggestedEdit.beforeCode += '\n' // add back in the line we deleted when we made the startline->endline range go negative
|
||||
greenRange = new vscode.Range(suggestedDiff.startLine, 0, suggestedDiff.startLine, 0)
|
||||
suggestedDiff.beforeCode += '\n' // add back in the line we deleted when we made the startline->endline range go negative
|
||||
}
|
||||
// REPLACEMENTS
|
||||
else {
|
||||
const originalRange = new vscode.Range(suggestedEdit.originalStartLine, 0, suggestedEdit.originalEndLine, Number.MAX_SAFE_INTEGER)
|
||||
workspaceEdit.replace(docUri, originalRange, suggestedEdit.afterCode)
|
||||
greenRange = new vscode.Range(suggestedEdit.startLine, 0, suggestedEdit.endLine, Number.MAX_SAFE_INTEGER)
|
||||
const originalRange = new vscode.Range(suggestedDiff.originalStartLine, 0, suggestedDiff.originalEndLine, Number.MAX_SAFE_INTEGER)
|
||||
workspaceEdit.replace(docUri, originalRange, suggestedDiff.afterCode)
|
||||
greenRange = new vscode.Range(suggestedDiff.startLine, 0, suggestedDiff.endLine, Number.MAX_SAFE_INTEGER)
|
||||
}
|
||||
|
||||
this._diffsOfDocument[docUriStr].push({
|
||||
diffid: this._diffidPool,
|
||||
greenRange: greenRange,
|
||||
originalCode: suggestedEdit.beforeCode,
|
||||
originalCode: suggestedDiff.beforeCode,
|
||||
lenses: [
|
||||
new vscode.CodeLens(greenRange, { title: 'Accept', command: 'void.acceptDiff', arguments: [{ diffid: this._diffidPool }] }),
|
||||
new vscode.CodeLens(greenRange, { title: 'Reject', command: 'void.rejectDiff', arguments: [{ diffid: this._diffidPool }] })
|
||||
|
|
@ -110,15 +169,7 @@ export class ApplyChangesProvider implements vscode.CodeLensProvider {
|
|||
this._diffidPool += 1
|
||||
}
|
||||
|
||||
this._weAreEditing = true
|
||||
await vscode.workspace.applyEdit(workspaceEdit)
|
||||
await vscode.workspace.save(docUri)
|
||||
this._weAreEditing = false
|
||||
|
||||
// refresh
|
||||
this.refreshLenses(editor, docUriStr)
|
||||
|
||||
console.log('diffs after added:', this._diffsOfDocument[docUriStr])
|
||||
console.log('diffs:', this._diffsOfDocument[docUriStr])
|
||||
}
|
||||
|
||||
// called on void.acceptDiff
|
||||
|
|
@ -142,7 +193,7 @@ export class ApplyChangesProvider implements vscode.CodeLensProvider {
|
|||
this._diffsOfDocument[docUriStr].splice(index, 1)
|
||||
|
||||
// refresh
|
||||
this.refreshLenses(editor, docUriStr)
|
||||
this.refreshDiffAreas(docUri)
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -179,6 +230,6 @@ export class ApplyChangesProvider implements vscode.CodeLensProvider {
|
|||
this._weAreEditing = false
|
||||
|
||||
// refresh
|
||||
this.refreshLenses(editor, docUriStr)
|
||||
this.refreshDiffAreas(docUri)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,35 +115,38 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
} else if (m.type === 'applyChanges') {
|
||||
|
||||
console.log('Applying changes')
|
||||
|
||||
const editor = vscode.window.activeTextEditor
|
||||
if (!editor) {
|
||||
vscode.window.showInformationMessage('No active editor!')
|
||||
return
|
||||
}
|
||||
|
||||
// create an area to show diffs
|
||||
const diffArea: DiffArea = {
|
||||
startLine: 0, // in ctrl+L the start and end lines are the full document
|
||||
endLine: editor.document.lineCount,
|
||||
originalCode: undefined,
|
||||
originalCode: await readFileContentOfUri(editor.document.uri),
|
||||
}
|
||||
displayChangesProvider.addDiffArea(editor.document.uri, diffArea)
|
||||
|
||||
// save the original code
|
||||
diffArea.originalCode = await readFileContentOfUri(editor.document.uri)
|
||||
|
||||
// write the new code `m.code` to the document
|
||||
// TODO make this animated
|
||||
editor.edit(editBuilder => {
|
||||
// write new code `m.code` to the document
|
||||
// TODO update like this:
|
||||
// this._weAreEditing = true
|
||||
// await vscode.workspace.applyEdit(workspaceEdit)
|
||||
// await vscode.workspace.save(docUri)
|
||||
// this._weAreEditing = false
|
||||
await editor.edit(editBuilder => {
|
||||
editBuilder.replace(new vscode.Range(diffArea.startLine, 0, diffArea.endLine, 0), m.code);
|
||||
});
|
||||
|
||||
|
||||
// rediff the changes based on the diffArea (start, end, original code, current code)
|
||||
|
||||
// rediff the changes based on the diffArea (start, end, original code, [current code])
|
||||
displayChangesProvider.refreshDiffAreas(editor.document.uri)
|
||||
|
||||
|
||||
// TODO!!! put this logic in `displayChangesProvider.displayChanges(diffArea)` function
|
||||
const suggestedEdits = getDiffedLines(diffArea.originalCode, m.code)
|
||||
await displayChangesProvider.addNewChanges(editor, suggestedEdits)
|
||||
}
|
||||
else if (m.type === 'getApiConfig') {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { diffLines, Change } from 'diff';
|
||||
|
||||
export type SuggestedEdit = {
|
||||
export type SuggestedDiff = {
|
||||
// start/end of current file
|
||||
startLine: number,
|
||||
endLine: number,
|
||||
|
|
@ -16,6 +16,11 @@ export type SuggestedEdit = {
|
|||
|
||||
export function getDiffedLines(oldStr: string, newStr: string) {
|
||||
// an ordered list of every original line, line added to the new file, and line removed from the old file (order is unambiguous, think about it)
|
||||
|
||||
// replace \r\n with \n
|
||||
oldStr = oldStr.replace(/\r\n/g, '\n')
|
||||
newStr = newStr.replace(/\r\n/g, '\n')
|
||||
|
||||
const lineByLineChanges: Change[] = diffLines(oldStr, newStr);
|
||||
console.debug('Line by line changes', lineByLineChanges)
|
||||
|
||||
|
|
@ -30,7 +35,7 @@ export function getDiffedLines(oldStr: string, newStr: string) {
|
|||
let oldStrLines = oldStr.split('\n')
|
||||
let newStrLines = newStr.split('\n')
|
||||
|
||||
const replacements: SuggestedEdit[] = []
|
||||
const replacements: SuggestedDiff[] = []
|
||||
|
||||
for (let line of lineByLineChanges) {
|
||||
// no change on this line
|
||||
|
|
@ -46,7 +51,7 @@ export function getDiffedLines(oldStr: string, newStr: string) {
|
|||
const originalEndLine = oldFileLineNum - 1 // don't include current line, the edit was up to this line but not including it
|
||||
const originalContent = oldStrLines.slice(originalStartLine, originalEndLine + 1).join('\n')
|
||||
|
||||
const replacement: SuggestedEdit = { beforeCode: originalContent, afterCode: newContent, startLine, endLine, originalStartLine, originalEndLine, }
|
||||
const replacement: SuggestedDiff = { beforeCode: originalContent, afterCode: newContent, startLine, endLine, originalStartLine, originalEndLine, }
|
||||
|
||||
replacements.push(replacement)
|
||||
streakStartInNewFile = undefined
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ type File = { filepath: vscode.Uri, content: string }
|
|||
type DiffArea = {
|
||||
startLine: number,
|
||||
endLine: number,
|
||||
originalCode: string | undefined
|
||||
originalCode: string
|
||||
}
|
||||
|
||||
// each diff on the user's screen right now
|
||||
|
|
|
|||
Loading…
Reference in a new issue