fork of https://github.com/tree-sitter/tree-sitter-graph

Support multiple statements in error context

Changed files
+114 -66
src
execution
+108 -59
src/execution/error.rs
··· 77 77 78 78 #[derive(Clone, Debug)] 79 79 pub enum Context { 80 - Statement(StatementContext), 80 + Statement(Vec<StatementContext>), 81 81 Other(String), 82 82 } 83 83 ··· 109 109 110 110 impl From<StatementContext> for Context { 111 111 fn from(value: StatementContext) -> Self { 112 - Self::Statement(value) 112 + Self::Statement(vec![value]) 113 + } 114 + } 115 + 116 + impl From<(StatementContext, StatementContext)> for Context { 117 + fn from((left, right): (StatementContext, StatementContext)) -> Self { 118 + Self::Statement(vec![left, right]) 113 119 } 114 120 } 115 121 ··· 122 128 impl std::fmt::Display for Context { 123 129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 124 130 match self { 125 - Self::Statement(StatementContext { 126 - statement, 127 - stanza_location, 128 - source_location, 129 - node_kind, 130 - .. 131 - }) => write!( 132 - f, 133 - "Executing {} in stanza at {} matching ({}) node at {}", 134 - statement, stanza_location, node_kind, source_location 135 - ), 136 - Self::Other(msg) => write!(f, "{}", msg), 131 + Self::Statement(stmts) => { 132 + let mut first = true; 133 + for stmt in stmts { 134 + stmt.fmt(f, first)?; 135 + first = false; 136 + } 137 + } 138 + Self::Other(msg) => write!(f, "{}", msg)?, 137 139 } 140 + Ok(()) 141 + } 142 + } 143 + 144 + impl StatementContext { 145 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>, first: bool) -> std::fmt::Result { 146 + if first { 147 + write!(f, "Error executing",)?; 148 + } else { 149 + write!(f, " and executing",)?; 150 + } 151 + write!( 152 + f, 153 + " {} in stanza at {} matching ({}) node at {}", 154 + self.statement, self.stanza_location, self.node_kind, self.source_location 155 + )?; 156 + Ok(()) 138 157 } 139 158 } 140 159 ··· 202 221 match error { 203 222 ExecutionError::InContext(context, cause) => { 204 223 match context { 205 - Context::Statement(StatementContext { 206 - statement, 207 - statement_location, 208 - stanza_location, 209 - source_location, 210 - node_kind, 211 - }) => { 212 - writeln!(f, "{:>5}: Error executing statement {}", index, statement)?; 213 - write!( 214 - f, 215 - "{}", 216 - Excerpt::from_source( 224 + Context::Statement(stmts) => { 225 + let mut first = true; 226 + for stmt in stmts { 227 + stmt.fmt_pretty( 228 + f, 229 + self.source_path, 230 + self.source, 217 231 self.tsg_path, 218 232 self.tsg, 219 - statement_location.row, 220 - statement_location.to_column_range(), 221 - 7 222 - ) 223 - )?; 224 - writeln!(f, "{}in stanza", " ".repeat(7))?; 225 - write!( 226 - f, 227 - "{}", 228 - Excerpt::from_source( 229 - self.tsg_path, 230 - self.tsg, 231 - stanza_location.row, 232 - stanza_location.to_column_range(), 233 - 7 234 - ) 235 - )?; 236 - writeln!(f, "{}matching ({}) node", " ".repeat(7), node_kind)?; 237 - write!( 238 - f, 239 - "{}", 240 - Excerpt::from_source( 241 - self.source_path, 242 - self.source, 243 - source_location.row, 244 - source_location.to_column_range(), 245 - 7 246 - ) 247 - )?; 248 - Ok(()) 233 + index, 234 + first, 235 + )?; 236 + first = false; 237 + } 249 238 } 250 - Context::Other(msg) => writeln!(f, "{:>5}: {}", index, msg), 251 - }?; 252 - self.fmt_entry(f, index + 1, cause) 239 + Context::Other(msg) => writeln!(f, "{:>5}: {}", index, msg)?, 240 + }; 241 + self.fmt_entry(f, index + 1, cause)?; 242 + Ok(()) 253 243 } 254 244 other => writeln!(f, "{:>5}: {}", index, other), 255 245 } 256 246 } 257 247 } 248 + 249 + impl StatementContext { 250 + fn fmt_pretty( 251 + &self, 252 + f: &mut std::fmt::Formatter<'_>, 253 + source_path: &Path, 254 + source: &str, 255 + tsg_path: &Path, 256 + tsg: &str, 257 + index: usize, 258 + first: bool, 259 + ) -> std::fmt::Result { 260 + if first { 261 + writeln!( 262 + f, 263 + "{:>5}: Error executing statement {}", 264 + index, self.statement 265 + )?; 266 + } else { 267 + writeln!(f, " > and executing statement {}", self.statement)?; 268 + } 269 + write!( 270 + f, 271 + "{}", 272 + Excerpt::from_source( 273 + tsg_path, 274 + tsg, 275 + self.statement_location.row, 276 + self.statement_location.to_column_range(), 277 + 7 278 + ) 279 + )?; 280 + writeln!(f, "{}in stanza", " ".repeat(7))?; 281 + write!( 282 + f, 283 + "{}", 284 + Excerpt::from_source( 285 + tsg_path, 286 + tsg, 287 + self.stanza_location.row, 288 + self.stanza_location.to_column_range(), 289 + 7 290 + ) 291 + )?; 292 + writeln!(f, "{}matching ({}) node", " ".repeat(7), self.node_kind)?; 293 + write!( 294 + f, 295 + "{}", 296 + Excerpt::from_source( 297 + source_path, 298 + source, 299 + self.source_location.row, 300 + self.source_location.to_column_range(), 301 + 7 302 + ) 303 + )?; 304 + Ok(()) 305 + } 306 + }
+6 -7
src/execution/lazy/store.rs
··· 85 85 86 86 pub(super) fn evaluate_all(&self, exec: &mut EvaluationContext) -> Result<(), ExecutionError> { 87 87 for variable in &self.elements { 88 - variable.force(exec)?; 88 + let debug_info = variable.debug_info.clone(); 89 + variable.force(exec).with_context(|| debug_info.0.into())?; 89 90 } 90 91 Ok(()) 91 92 } ··· 161 162 match map.insert(node, value.clone()) { 162 163 Some(_) => { 163 164 return Err(ExecutionError::DuplicateVariable(format!( 164 - "{}.{} set at {} and {}", 165 - node, 166 - name, 167 - prev_debug_info.unwrap(), 168 - debug_info, 169 - ))); 165 + "{}.{}", 166 + node, name, 167 + ))) 168 + .with_context(|| (prev_debug_info.unwrap().0, debug_info.0).into()); 170 169 } 171 170 _ => {} 172 171 };