(
existing_code: &str,
replacement_range: LineRange,
replacement_code: &str,
)
| 83 | } |
| 84 | |
| 85 | fn apply_line_replacement( |
| 86 | existing_code: &str, |
| 87 | replacement_range: LineRange, |
| 88 | replacement_code: &str, |
| 89 | ) -> Result<String> { |
| 90 | if replacement_range.start_line == 0 |
| 91 | || replacement_range.end_line < replacement_range.start_line |
| 92 | { |
| 93 | bail!( |
| 94 | "invalid replacement range {}..{}", |
| 95 | replacement_range.start_line, |
| 96 | replacement_range.end_line |
| 97 | ); |
| 98 | } |
| 99 | |
| 100 | let mut lines: Vec<&str> = existing_code.split('\n').collect(); |
| 101 | let had_trailing_newline = existing_code.ends_with('\n'); |
| 102 | if had_trailing_newline && lines.last() == Some(&"") { |
| 103 | lines.pop(); |
| 104 | } |
| 105 | |
| 106 | let line_count = lines.len(); |
| 107 | let normalized = replacement_code.replace("\r\n", "\n"); |
| 108 | if line_count == 0 && replacement_range.start_line == 1 && replacement_range.end_line == 1 { |
| 109 | let mut updated = normalized; |
| 110 | if had_trailing_newline && !updated.ends_with('\n') { |
| 111 | updated.push('\n'); |
| 112 | } |
| 113 | return Ok(updated); |
| 114 | } |
| 115 | |
| 116 | if replacement_range.end_line > line_count { |
| 117 | bail!( |
| 118 | "replacement range {}..{} exceeds file length {}", |
| 119 | replacement_range.start_line, |
| 120 | replacement_range.end_line, |
| 121 | line_count |
| 122 | ); |
| 123 | } |
| 124 | |
| 125 | let start_idx = replacement_range.start_line - 1; |
| 126 | let end_idx = replacement_range.end_line; |
| 127 | let replacement_lines = split_lines_preserving_empty(&normalized); |
| 128 | |
| 129 | let mut out = Vec::new(); |
| 130 | out.extend_from_slice(&lines[..start_idx]); |
| 131 | out.extend(replacement_lines.iter().map(|line| line.as_str())); |
| 132 | out.extend_from_slice(&lines[end_idx..]); |
| 133 | |
| 134 | let mut updated = out.join("\n"); |
| 135 | if had_trailing_newline { |
| 136 | updated.push('\n'); |
| 137 | } |
| 138 | Ok(updated) |
| 139 | } |
| 140 | |
| 141 | fn build_unified_diff(file_path: &str, old: &str, new: &str) -> String { |
| 142 | if old == new { |
no test coverage detected
searching dependent graphs…