difftreelog
feat show full error range instead of just start
in: master
4 files changed
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -15,14 +15,9 @@
};
#[derive(Debug, Clone)]
-pub struct SyntaxErrorLocation {
- pub offset: usize,
-}
-
-#[derive(Debug, Clone)]
pub struct SyntaxError {
pub message: String,
- pub location: SyntaxErrorLocation,
+ pub location: (u32, u32),
}
impl fmt::Display for SyntaxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -50,7 +50,7 @@
#[cfg(not(any(feature = "ir-parser", feature = "peg-parser")))]
compile_error!("at least one of `ir-parser` or `peg-parser` features must be enabled");
-pub use error::{SyntaxError, SyntaxErrorLocation};
+pub use error::SyntaxError;
pub use obj::*;
pub use rustc_hash;
use rustc_hash::FxHashMap;
@@ -87,9 +87,7 @@
jrsonnet_ir_parser::parse(code, &jrsonnet_ir_parser::ParserSettings { source }).map_err(|e| {
SyntaxError {
message: e.message,
- location: SyntaxErrorLocation {
- offset: e.location.offset,
- },
+ location: (e.location.0, e.location.1),
}
})
}
@@ -107,7 +105,7 @@
"expected {}, got {:?}",
e.expected,
code.chars()
- .nth(e.location.offset)
+ .nth(e.location.0)
.map_or_else(|| "EOF".into(), |c: char| c.to_string())
)
},
@@ -115,9 +113,7 @@
);
SyntaxError {
message,
- location: SyntaxErrorLocation {
- offset: e.location.offset,
- },
+ location: e.location,
}
})
}
crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/trace/mod.rs
+++ b/crates/jrsonnet-evaluator/src/trace/mod.rs
@@ -122,7 +122,7 @@
|| path.source_path().to_string(),
|r| self.resolver.resolve(r),
);
- let mut offset = error.location.offset;
+ let mut offset = error.location.0 as usize;
let is_eof = if offset >= path.code().len() {
offset = path.code().len().saturating_sub(1);
true
@@ -263,11 +263,15 @@
write!(out, "{}", error.error())?;
if let ErrorKind::ImportSyntaxError { path, error } = error.error() {
writeln!(out)?;
- let offset = error.location.offset;
+ let mut offset = error.location;
+ // To inclusive range
+ if offset.1 > offset.0 {
+ offset.1 -= 1;
+ }
let mut builder = SnippetBuilder::new(path.code());
builder
.error(Text::fragment("syntax error", Formatting::default()))
- .range(offset..=offset)
+ .range(offset.0 as usize..=offset.1 as usize)
.build();
let source = builder.build();
let ansi = source_to_ansi(&source);
crates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth7 ImportKind, IndexPart, LiteralType, Member, ObjBody, ObjComp, ObjMembers, Slice, SliceDesc,7 ImportKind, IndexPart, LiteralType, Member, ObjBody, ObjComp, ObjMembers, Slice, SliceDesc,8 Source, Span, Spanned, UnaryOpType, Visibility, unescape,8 Source, Span, Spanned, UnaryOpType, Visibility, unescape,9};9};10use jrsonnet_lexer::{Lexeme, Lexer, SyntaxKind, T, collect_lexed_str_block};10use jrsonnet_lexer::{Lexeme, Lexer, Span as LexSpan, SyntaxKind, T, collect_lexed_str_block};111112pub struct ParserSettings {12pub struct ParserSettings {13 pub source: Source,13 pub source: Source,14}14}151516#[derive(Debug, Clone)]16#[derive(Debug, Clone)]17pub struct ParseErrorLocation {18 pub offset: usize,19}2021#[derive(Debug, Clone)]22pub struct ParseError {17pub struct ParseError {23 pub message: String,18 pub message: String,24 pub location: ParseErrorLocation,19 pub location: LexSpan,25}20}262127impl std::fmt::Display for ParseError {22impl std::fmt::Display for ParseError {131126132 fn error(&self, message: String) -> ParseError {127 fn error(&self, message: String) -> ParseError {133 ParseError {128 ParseError {134 location: ParseErrorLocation {129 location: self.lexemes[self.offset].range,135 offset: self.span_start() as usize,136 },137 message,130 message,138 }131 }139 }132 }143 return Err(self.error(format!("expected identifier, got {}", self.current_desc())));136 return Err(self.error(format!("expected identifier, got {}", self.current_desc())));144 }137 }145 let text = self.text();138 let text = self.text();146 if is_reserved(text) {147 return Err(self.error(format!("expected identifier, got reserved word '{text}'")));148 }149 let s: IStr = text.into();139 let s: IStr = text.into();150 self.eat_any();140 self.eat_any();151 Ok(s)141 Ok(s)154 fn at_ident(&self) -> bool {144 fn at_ident(&self) -> bool {155 self.at(SyntaxKind::IDENT) && !is_reserved(self.lexemes[self.offset].text)145 self.at(SyntaxKind::IDENT) && !is_reserved(self.lexemes[self.offset].text)156 }146 }157}158159fn is_reserved(s: &str) -> bool {160 matches!(161 s,162 "assert"163 | "else" | "error"164 | "false" | "for"165 | "function"166 | "if" | "import"167 | "importstr"168 | "importbin"169 | "in" | "local"170 | "null" | "tailstrict"171 | "then" | "self"172 | "super" | "true"173 )174}147}175148176fn spanned<T: Acyclic>(149fn spanned<T: Acyclic>(1040 if let Some(desc) = lexeme.kind.error_description() {1013 if let Some(desc) = lexeme.kind.error_description() {1041 return Err(ParseError {1014 return Err(ParseError {1042 message: desc.to_owned(),1015 message: desc.to_owned(),1043 location: ParseErrorLocation {1016 location: lexeme.range,1044 offset: lexeme.range.0 as usize,1045 },1046 });1017 });1047 }1018 }1048 }1019 }