use serde::Serialize;
#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize)]
pub struct LineColumn {
pub line: usize,
pub column: usize,
}
impl From<proc_macro2::LineColumn> for LineColumn {
fn from(l: proc_macro2::LineColumn) -> Self {
LineColumn {
line: l.line,
column: l.column + 1,
}
}
}
#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize)]
pub struct Span {
pub start: LineColumn,
pub end: LineColumn,
}
impl From<proc_macro2::Span> for Span {
fn from(s: proc_macro2::Span) -> Self {
Span {
start: s.start().into(),
end: s.end().into(),
}
}
}
impl From<&proc_macro2::Span> for Span {
fn from(s: &proc_macro2::Span) -> Self {
Span {
start: s.start().into(),
end: s.end().into(),
}
}
}
pub(crate) fn replace_region(
s: &str,
start: &LineColumn,
end: &LineColumn,
replacement: &str,
) -> String {
let mut r = String::with_capacity(s.len() + replacement.len());
let mut line_no = 1;
let mut col_no = 1;
for c in s.chars() {
if line_no < start.line
|| line_no > end.line
|| (line_no == start.line && col_no < start.column)
|| (line_no == end.line && col_no > end.column)
{
r.push(c);
} else if line_no == start.line && col_no == start.column {
r.push_str(replacement);
}
if c == '\n' {
line_no += 1;
col_no = 1;
} else if c == '\r' {
} else {
col_no += 1;
}
}
r
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn replace_treats_crlf_as_part_of_last_column() {
let source = "fn foo() {\r\n wibble();\r\n}\r\n//hey!\r\n";
assert_eq!(
replace_region(
source,
&LineColumn {
line: 1,
column: 10
},
&LineColumn { line: 3, column: 2 },
"{}\r\n"
),
"fn foo() {}\r\n//hey!\r\n"
);
}
#[test]
fn test_replace_region() {
let source = "
fn foo() {
some();
stuff();
}
const BAR: u32 = 32;
";
assert_eq!(
replace_region(
source,
&LineColumn {
line: 2,
column: 10
},
&LineColumn { line: 5, column: 1 },
"{ /* body deleted */ }"
),
"
fn foo() { /* body deleted */ }
const BAR: u32 = 32;
"
);
assert_eq!(
replace_region(
source,
&LineColumn {
line: 7,
column: 18
},
&LineColumn {
line: 7,
column: 19
},
"69"
),
"
fn foo() {
some();
stuff();
}
const BAR: u32 = 69;
"
);
}
}