difftreelog
feat show full error range instead of just start
in: master
4 files changed
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth14 val::ConvertNumValueError,14 val::ConvertNumValueError,15};15};1617#[derive(Debug, Clone)]18pub struct SyntaxErrorLocation {19 pub offset: usize,20}211622#[derive(Debug, Clone)]17#[derive(Debug, Clone)]23pub struct SyntaxError {18pub struct SyntaxError {24 pub message: String,19 pub message: String,25 pub location: SyntaxErrorLocation,20 pub location: (u32, u32),26}21}27impl fmt::Display for SyntaxError {22impl fmt::Display for SyntaxError {28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth50#[cfg(not(any(feature = "ir-parser", feature = "peg-parser")))]50#[cfg(not(any(feature = "ir-parser", feature = "peg-parser")))]51compile_error!("at least one of `ir-parser` or `peg-parser` features must be enabled");51compile_error!("at least one of `ir-parser` or `peg-parser` features must be enabled");525253pub use error::{SyntaxError, SyntaxErrorLocation};53pub use error::SyntaxError;54pub use obj::*;54pub use obj::*;55pub use rustc_hash;55pub use rustc_hash;56use rustc_hash::FxHashMap;56use rustc_hash::FxHashMap;87 jrsonnet_ir_parser::parse(code, &jrsonnet_ir_parser::ParserSettings { source }).map_err(|e| {87 jrsonnet_ir_parser::parse(code, &jrsonnet_ir_parser::ParserSettings { source }).map_err(|e| {88 SyntaxError {88 SyntaxError {89 message: e.message,89 message: e.message,90 location: SyntaxErrorLocation {90 location: (e.location.0, e.location.1),91 offset: e.location.offset,92 },93 }91 }94 })92 })95}93}107 "expected {}, got {:?}",105 "expected {}, got {:?}",108 e.expected,106 e.expected,109 code.chars()107 code.chars()110 .nth(e.location.offset)108 .nth(e.location.0)111 .map_or_else(|| "EOF".into(), |c: char| c.to_string())109 .map_or_else(|| "EOF".into(), |c: char| c.to_string())112 )110 )113 },111 },114 |v| v[3..].into(),112 |v| v[3..].into(),115 );113 );116 SyntaxError {114 SyntaxError {117 message,115 message,118 location: SyntaxErrorLocation {116 location: e.location,119 offset: e.location.offset,120 },121 }117 }122 })118 })123}119}crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth122 || path.source_path().to_string(),122 || path.source_path().to_string(),123 |r| self.resolver.resolve(r),123 |r| self.resolver.resolve(r),124 );124 );125 let mut offset = error.location.offset;125 let mut offset = error.location.0 as usize;126 let is_eof = if offset >= path.code().len() {126 let is_eof = if offset >= path.code().len() {127 offset = path.code().len().saturating_sub(1);127 offset = path.code().len().saturating_sub(1);128 true128 true263 write!(out, "{}", error.error())?;263 write!(out, "{}", error.error())?;264 if let ErrorKind::ImportSyntaxError { path, error } = error.error() {264 if let ErrorKind::ImportSyntaxError { path, error } = error.error() {265 writeln!(out)?;265 writeln!(out)?;266 let offset = error.location.offset;266 let mut offset = error.location;267 // To inclusive range268 if offset.1 > offset.0 {269 offset.1 -= 1;270 }267 let mut builder = SnippetBuilder::new(path.code());271 let mut builder = SnippetBuilder::new(path.code());268 builder272 builder269 .error(Text::fragment("syntax error", Formatting::default()))273 .error(Text::fragment("syntax error", Formatting::default()))270 .range(offset..=offset)274 .range(offset.0 as usize..=offset.1 as usize)271 .build();275 .build();272 let source = builder.build();276 let source = builder.build();273 let ansi = source_to_ansi(&source);277 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 }