Make edit diffs more robust (#493)

This commit is contained in:
Solomon
2025-08-15 16:17:22 +01:00
committed by GitHub
parent 41305215fe
commit c4ea84e7cf
2 changed files with 41 additions and 17 deletions

View File

@@ -82,10 +82,19 @@ pub fn extract_unified_diff_hunks(unified_diff: &str) -> Vec<String> {
.filter(|line| line.starts_with([' ', '+', '-']))
.collect::<String>();
let old_count = lines
.iter()
.filter(|line| line.starts_with(['-', ' ']))
.count();
let new_count = lines
.iter()
.filter(|line| line.starts_with(['+', ' ']))
.count();
return if hunk.is_empty() {
vec![]
} else {
vec!["@@\n".to_string() + &hunk]
vec![format!("@@ -0,{old_count} +0,{new_count} @@\n{hunk}")]
};
}
@@ -185,7 +194,12 @@ pub fn concatenate_diff_hunks(file_path: &str, hunks: &[String]) -> String {
unified_diff.push_str(&header);
if !hunks.is_empty() {
unified_diff.push_str(hunks.join("\n").as_str());
let lines = hunks
.iter()
.flat_map(|hunk| hunk.lines())
.filter(|line| line.starts_with("@@ ") || line.starts_with([' ', '+', '-']))
.collect::<Vec<_>>();
unified_diff.push_str(lines.join("\n").as_str());
if !unified_diff.ends_with('\n') {
unified_diff.push('\n');
}

View File

@@ -25,12 +25,9 @@ type Props = {
* - Decide whether to hide line numbers based on backend data
*/
function processUnifiedDiff(unifiedDiff: string, hasLineNumbers: boolean) {
const totalHunks = unifiedDiff
.split('\n')
.filter((line) => line.startsWith('@@ ')).length;
// Hide line numbers when backend says they are unreliable
const hideNums = !hasLineNumbers;
let isValidDiff;
// Pre-compute additions/deletions using the library parser so counts are available while collapsed
let additions = 0;
@@ -43,16 +40,18 @@ function processUnifiedDiff(unifiedDiff: string, hasLineNumbers: boolean) {
else if (line.type === DiffLineType.Delete) deletions++;
}
}
isValidDiff = parsed.hunks.length > 0;
} catch (err) {
console.error('Failed to parse diff hunks:', err);
isValidDiff = false;
}
return {
hunks: [unifiedDiff],
hideLineNumbers: hideNums,
totalHunks,
additions,
deletions,
isValidDiff,
};
}
@@ -65,7 +64,7 @@ function EditDiffRenderer({ path, unifiedDiff, hasLineNumbers }: Props) {
theme = 'dark';
}
const { hunks, hideLineNumbers, totalHunks, additions, deletions } = useMemo(
const { hunks, hideLineNumbers, additions, deletions, isValidDiff } = useMemo(
() => processUnifiedDiff(unifiedDiff, hasLineNumbers),
[path, unifiedDiff, hasLineNumbers]
);
@@ -112,16 +111,27 @@ function EditDiffRenderer({ path, unifiedDiff, hasLineNumbers }: Props) {
</p>
</div>
{expanded && totalHunks > 0 && (
{expanded && (
<div className={'mt-2' + hideLineNumbersClass}>
<DiffView
data={diffData}
diffViewWrap={false}
diffViewTheme={theme}
diffViewHighlight
diffViewMode={DiffModeEnum.Unified}
diffViewFontSize={12}
/>
{isValidDiff ? (
<DiffView
data={diffData}
diffViewWrap={false}
diffViewTheme={theme}
diffViewHighlight
diffViewMode={DiffModeEnum.Unified}
diffViewFontSize={12}
/>
) : (
<>
<pre
className="px-4 pb-4 text-xs font-mono overflow-x-auto whitespace-pre-wrap"
style={{ color: 'hsl(var(--muted-foreground) / 0.9)' }}
>
{unifiedDiff}
</pre>
</>
)}
</div>
)}
</div>