Ignore PlainText segments when diffing

This commit is contained in:
Luke Street 2024-10-31 17:27:27 -06:00
parent c5da7f7dd5
commit 7f14b684bf
4 changed files with 22 additions and 12 deletions

View File

@ -299,15 +299,10 @@ fn compare_ins(
) -> Result<InsDiffResult> { ) -> Result<InsDiffResult> {
let mut result = InsDiffResult::default(); let mut result = InsDiffResult::default();
if let (Some(left_ins), Some(right_ins)) = (&left.ins, &right.ins) { if let (Some(left_ins), Some(right_ins)) = (&left.ins, &right.ins) {
if left_ins.args.len() != right_ins.args.len() // Count only non-PlainText args
|| left_ins.op != right_ins.op let left_args_count = left_ins.iter_args().count();
// Check if any PlainText segments differ (punctuation and spacing) let right_args_count = right_ins.iter_args().count();
// This indicates a more significant difference than a simple arg mismatch if left_args_count != right_args_count || left_ins.op != right_ins.op {
|| !left_ins.args.iter().zip(&right_ins.args).all(|(a, b)| match (a, b) {
(ObjInsArg::PlainText(l), ObjInsArg::PlainText(r)) => l == r,
_ => true,
})
{
// Totally different op // Totally different op
result.kind = ObjInsDiffKind::Replace; result.kind = ObjInsDiffKind::Replace;
state.diff_count += 1; state.diff_count += 1;
@ -318,7 +313,7 @@ fn compare_ins(
result.kind = ObjInsDiffKind::OpMismatch; result.kind = ObjInsDiffKind::OpMismatch;
state.diff_count += 1; state.diff_count += 1;
} }
for (a, b) in left_ins.args.iter().zip(&right_ins.args) { for (a, b) in left_ins.iter_args().zip(right_ins.iter_args()) {
if arg_eq(config, left_obj, right_obj, a, b, left, right) { if arg_eq(config, left_obj, right_obj, a, b, left, right) {
result.left_args_diff.push(None); result.left_args_diff.push(None);
result.right_args_diff.push(None); result.right_args_diff.push(None);

View File

@ -58,20 +58,23 @@ pub fn display_diff<E>(
cb(DiffText::Spacing(4))?; cb(DiffText::Spacing(4))?;
} }
cb(DiffText::Opcode(&ins.mnemonic, ins.op))?; cb(DiffText::Opcode(&ins.mnemonic, ins.op))?;
let mut arg_diff_idx = 0; // non-PlainText index
for (i, arg) in ins.args.iter().enumerate() { for (i, arg) in ins.args.iter().enumerate() {
if i == 0 { if i == 0 {
cb(DiffText::Spacing(1))?; cb(DiffText::Spacing(1))?;
} }
let diff = ins_diff.arg_diff.get(i).and_then(|o| o.as_ref()); let diff = ins_diff.arg_diff.get(arg_diff_idx).and_then(|o| o.as_ref());
match arg { match arg {
ObjInsArg::PlainText(s) => { ObjInsArg::PlainText(s) => {
cb(DiffText::Basic(s))?; cb(DiffText::Basic(s))?;
} }
ObjInsArg::Arg(v) => { ObjInsArg::Arg(v) => {
cb(DiffText::Argument(v, diff))?; cb(DiffText::Argument(v, diff))?;
arg_diff_idx += 1;
} }
ObjInsArg::Reloc => { ObjInsArg::Reloc => {
display_reloc_name(ins.reloc.as_ref().unwrap(), &mut cb, diff)?; display_reloc_name(ins.reloc.as_ref().unwrap(), &mut cb, diff)?;
arg_diff_idx += 1;
} }
ObjInsArg::BranchDest(dest) => { ObjInsArg::BranchDest(dest) => {
if let Some(dest) = dest.checked_sub(base_addr) { if let Some(dest) = dest.checked_sub(base_addr) {
@ -79,6 +82,7 @@ pub fn display_diff<E>(
} else { } else {
cb(DiffText::Basic("<unknown>"))?; cb(DiffText::Basic("<unknown>"))?;
} }
arg_diff_idx += 1;
} }
} }
} }

View File

@ -245,7 +245,7 @@ pub struct ObjInsDiff {
pub branch_from: Option<ObjInsBranchFrom>, pub branch_from: Option<ObjInsBranchFrom>,
/// Branches to instruction /// Branches to instruction
pub branch_to: Option<ObjInsBranchTo>, pub branch_to: Option<ObjInsBranchTo>,
/// Arg diffs /// Arg diffs (only contains non-PlainText args)
pub arg_diff: Vec<Option<ObjInsArgDiff>>, pub arg_diff: Vec<Option<ObjInsArgDiff>>,
} }

View File

@ -85,6 +85,9 @@ pub enum ObjInsArg {
} }
impl ObjInsArg { impl ObjInsArg {
#[inline]
pub fn is_plain_text(&self) -> bool { matches!(self, ObjInsArg::PlainText(_)) }
pub fn loose_eq(&self, other: &ObjInsArg) -> bool { pub fn loose_eq(&self, other: &ObjInsArg) -> bool {
match (self, other) { match (self, other) {
(ObjInsArg::Arg(a), ObjInsArg::Arg(b)) => a.loose_eq(b), (ObjInsArg::Arg(a), ObjInsArg::Arg(b)) => a.loose_eq(b),
@ -112,6 +115,14 @@ pub struct ObjIns {
pub orig: Option<String>, pub orig: Option<String>,
} }
impl ObjIns {
/// Iterate over non-PlainText arguments.
#[inline]
pub fn iter_args(&self) -> impl DoubleEndedIterator<Item = &ObjInsArg> {
self.args.iter().filter(|a| !a.is_plain_text())
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
pub enum ObjSymbolKind { pub enum ObjSymbolKind {
#[default] #[default]