+24
-102
src/execution/error.rs
+24
-102
src/execution/error.rs
···
5
5
// Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.
6
6
// ------------------------------------------------------------------------------------------------
7
7
8
-
#[cfg(feature = "term-colors")]
9
-
use colored::Colorize;
10
8
use std::path::Path;
11
9
use thiserror::Error;
12
10
13
-
use crate::ast::{Stanza, Statement};
11
+
use crate::ast::Stanza;
12
+
use crate::ast::Statement;
14
13
use crate::execution::CancellationError;
14
+
use crate::parse_error::Excerpt;
15
15
use crate::Location;
16
16
17
17
/// An error that can occur while executing a graph DSL file
···
213
213
write!(
214
214
f,
215
215
"{}",
216
-
Excerpt::from_source(self.tsg_path, self.tsg, statement_location, 7)
216
+
Excerpt::from_source(
217
+
self.tsg_path,
218
+
self.tsg,
219
+
statement_location.row,
220
+
statement_location.to_column_range(),
221
+
7
222
+
)
217
223
)?;
218
224
writeln!(f, "{}in stanza", " ".repeat(7))?;
219
225
write!(
220
226
f,
221
227
"{}",
222
-
Excerpt::from_source(self.tsg_path, self.tsg, stanza_location, 7)
228
+
Excerpt::from_source(
229
+
self.tsg_path,
230
+
self.tsg,
231
+
stanza_location.row,
232
+
stanza_location.to_column_range(),
233
+
7
234
+
)
223
235
)?;
224
236
writeln!(f, "{}matching ({}) node", " ".repeat(7), node_kind)?;
225
237
write!(
226
238
f,
227
239
"{}",
228
-
Excerpt::from_source(self.source_path, self.source, source_location, 7)
240
+
Excerpt::from_source(
241
+
self.source_path,
242
+
self.source,
243
+
source_location.row,
244
+
source_location.to_column_range(),
245
+
7
246
+
)
229
247
)?;
230
248
Ok(())
231
249
}
···
237
255
}
238
256
}
239
257
}
240
-
241
-
/// Excerpts of source from either the target language file or the tsg rules file.
242
-
struct Excerpt<'a> {
243
-
path: &'a Path,
244
-
source: Option<&'a str>,
245
-
location: &'a Location,
246
-
indent: usize,
247
-
}
248
-
249
-
impl<'a> Excerpt<'a> {
250
-
pub fn from_source(
251
-
path: &'a Path,
252
-
source: &'a str,
253
-
location: &'a Location,
254
-
indent: usize,
255
-
) -> Excerpt<'a> {
256
-
Excerpt {
257
-
path,
258
-
source: source.lines().nth(location.row),
259
-
location,
260
-
indent,
261
-
}
262
-
}
263
-
264
-
fn gutter_width(&self) -> usize {
265
-
((self.location.row + 1) as f64).log10() as usize + 1
266
-
}
267
-
}
268
-
269
-
impl<'a> std::fmt::Display for Excerpt<'a> {
270
-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
271
-
// path and line/col
272
-
write!(
273
-
f,
274
-
"{}{}:{}:{}:",
275
-
" ".repeat(self.indent),
276
-
white_bold(&self.path.to_str().unwrap_or("<unknown file>")),
277
-
white_bold(&format!("{}", self.location.row + 1)),
278
-
white_bold(&format!("{}", self.location.column + 1)),
279
-
)?;
280
-
if let Some(source) = self.source {
281
-
writeln!(f)?;
282
-
// first line: line number & source
283
-
writeln!(
284
-
f,
285
-
"{}{}{}{}",
286
-
" ".repeat(self.indent),
287
-
blue(&format!("{}", self.location.row + 1)),
288
-
blue(" | "),
289
-
source,
290
-
)?;
291
-
// second line: caret
292
-
writeln!(
293
-
f,
294
-
"{}{}{}{}{}",
295
-
" ".repeat(self.indent),
296
-
" ".repeat(self.gutter_width()),
297
-
blue(" | "),
298
-
" ".repeat(self.location.column),
299
-
green_bold("^")
300
-
)?;
301
-
} else {
302
-
writeln!(f, " <missing source>")?;
303
-
}
304
-
Ok(())
305
-
}
306
-
}
307
-
308
-
// coloring functions
309
-
310
-
#[cfg(feature = "term-colors")]
311
-
fn blue(str: &str) -> impl std::fmt::Display {
312
-
str.blue()
313
-
}
314
-
#[cfg(not(feature = "term-colors"))]
315
-
fn blue<'a>(str: &'a str) -> impl std::fmt::Display + 'a {
316
-
str
317
-
}
318
-
319
-
#[cfg(feature = "term-colors")]
320
-
fn green_bold(str: &str) -> impl std::fmt::Display {
321
-
str.green().bold()
322
-
}
323
-
#[cfg(not(feature = "term-colors"))]
324
-
fn green_bold<'a>(str: &'a str) -> impl std::fmt::Display + 'a {
325
-
str
326
-
}
327
-
328
-
#[cfg(feature = "term-colors")]
329
-
fn white_bold(str: &str) -> impl std::fmt::Display {
330
-
str.white().bold()
331
-
}
332
-
#[cfg(not(feature = "term-colors"))]
333
-
fn white_bold<'a>(str: &'a str) -> impl std::fmt::Display + 'a {
334
-
str
335
-
}
+110
-2
src/parse_error.rs
+110
-2
src/parse_error.rs
···
7
7
8
8
//! Data types and functions for finding and displaying tree-sitter parse errors.
9
9
10
+
#[cfg(feature = "term-colors")]
11
+
use colored::Colorize;
12
+
use std::ops::Range;
13
+
use std::path::Path;
10
14
use tree_sitter::Node;
11
15
use tree_sitter::Tree;
12
16
···
57
61
}
58
62
}
59
63
60
-
pub fn display(&self, source: &'tree str, verbose: bool) -> ParseErrorDisplay {
64
+
pub fn display<'a: 'tree>(
65
+
&'a self,
66
+
source: &'tree str,
67
+
verbose: bool,
68
+
) -> impl std::fmt::Display + 'a + 'tree {
61
69
ParseErrorDisplay {
62
70
error: self,
63
71
source,
···
66
74
}
67
75
}
68
76
69
-
pub struct ParseErrorDisplay<'tree> {
77
+
struct ParseErrorDisplay<'tree> {
70
78
error: &'tree ParseError<'tree>,
71
79
source: &'tree str,
72
80
verbose: bool,
···
308
316
// This is okay because Send and Sync _are_ implemented for Tree, which also holds ffi::TSTree
309
317
unsafe impl Send for TreeWithParseErrorVec {}
310
318
unsafe impl Sync for TreeWithParseErrorVec {}
319
+
320
+
//-----------------------------------------------------------------------------
321
+
322
+
/// Excerpts of source from either the target language file or the tsg rules file.
323
+
pub(crate) struct Excerpt<'a> {
324
+
path: &'a Path,
325
+
source: Option<&'a str>,
326
+
row: usize,
327
+
columns: Range<usize>,
328
+
indent: usize,
329
+
}
330
+
331
+
impl<'a> Excerpt<'a> {
332
+
pub fn from_source(
333
+
path: &'a Path,
334
+
source: &'a str,
335
+
row: usize,
336
+
columns: Range<usize>,
337
+
indent: usize,
338
+
) -> Excerpt<'a> {
339
+
Excerpt {
340
+
path,
341
+
source: source.lines().nth(row),
342
+
row,
343
+
columns,
344
+
indent,
345
+
}
346
+
}
347
+
348
+
fn gutter_width(&self) -> usize {
349
+
((self.row + 1) as f64).log10() as usize + 1
350
+
}
351
+
}
352
+
353
+
impl<'a> std::fmt::Display for Excerpt<'a> {
354
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
355
+
// path and line/col
356
+
writeln!(
357
+
f,
358
+
"{}{}:{}:{}:",
359
+
" ".repeat(self.indent),
360
+
white_bold(&self.path.to_str().unwrap_or("<unknown file>")),
361
+
white_bold(&format!("{}", self.row + 1)),
362
+
white_bold(&format!("{}", self.columns.start + 1)),
363
+
)?;
364
+
if let Some(source) = self.source {
365
+
// first line: line number & source
366
+
writeln!(
367
+
f,
368
+
"{}{}{}{}",
369
+
" ".repeat(self.indent),
370
+
blue(&format!("{}", self.row + 1)),
371
+
blue(" | "),
372
+
source,
373
+
)?;
374
+
// second line: caret
375
+
writeln!(
376
+
f,
377
+
"{}{}{}{}{}",
378
+
" ".repeat(self.indent),
379
+
" ".repeat(self.gutter_width()),
380
+
blue(" | "),
381
+
" ".repeat(self.columns.start),
382
+
green_bold(&"^".repeat(self.columns.len()))
383
+
)?;
384
+
} else {
385
+
writeln!(f, "{}{}", " ".repeat(self.indent), "<missing source>",)?;
386
+
}
387
+
Ok(())
388
+
}
389
+
}
390
+
391
+
// coloring functions
392
+
393
+
#[cfg(feature = "term-colors")]
394
+
fn blue(str: &str) -> impl std::fmt::Display {
395
+
str.blue()
396
+
}
397
+
#[cfg(not(feature = "term-colors"))]
398
+
fn blue<'a>(str: &'a str) -> impl std::fmt::Display + 'a {
399
+
str
400
+
}
401
+
402
+
#[cfg(feature = "term-colors")]
403
+
fn green_bold(str: &str) -> impl std::fmt::Display {
404
+
str.green().bold()
405
+
}
406
+
#[cfg(not(feature = "term-colors"))]
407
+
fn green_bold<'a>(str: &'a str) -> impl std::fmt::Display + 'a {
408
+
str
409
+
}
410
+
411
+
#[cfg(feature = "term-colors")]
412
+
fn white_bold(str: &str) -> impl std::fmt::Display {
413
+
str.white().bold()
414
+
}
415
+
#[cfg(not(feature = "term-colors"))]
416
+
fn white_bold<'a>(str: &'a str) -> impl std::fmt::Display + 'a {
417
+
str
418
+
}
+5
src/parser.rs
+5
src/parser.rs
···
7
7
8
8
use std::fmt::Display;
9
9
use std::iter::Peekable;
10
+
use std::ops::Range;
10
11
use std::str::Chars;
11
12
12
13
use regex::Regex;
···
91
92
} else {
92
93
self.column += 1;
93
94
}
95
+
}
96
+
97
+
pub(crate) fn to_column_range(&self) -> Range<usize> {
98
+
self.column..self.column + 1
94
99
}
95
100
}
96
101