use syntax::source_map::{SourceMap, Span, DUMMY_SP};
use crate::rewrite::TextRewrite;
fn empty_span(sp: Span) -> bool {
sp.lo() == sp.hi()
}
fn equal_span_text(cm: &SourceMap, sp1: Span, sp2: Span) -> bool {
if sp1 == sp2 {
return true;
}
let lo1 = cm.lookup_byte_offset(sp1.lo());
let hi1 = cm.lookup_byte_offset(sp1.hi());
let src1 = lo1
.sf
.src
.as_ref()
.unwrap_or_else(|| panic!("source of file {} is not available", lo1.sf.name));
let lo2 = cm.lookup_byte_offset(sp2.lo());
let hi2 = cm.lookup_byte_offset(sp2.hi());
let src2 = lo2
.sf
.src
.as_ref()
.unwrap_or_else(|| panic!("source of file {} is not available", lo2.sf.name));
src1[lo1.pos.0 as usize..hi1.pos.0 as usize] == src2[lo2.pos.0 as usize..hi2.pos.0 as usize]
}
pub fn cleanup_rewrites(cm: &SourceMap, rws: Vec<TextRewrite>) -> Vec<TextRewrite> {
let mut rws = rws;
rws.sort_by_key(|rw| (rw.old_span.lo().0, rw.old_span.hi().0));
let mut new_rws: Vec<TextRewrite> = Vec::with_capacity(rws.len());
for mut rw in rws {
if rw.old_span == DUMMY_SP {
assert!(
rw.new_span == DUMMY_SP,
"tried to insert text at dummy location"
);
continue;
}
rw.rewrites = cleanup_rewrites(cm, rw.rewrites);
if new_rws
.last()
.map_or(true, |prev| prev.old_span.hi().0 <= rw.old_span.lo().0)
{
new_rws.push(rw);
continue;
}
let prev = new_rws.last().unwrap();
if rw.old_span.lo().0 <= prev.old_span.hi().0
&& empty_span(rw.new_span)
&& empty_span(prev.new_span)
{
rw.old_span = rw.old_span.with_lo(prev.old_span.hi());
new_rws.push(rw);
continue;
}
if rw.old_span == prev.old_span
&& equal_span_text(cm, rw.new_span, prev.new_span)
&& rw.rewrites == prev.rewrites
&& rw.adjust == prev.adjust
{
continue;
}
panic!("conflicting rewrites:\nprev = {:#?}\ncur = {:#?}", prev, rw);
}
new_rws
}