(error: parser::ParseError, source_file: &SourceFile)
| 47 | |
| 48 | impl CompileError { |
| 49 | pub fn from_ruff_parse_error(error: parser::ParseError, source_file: &SourceFile) -> Self { |
| 50 | let source_code = source_file.to_source_code(); |
| 51 | let source_text = source_file.source_text(); |
| 52 | |
| 53 | // For EOF errors (unclosed brackets), find the unclosed bracket position |
| 54 | // and adjust both the error location and message |
| 55 | let mut is_unclosed_bracket = false; |
| 56 | let (error_type, location, end_location) = if matches!( |
| 57 | &error.error, |
| 58 | parser::ParseErrorType::Lexical(parser::LexicalErrorType::Eof) |
| 59 | ) { |
| 60 | if let Some((bracket_char, bracket_offset)) = find_unclosed_bracket(source_text) { |
| 61 | let bracket_text_size = ruff_text_size::TextSize::new(bracket_offset as u32); |
| 62 | let loc = source_code.source_location(bracket_text_size, PositionEncoding::Utf8); |
| 63 | let end_loc = SourceLocation { |
| 64 | line: loc.line, |
| 65 | character_offset: loc.character_offset.saturating_add(1), |
| 66 | }; |
| 67 | let msg = format!("'{}' was never closed", bracket_char); |
| 68 | is_unclosed_bracket = true; |
| 69 | (parser::ParseErrorType::OtherError(msg), loc, end_loc) |
| 70 | } else { |
| 71 | let loc = |
| 72 | source_code.source_location(error.location.start(), PositionEncoding::Utf8); |
| 73 | let end_loc = |
| 74 | source_code.source_location(error.location.end(), PositionEncoding::Utf8); |
| 75 | (error.error, loc, end_loc) |
| 76 | } |
| 77 | } else if matches!( |
| 78 | &error.error, |
| 79 | parser::ParseErrorType::Lexical(parser::LexicalErrorType::IndentationError) |
| 80 | ) { |
| 81 | // For IndentationError, point the offset to the end of the line content |
| 82 | // instead of the beginning |
| 83 | let loc = source_code.source_location(error.location.start(), PositionEncoding::Utf8); |
| 84 | let line_idx = loc.line.to_zero_indexed(); |
| 85 | let line = source_text.split('\n').nth(line_idx).unwrap_or(""); |
| 86 | let line_end_col = line.chars().count() + 1; // 1-indexed, past last char |
| 87 | let end_loc = SourceLocation { |
| 88 | line: loc.line, |
| 89 | character_offset: ruff_source_file::OneIndexed::new(line_end_col) |
| 90 | .unwrap_or(loc.character_offset), |
| 91 | }; |
| 92 | (error.error, end_loc, end_loc) |
| 93 | } else { |
| 94 | let loc = source_code.source_location(error.location.start(), PositionEncoding::Utf8); |
| 95 | let mut end_loc = |
| 96 | source_code.source_location(error.location.end(), PositionEncoding::Utf8); |
| 97 | |
| 98 | // If the error range ends at the start of a new line (column 1), |
| 99 | // adjust it to the end of the previous line |
| 100 | if end_loc.character_offset.get() == 1 && end_loc.line > loc.line { |
| 101 | let prev_line_end = error.location.end() - ruff_text_size::TextSize::from(1); |
| 102 | end_loc = source_code.source_location(prev_line_end, PositionEncoding::Utf8); |
| 103 | end_loc.character_offset = end_loc.character_offset.saturating_add(1); |
| 104 | } |
| 105 | |
| 106 | (error.error, loc, end_loc) |
nothing calls this directly
no test coverage detected