|
2 | 2 |
|
3 | 3 | use std::borrow::Cow;
|
4 | 4 | use std::io::Write as _;
|
| 5 | +use std::ops::Range; |
5 | 6 | use std::sync::{atomic, Mutex};
|
6 | 7 |
|
7 | 8 | use annotate_snippets::Annotation;
|
@@ -162,41 +163,64 @@ fn typo_to_group<'t>(msg: &'t Typo<'t>) -> Group<'t> {
|
162 | 163 | let group = match &msg.context {
|
163 | 164 | Some(Context::File(context)) => {
|
164 | 165 | let path = context.path.as_os_str().to_string_lossy();
|
165 |
| - let line = String::from_utf8_lossy(msg.buffer.as_ref()); |
| 166 | + let (line, span) = to_string(&msg.buffer, msg.byte_offset, msg.typo.len()); |
166 | 167 | let snippet = Snippet::source(line)
|
167 | 168 | .path(path)
|
168 | 169 | .line_start(context.line_num);
|
169 |
| - append_corrections(msg, 0, snippet, group) |
| 170 | + append_corrections(span, snippet, group) |
170 | 171 | }
|
171 | 172 | Some(Context::Path(context)) => {
|
172 |
| - let path = context |
173 |
| - .path |
174 |
| - .parent() |
175 |
| - .unwrap_or(std::path::Path::new(".")) |
176 |
| - .join(""); |
177 |
| - let path = path.as_os_str().to_string_lossy(); |
178 |
| - let line = context.path.as_os_str().to_string_lossy(); |
| 173 | + let parent = context.path.parent().unwrap_or(std::path::Path::new(".")); |
| 174 | + let parent = parent.as_os_str().to_string_lossy(); |
| 175 | + let mut line = parent.into_owned(); |
| 176 | + line.push(std::path::MAIN_SEPARATOR); |
| 177 | + let parent_len = line.len(); |
| 178 | + let mut line = line.into_bytes(); |
| 179 | + line.extend(msg.buffer.iter()); |
| 180 | + let (line, span) = to_string(&line, parent_len + msg.byte_offset, msg.typo.len()); |
| 181 | + let line = line.into_owned(); |
179 | 182 | let snippet = Snippet::source(line);
|
180 |
| - append_corrections(msg, path.len(), snippet, group) |
| 183 | + append_corrections(span, snippet, group) |
181 | 184 | }
|
182 | 185 | Some(_) | None => group,
|
183 | 186 | };
|
184 | 187 | group
|
185 | 188 | }
|
186 | 189 |
|
187 | 190 | fn append_corrections<'t>(
|
188 |
| - msg: &'t Typo<'t>, |
189 |
| - offset: usize, |
| 191 | + span: Range<usize>, |
190 | 192 | snippet: Snippet<'t, Annotation<'t>>,
|
191 | 193 | group: Group<'t>,
|
192 | 194 | ) -> Group<'t> {
|
193 |
| - let span_start = msg.byte_offset + offset; |
194 |
| - let span_end = span_start + msg.typo.len(); |
195 |
| - let span = span_start..span_end; |
196 | 195 | let snippet = snippet.annotation(AnnotationKind::Primary.span(span));
|
197 | 196 | group.element(snippet)
|
198 | 197 | }
|
199 | 198 |
|
| 199 | +fn to_string(line: &[u8], start: usize, len: usize) -> (Cow<'_, str>, Range<usize>) { |
| 200 | + let end = start + len; |
| 201 | + |
| 202 | + if let Ok(line) = std::str::from_utf8(line) { |
| 203 | + return (Cow::Borrowed(line), start..end); |
| 204 | + } |
| 205 | + |
| 206 | + let prefix = &line[0..start]; |
| 207 | + let prefix = String::from_utf8_lossy(prefix); |
| 208 | + |
| 209 | + let middle = &line[start..end]; |
| 210 | + let middle = String::from_utf8_lossy(middle); |
| 211 | + |
| 212 | + let suffix = &line[end..]; |
| 213 | + let suffix = String::from_utf8_lossy(suffix); |
| 214 | + |
| 215 | + let span_start = prefix.len(); |
| 216 | + let span_end = span_start + middle.len(); |
| 217 | + |
| 218 | + ( |
| 219 | + Cow::Owned(format!("{prefix}{middle}{suffix}")), |
| 220 | + span_start..span_end, |
| 221 | + ) |
| 222 | +} |
| 223 | + |
200 | 224 | fn error_to_group<'e>(error: &'e Error<'e>) -> Group<'e> {
|
201 | 225 | let group = Group::with_title(Level::ERROR.primary_title(&error.msg));
|
202 | 226 | match &error.context {
|
|
0 commit comments