mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
Fix accept/reject diff
This commit is contained in:
parent
1557a44934
commit
20056f209e
4 changed files with 109 additions and 56 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { findDiffs } from './findDiffs';
|
||||
import { Diff, DiffArea, DiffBlock } from './shared_types';
|
||||
import { Diff, BaseDiffArea, BaseDiff, DiffArea } from './shared_types';
|
||||
|
||||
|
||||
|
||||
|
|
@ -17,6 +17,7 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
private _diffAreasOfDocument: { [docUriStr: string]: DiffArea[] } = {}
|
||||
private _diffsOfDocument: { [docUriStr: string]: Diff[] } = {}
|
||||
|
||||
private _diffareaidPool = 0
|
||||
private _diffidPool = 0
|
||||
private _weAreEditing: boolean = false
|
||||
|
||||
|
|
@ -37,6 +38,7 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
|
||||
// this acts as a useEffect. Every time text changes, clear the diffs in this editor
|
||||
vscode.workspace.onDidChangeTextDocument((e) => {
|
||||
|
||||
const editor = vscode.window.activeTextEditor
|
||||
|
||||
if (!editor)
|
||||
|
|
@ -97,7 +99,7 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
|
||||
|
||||
// used by us only
|
||||
public addDiffArea(uri: vscode.Uri, diffArea: DiffArea) {
|
||||
public addDiffArea(uri: vscode.Uri, diffArea: BaseDiffArea) {
|
||||
|
||||
const uriStr = uri.toString()
|
||||
|
||||
|
|
@ -107,16 +109,20 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
|
||||
// remove all diffAreas that the new `diffArea` is overlapping with
|
||||
this._diffAreasOfDocument[uriStr] = this._diffAreasOfDocument[uriStr].filter(da => {
|
||||
// condition for no overlap
|
||||
|
||||
const noOverlap = da.startLine > diffArea.endLine || da.endLine < diffArea.startLine
|
||||
// if there is overlap (ie there is `not noOverlap`), remove `da`
|
||||
|
||||
if (!noOverlap) return false
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
// add `diffArea` to storage
|
||||
this._diffAreasOfDocument[uriStr].push(diffArea)
|
||||
|
||||
this._diffAreasOfDocument[uriStr].push({
|
||||
...diffArea,
|
||||
diffareaid: this._diffareaidPool
|
||||
})
|
||||
this._diffareaidPool += 1
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -149,7 +155,7 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
console.log('!CODEAfter:', JSON.stringify(currentCode))
|
||||
|
||||
// add the diffs to `this._diffsOfDocument[docUriStr]`
|
||||
this.addDiffs(editor.document.uri, diffs)
|
||||
this.addDiffs(editor.document.uri, diffs, diffArea)
|
||||
|
||||
for (const diff of this._diffsOfDocument[docUriStr]) {
|
||||
console.log('------------')
|
||||
|
|
@ -180,7 +186,7 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
}
|
||||
|
||||
// used by us only
|
||||
public addDiffs(docUri: vscode.Uri, diffs: DiffBlock[]) {
|
||||
public addDiffs(docUri: vscode.Uri, diffs: BaseDiff[], diffArea: DiffArea) {
|
||||
|
||||
const docUriStr = docUri.toString()
|
||||
|
||||
|
|
@ -197,8 +203,8 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
diffid: this._diffidPool,
|
||||
// originalCode: suggestedDiff.deletedText,
|
||||
lenses: [
|
||||
new vscode.CodeLens(suggestedDiff.insertedRange, { title: 'Accept', command: 'void.acceptDiff', arguments: [{ diffid: this._diffidPool }] }),
|
||||
new vscode.CodeLens(suggestedDiff.insertedRange, { title: 'Reject', command: 'void.rejectDiff', arguments: [{ diffid: this._diffidPool }] })
|
||||
new vscode.CodeLens(suggestedDiff.insertedRange, { title: 'Accept', command: 'void.acceptDiff', arguments: [{ diffid: this._diffidPool, diffareaid: diffArea.diffareaid }] }),
|
||||
new vscode.CodeLens(suggestedDiff.insertedRange, { title: 'Reject', command: 'void.rejectDiff', arguments: [{ diffid: this._diffidPool, diffareaid: diffArea.diffareaid }] })
|
||||
]
|
||||
});
|
||||
this._diffidPool += 1
|
||||
|
|
@ -207,7 +213,7 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
}
|
||||
|
||||
// called on void.acceptDiff
|
||||
public async acceptDiff({ diffid }: { diffid: number }) {
|
||||
public async acceptDiff({ diffid, diffareaid }: { diffid: number, diffareaid: number }) {
|
||||
const editor = vscode.window.activeTextEditor
|
||||
if (!editor)
|
||||
return
|
||||
|
|
@ -216,54 +222,94 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
const docUri = editor.document.uri
|
||||
const docUriStr = docUri.toString()
|
||||
|
||||
// get index of this diff in diffsOfDocument
|
||||
const index = this._diffsOfDocument[docUriStr].findIndex(diff => diff.diffid === diffid);
|
||||
if (index === -1) {
|
||||
console.error('Error: DiffID could not be found: ', diffid, this._diffsOfDocument[docUriStr])
|
||||
return
|
||||
// get relevant diff
|
||||
// TODO speed up with hashmap
|
||||
const diffIdx = this._diffsOfDocument[docUriStr].findIndex(diff => diff.diffid === diffid);
|
||||
if (diffIdx === -1) {
|
||||
console.error('Error: DiffID could not be found: ', diffid, diffareaid, this._diffsOfDocument[docUriStr], this._diffAreasOfDocument[docUriStr]); return;
|
||||
}
|
||||
|
||||
// remove this diff from the diffsOfDocument[docStr] (can change this behavior in future if add something like history)
|
||||
this._diffsOfDocument[docUriStr].splice(index, 1)
|
||||
// get relevant diffArea
|
||||
const diffareaIdx = this._diffAreasOfDocument[docUriStr].findIndex(diff => diff.diffareaid === diffareaid);
|
||||
if (diffareaIdx === -1) {
|
||||
console.error('Error: DiffAreaID could not be found: ', diffid, diffareaid, this._diffsOfDocument[docUriStr], this._diffAreasOfDocument[docUriStr]); return;
|
||||
}
|
||||
|
||||
// refresh
|
||||
const diff = this._diffsOfDocument[docUriStr][diffIdx]
|
||||
const diffArea = this._diffAreasOfDocument[docUriStr][diffareaIdx]
|
||||
|
||||
// replace `originalCode[diff.deletedRange]` with diff.insertedCode
|
||||
// TODO add a history event to undo this change
|
||||
const originalLines = diffArea.originalCode.split('\n');
|
||||
const relativeStart = diff.deletedRange.start.line - diffArea.originalStartLine
|
||||
const relativeEnd = diff.deletedRange.end.line - diffArea.originalStartLine
|
||||
diffArea.originalCode = [
|
||||
...originalLines.slice(0, relativeStart), // lines before the deleted range
|
||||
...diff.insertedCode.split('\n'), // inserted lines
|
||||
...originalLines.slice(relativeEnd + 1) // lines after the deleted range
|
||||
].join('\n')
|
||||
|
||||
// if the diffArea has no changes, remove it
|
||||
const currentDiffAreaCode = editor.document.getText()
|
||||
.replace(/\r\n/g, '\n')
|
||||
.split('\n')
|
||||
.slice(diffArea.startLine, diffArea.endLine + 1)
|
||||
.join('\n')
|
||||
if (diffArea.originalCode === currentDiffAreaCode) { // if the currentDiffAreaCode === diffArea.originalCode, remove the diffArea
|
||||
const index = this._diffAreasOfDocument[docUriStr].findIndex(da => da.diffareaid === diffArea.diffareaid)
|
||||
this._diffAreasOfDocument[docUriStr].splice(index, 1)
|
||||
}
|
||||
|
||||
// refresh the diff area
|
||||
this.refreshDiffAreas(docUri)
|
||||
}
|
||||
|
||||
|
||||
// called on void.rejectDiff
|
||||
public async rejectDiff({ diffid }: { diffid: number }) {
|
||||
public async rejectDiff({ diffid, diffareaid }: { diffid: number, diffareaid: number }) {
|
||||
const editor = vscode.window.activeTextEditor
|
||||
if (!editor)
|
||||
return
|
||||
|
||||
// get document uri
|
||||
const docUri = editor.document.uri
|
||||
const docUriStr = docUri.toString()
|
||||
|
||||
// get index of this diff in diffsOfDocument
|
||||
const index = this._diffsOfDocument[docUriStr].findIndex(diff => diff.diffid === diffid);
|
||||
if (index === -1) {
|
||||
console.error('Void error: DiffID could not be found: ', diffid, this._diffsOfDocument[docUriStr])
|
||||
return
|
||||
// get relevant diff
|
||||
// TODO speed up with hashmap
|
||||
const diffIdx = this._diffsOfDocument[docUriStr].findIndex(diff => diff.diffid === diffid);
|
||||
if (diffIdx === -1) {
|
||||
console.error('Error: DiffID could not be found: ', diffid, diffareaid, this._diffsOfDocument[docUriStr], this._diffAreasOfDocument[docUriStr]); return;
|
||||
}
|
||||
|
||||
const { insertedRange: range, lenses, deletedCode } = this._diffsOfDocument[docUriStr][index] // do this before we splice and mess up index
|
||||
// get relevant diffArea
|
||||
const diffareaIdx = this._diffAreasOfDocument[docUriStr].findIndex(diff => diff.diffareaid === diffareaid);
|
||||
if (diffareaIdx === -1) {
|
||||
console.error('Error: DiffAreaID could not be found: ', diffid, diffareaid, this._diffsOfDocument[docUriStr], this._diffAreasOfDocument[docUriStr]); return;
|
||||
}
|
||||
|
||||
// remove this diff from the diffsOfDocument[docStr] (can change this behavior in future if add something like history)
|
||||
this._diffsOfDocument[docUriStr].splice(index, 1)
|
||||
const diff = this._diffsOfDocument[docUriStr][diffIdx]
|
||||
const diffArea = this._diffAreasOfDocument[docUriStr][diffareaIdx]
|
||||
|
||||
// clear the decoration in this diffs range
|
||||
// editor.setDecorations(greenDecoration, this._diffsOfDocument[docUriStr].map(diff => diff.insertionRange))
|
||||
|
||||
// REVERT THE CHANGE (this is the only part that's different from acceptDiff)
|
||||
let workspaceEdit = new vscode.WorkspaceEdit();
|
||||
// workspaceEdit.replace(docUri, range, deletedCode);
|
||||
// replace `editorCode[diff.insertedRange]` with diff.deletedCode
|
||||
const workspaceEdit = new vscode.WorkspaceEdit();
|
||||
workspaceEdit.replace(docUri, diff.insertedRange, diff.deletedCode)
|
||||
this._weAreEditing = true
|
||||
await vscode.workspace.applyEdit(workspaceEdit)
|
||||
await vscode.workspace.save(docUri)
|
||||
this._weAreEditing = false
|
||||
|
||||
// refresh
|
||||
// if the diffArea has no changes, remove it
|
||||
const currentDiffAreaCode = editor.document.getText()
|
||||
.replace(/\r\n/g, '\n')
|
||||
.split('\n')
|
||||
.slice(diffArea.startLine, diffArea.endLine + 1)
|
||||
.join('\n')
|
||||
if (diffArea.originalCode === currentDiffAreaCode) { // if the currentDiffAreaCode === diffArea.originalCode, remove the diffArea
|
||||
const index = this._diffAreasOfDocument[docUriStr].findIndex(da => da.diffareaid === diffArea.diffareaid)
|
||||
this._diffAreasOfDocument[docUriStr].splice(index, 1)
|
||||
}
|
||||
|
||||
// refresh the diff area
|
||||
this.refreshDiffAreas(docUri)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { DiffArea, WebviewMessage } from './shared_types';
|
||||
import { BaseDiffArea, WebviewMessage } from './shared_types';
|
||||
import { CtrlKCodeLensProvider } from './CtrlKCodeLensProvider';
|
||||
import { DisplayChangesProvider } from './DisplayChangesProvider';
|
||||
import { SidebarWebviewProvider } from './SidebarWebviewProvider';
|
||||
|
|
@ -57,7 +57,7 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
// vscode.commands.executeCommand('vscode.moveViewToPanel', CustomViewProvider.viewId); // move to aux bar
|
||||
|
||||
// get the text the user is selecting
|
||||
const selectionStr = editor.document.getText(editor.selection);5
|
||||
const selectionStr = editor.document.getText(editor.selection); 5
|
||||
|
||||
// get the range of the selection
|
||||
const selectionRange = editor.selection;
|
||||
|
|
@ -124,9 +124,11 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
}
|
||||
|
||||
// create an area to show diffs
|
||||
const diffArea: DiffArea = {
|
||||
const diffArea: BaseDiffArea = {
|
||||
startLine: 0, // in ctrl+L the start and end lines are the full document
|
||||
endLine: editor.document.lineCount,
|
||||
originalStartLine: 0,
|
||||
originalEndLine: editor.document.lineCount,
|
||||
originalCode: await readFileContentOfUri(editor.document.uri),
|
||||
}
|
||||
displayChangesProvider.addDiffArea(editor.document.uri, diffArea)
|
||||
|
|
@ -139,12 +141,10 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
// 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);
|
||||
editBuilder.replace(new vscode.Range(diffArea.startLine, 0, diffArea.endLine, Number.MAX_SAFE_INTEGER), m.code);
|
||||
});
|
||||
|
||||
|
||||
|
||||
// rediff the changes based on the diffArea (start, end, original code, [current code])
|
||||
// rediff the changes based on the diffAreas
|
||||
displayChangesProvider.refreshDiffAreas(editor.document.uri)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
import * as vscode from 'vscode';
|
||||
// import { diffLines, Change } from 'diff';
|
||||
import { DiffBlock } from './shared_types';
|
||||
import { BaseDiff } from './shared_types';
|
||||
|
||||
import { diff_match_patch } from 'diff-match-patch';
|
||||
|
||||
|
|
@ -20,11 +20,11 @@ const diffLines = (text1: string, text2: string) => {
|
|||
|
||||
|
||||
// TODO use a better diff algorithm
|
||||
export const findDiffs = (oldText: string, newText: string): DiffBlock[] => {
|
||||
export const findDiffs = (oldText: string, newText: string): BaseDiff[] => {
|
||||
|
||||
const diffs = diffLines(oldText, newText);
|
||||
|
||||
const blocks: DiffBlock[] = [];
|
||||
const blocks: BaseDiff[] = [];
|
||||
let reprBlock: string[] = [];
|
||||
let deletedBlock: string[] = [];
|
||||
let insertedBlock: string[] = [];
|
||||
|
|
|
|||
|
|
@ -10,18 +10,25 @@ type CodeSelection = { selectionStr: string, selectionRange: vscode.Range, fileP
|
|||
type File = { filepath: vscode.Uri, content: string }
|
||||
|
||||
// an area that is currently being diffed
|
||||
type DiffArea = {
|
||||
startLine: number,
|
||||
endLine: number,
|
||||
originalCode: string
|
||||
type BaseDiffArea = {
|
||||
// use `startLine` and `endLine` instead of `range` for mutibility
|
||||
// bounds are relative to the file, inclusive
|
||||
startLine: number;
|
||||
endLine: number;
|
||||
originalStartLine: number,
|
||||
originalEndLine: number,
|
||||
originalCode: string, // the original chunk of code (not necessarily the whole file)
|
||||
// `newCode: string,` is not included because it is the code in the actual file, `document.text()[startline: endLine + 1]`
|
||||
}
|
||||
|
||||
type DiffArea = BaseDiffArea & { diffareaid: number }
|
||||
|
||||
// the return type of diff creator
|
||||
type DiffBlock = {
|
||||
code: string;
|
||||
deletedRange: vscode.Range;
|
||||
deletedCode: string;
|
||||
type BaseDiff = {
|
||||
code: string; // representation of the diff in text
|
||||
deletedRange: vscode.Range; // relative to the file, inclusive
|
||||
insertedRange: vscode.Range;
|
||||
deletedCode: string;
|
||||
insertedCode: string;
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +36,7 @@ type DiffBlock = {
|
|||
type Diff = {
|
||||
diffid: number,
|
||||
lenses: vscode.CodeLens[],
|
||||
} & DiffBlock
|
||||
} & BaseDiff
|
||||
|
||||
type WebviewMessage = (
|
||||
|
||||
|
|
@ -57,7 +64,7 @@ type WebviewMessage = (
|
|||
type Command = WebviewMessage['type']
|
||||
|
||||
export {
|
||||
DiffBlock,
|
||||
BaseDiff, BaseDiffArea,
|
||||
CodeSelection,
|
||||
File,
|
||||
WebviewMessage,
|
||||
|
|
|
|||
Loading…
Reference in a new issue