Skip to content

Commit fd1ac68

Browse files
committed
feat: optimize diff computation, fix diff renderer separators, and fix backend compilation
1 parent 167c654 commit fd1ac68

11 files changed

Lines changed: 214 additions & 21 deletions

File tree

anycode-backend/src/diff.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn compute_text_edits(old: &str, new: &str) -> Vec<Edit> {
2727
let text = slice.concat();
2828
edits.push(Edit {
2929
start: utf16_offset,
30-
text: text.clone(),
30+
text,
3131
operation: Operation::Remove,
3232
});
3333
// Deletion does not move offset forward
@@ -36,7 +36,7 @@ pub fn compute_text_edits(old: &str, new: &str) -> Vec<Edit> {
3636
let text = slice.concat();
3737
edits.push(Edit {
3838
start: utf16_offset,
39-
text: text.clone(),
39+
text,
4040
operation: Operation::Insert,
4141
});
4242
// Insertion moves offset forward

anycode-backend/src/handlers/lsp_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub async fn handle_hover(
5959
ack: AckSender,
6060
state: State<AppState>,
6161
) {
62-
info!("handle_completion {}", request.file);
62+
info!("handle_hover {}", request.file);
6363
let HoverRequest { file, row, column } = request;
6464

6565
let abs_path = match abs_file(&file) {

anycode-backend/src/lsp.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,8 @@ impl Lsp {
339339
text_document: TextDocumentIdentifier {
340340
uri: path_to_uri(path).unwrap(),
341341
},
342-
text: text.map(|s| s.to_string()),
342+
text: None,
343+
// text: text.map(|s| s.to_string()),
343344
};
344345
self.send_notification::<DidSaveTextDocument>(params);
345346
}

anycode-backend/src/search.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ pub async fn global_search(
304304
}
305305

306306
pub mod search_exp {
307+
use super::*;
307308

308309
#[test]
309310
fn test_line_search_simple() {

anycode-base/src/code.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ export class Code {
255255
return this.buffer.getLinesContent().join("\n");
256256
}
257257

258+
public getLines(): string[] {
259+
return this.buffer.getLinesContent();
260+
}
261+
258262
public getContentLength(): number {
259263
return this.buffer.getLength();
260264
}

anycode-base/src/diff.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,33 @@ export type DiffInfo = {
2121
hunkId: number;
2222
};
2323

24+
function splitLines(str: string): string[] {
25+
if (str === '') {
26+
return [];
27+
}
28+
return str.split(/\r?\n/);
29+
}
30+
2431
export function computeGitChanges(
25-
original: string, current: string
32+
original: string[] | string,
33+
current: string[] | string
2634
): Map<number, DiffInfo> {
2735
const changes = new Map<number, DiffInfo>();
28-
const diffs = JsDiff.diffLines(original, current);
29-
const currentLineCount = current === '' ? 1 : current.split('\n').length;
36+
const originalLines = typeof original === 'string' ? splitLines(original) : original;
37+
const currentLines = typeof current === 'string' ? splitLines(current) : current;
38+
39+
const diffs = JsDiff.diffArrays(originalLines, currentLines);
40+
const currentLineCount = currentLines.length === 0 ? 1 : currentLines.length;
3041

3142
let oldLine = 1;
3243
let newLine = 1;
3344
let hunkId = 0;
3445
let inChangeBlock = false;
3546

36-
const countLines = (value: string): number => {
37-
if (value === '') {
38-
return 0;
39-
}
40-
const parts = value.split('\n');
41-
return value.endsWith('\n') ? parts.length - 1 : parts.length;
42-
};
43-
4447
for (let i = 0; i < diffs.length; i++) {
4548
const diff = diffs[i];
4649
const { added, removed } = diff;
47-
const count = countLines(diff.value);
50+
const count = diff.value.length;
4851

4952
if (added || removed) {
5053
inChangeBlock = true;
@@ -58,7 +61,7 @@ export function computeGitChanges(
5861

5962
const next = diffs[i + 1];
6063
if (next?.added) {
61-
const addedCount = countLines(next.value);
64+
const addedCount = next.value.length;
6265
for (let j = 0; j < addedCount; j++) {
6366
changes.set(newLine + j, {
6467
changeType: 'modified',

anycode-base/src/editor.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1561,7 +1561,10 @@ export class AnycodeEditor {
15611561

15621562
private recomputeDiffs(): void {
15631563
if (this.diffEnabled && this.originalCode) {
1564-
this.diffs = computeGitChanges(this.originalCode.getContent(), this.code.getContent());
1564+
this.diffs = computeGitChanges(
1565+
this.originalCode.getLines(),
1566+
this.code.getLines()
1567+
);
15651568
} else {
15661569
this.diffs = undefined;
15671570
}

anycode-base/src/renderer/DiffRenderer.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ export class DiffRenderer {
207207
* lines are non-contiguous (i.e. some lines were hidden).
208208
* No-op when focused diff is disabled.
209209
*/
210-
public insertSeparators(rows: VisualRow[]): VisualRow[] {
210+
public insertSeparators(rows: VisualRow[], totalLines: number): VisualRow[] {
211211
if (!this.focusedDiffEnabled) {
212212
return rows;
213213
}
@@ -217,7 +217,18 @@ export class DiffRenderer {
217217

218218
for (const row of rows) {
219219
if (row.kind === 'real') {
220-
if (prevRealLine !== null && row.lineIndex - prevRealLine > 1) {
220+
if (prevRealLine === null) {
221+
if (row.lineIndex > 0) {
222+
const hiddenStart = 0;
223+
const hiddenEnd = row.lineIndex - 1;
224+
result.push({
225+
kind: 'separator',
226+
hiddenStart,
227+
hiddenEnd,
228+
hiddenCount: hiddenEnd - hiddenStart + 1,
229+
});
230+
}
231+
} else if (row.lineIndex - prevRealLine > 1) {
221232
const hiddenStart = prevRealLine + 1;
222233
const hiddenEnd = row.lineIndex - 1;
223234
result.push({
@@ -232,6 +243,26 @@ export class DiffRenderer {
232243
result.push(row);
233244
}
234245

246+
if (prevRealLine !== null) {
247+
if (prevRealLine < totalLines - 1) {
248+
const hiddenStart = prevRealLine + 1;
249+
const hiddenEnd = totalLines - 1;
250+
result.push({
251+
kind: 'separator',
252+
hiddenStart,
253+
hiddenEnd,
254+
hiddenCount: hiddenEnd - hiddenStart + 1,
255+
});
256+
}
257+
} else if (totalLines > 0) {
258+
result.push({
259+
kind: 'separator',
260+
hiddenStart: 0,
261+
hiddenEnd: totalLines - 1,
262+
hiddenCount: totalLines,
263+
});
264+
}
265+
235266
return result;
236267
}
237268

anycode-base/src/renderer/Renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ export class Renderer {
258258
}
259259
}
260260

261-
return this.diffRenderer.insertSeparators(rows);
261+
return this.diffRenderer.insertSeparators(rows, totalLines);
262262
}
263263

264264
public expandFocusedHiddenRange(
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { DiffRenderer } from '../src/renderer/DiffRenderer';
3+
import { VisualRow } from '../src/renderer/Renderer';
4+
5+
describe('DiffRenderer.insertSeparators', () => {
6+
it('should add gaps at start and end of file when appropriate', () => {
7+
const renderer = new DiffRenderer({} as any, {} as any, {} as any);
8+
renderer.setFocusedDiffMode(true);
9+
10+
// Case 1: Gap at start only (line 0 is hidden, lines 1 and 2 are visible)
11+
const rows1: VisualRow[] = [
12+
{ kind: 'real', lineIndex: 1 },
13+
{ kind: 'real', lineIndex: 2 },
14+
];
15+
const result1 = renderer.insertSeparators(rows1, 3);
16+
expect(result1).toEqual([
17+
{ kind: 'separator', hiddenStart: 0, hiddenEnd: 0, hiddenCount: 1 },
18+
{ kind: 'real', lineIndex: 1 },
19+
{ kind: 'real', lineIndex: 2 },
20+
]);
21+
22+
// Case 2: Gap at end only (lines 0 and 1 are visible, line 2 is hidden)
23+
const rows2: VisualRow[] = [
24+
{ kind: 'real', lineIndex: 0 },
25+
{ kind: 'real', lineIndex: 1 },
26+
];
27+
const result2 = renderer.insertSeparators(rows2, 3);
28+
expect(result2).toEqual([
29+
{ kind: 'real', lineIndex: 0 },
30+
{ kind: 'real', lineIndex: 1 },
31+
{ kind: 'separator', hiddenStart: 2, hiddenEnd: 2, hiddenCount: 1 },
32+
]);
33+
34+
// Case 3: Gaps at both start and end
35+
const rows3: VisualRow[] = [
36+
{ kind: 'real', lineIndex: 2 },
37+
{ kind: 'real', lineIndex: 3 },
38+
];
39+
const result3 = renderer.insertSeparators(rows3, 6);
40+
expect(result3).toEqual([
41+
{ kind: 'separator', hiddenStart: 0, hiddenEnd: 1, hiddenCount: 2 },
42+
{ kind: 'real', lineIndex: 2 },
43+
{ kind: 'real', lineIndex: 3 },
44+
{ kind: 'separator', hiddenStart: 4, hiddenEnd: 5, hiddenCount: 2 },
45+
]);
46+
47+
// Case 4: No gaps (first and last lines are visible)
48+
const rows4: VisualRow[] = [
49+
{ kind: 'real', lineIndex: 0 },
50+
{ kind: 'real', lineIndex: 1 },
51+
{ kind: 'real', lineIndex: 2 },
52+
];
53+
const result4 = renderer.insertSeparators(rows4, 3);
54+
expect(result4).toEqual([
55+
{ kind: 'real', lineIndex: 0 },
56+
{ kind: 'real', lineIndex: 1 },
57+
{ kind: 'real', lineIndex: 2 },
58+
]);
59+
60+
// Case 5: Empty file
61+
const rows5: VisualRow[] = [];
62+
const result5 = renderer.insertSeparators(rows5, 0);
63+
expect(result5).toEqual([]);
64+
65+
// Case 6: Entire file hidden
66+
const rows6: VisualRow[] = [];
67+
const result6 = renderer.insertSeparators(rows6, 5);
68+
expect(result6).toEqual([
69+
{ kind: 'separator', hiddenStart: 0, hiddenEnd: 4, hiddenCount: 5 },
70+
]);
71+
72+
// Case 7: Only ghost rows in input (entire file is hidden, but ghost rows exist)
73+
const rows7: VisualRow[] = [
74+
{ kind: 'ghost', hunkId: 0, anchorLine: 1, originalLineIndex: 0 },
75+
];
76+
const result7 = renderer.insertSeparators(rows7, 3);
77+
expect(result7).toEqual([
78+
{ kind: 'ghost', hunkId: 0, anchorLine: 1, originalLineIndex: 0 },
79+
{ kind: 'separator', hiddenStart: 0, hiddenEnd: 2, hiddenCount: 3 },
80+
]);
81+
});
82+
});
83+

0 commit comments

Comments
 (0)