1
1
pub use anyhow:: Result ;
2
2
3
3
use ariadne:: { Cache , Config , Label , Report , ReportKind , Source } ;
4
- use itertools:: Itertools ;
5
4
use serde:: de:: Visitor ;
6
5
use serde:: { Deserialize , Serialize } ;
7
6
@@ -11,12 +10,14 @@ use std::fmt::{self, Debug, Display, Formatter};
11
10
use std:: ops:: { Add , Range } ;
12
11
use std:: path:: PathBuf ;
13
12
14
- use crate :: FileTree ;
13
+ use crate :: SourceTree ;
15
14
16
15
#[ derive( Clone , PartialEq , Eq , Copy ) ]
17
16
pub struct Span {
18
17
pub start : usize ,
19
18
pub end : usize ,
19
+
20
+ pub source_id : usize ,
20
21
}
21
22
22
23
#[ derive( Debug , Clone ) ]
@@ -251,21 +252,23 @@ impl ErrorMessages {
251
252
}
252
253
253
254
/// Computes message location and builds the pretty display.
254
- pub fn composed ( mut self , sources : & FileTree , color : bool ) -> Self {
255
+ pub fn composed ( mut self , sources : & SourceTree , color : bool ) -> Self {
255
256
let mut cache = FileTreeCache :: new ( sources) ;
256
257
257
- // TODO: get id from the error
258
- let Ok ( ( id, _) ) = sources. files . iter ( ) . exactly_one ( ) else {
259
- return self ;
260
- } ;
261
-
262
258
for e in & mut self . inner {
263
- let Ok ( source) = cache. fetch ( id) else {
259
+ let Some ( span) = e. span else {
260
+ continue ;
261
+ } ;
262
+ let Some ( source_path) = sources. source_ids . get ( & span. source_id ) else {
263
+ continue ;
264
+ } ;
265
+
266
+ let Ok ( source) = cache. fetch ( source_path) else {
264
267
continue
265
268
} ;
266
269
e. location = e. compose_location ( source) ;
267
270
268
- e. display = e. compose_display ( id . clone ( ) , & mut cache, color) ;
271
+ e. display = e. compose_display ( source_path . clone ( ) , & mut cache, color) ;
269
272
}
270
273
self
271
274
}
@@ -274,17 +277,17 @@ impl ErrorMessages {
274
277
impl ErrorMessage {
275
278
fn compose_display (
276
279
& self ,
277
- source_id : PathBuf ,
280
+ source_path : PathBuf ,
278
281
cache : & mut FileTreeCache ,
279
282
color : bool ,
280
283
) -> Option < String > {
281
284
let config = Config :: default ( ) . with_color ( color) ;
282
285
283
286
let span = Range :: from ( self . span ?) ;
284
287
285
- let mut report = Report :: build ( ReportKind :: Error , source_id . clone ( ) , span. start )
288
+ let mut report = Report :: build ( ReportKind :: Error , source_path . clone ( ) , span. start )
286
289
. with_config ( config)
287
- . with_label ( Label :: new ( ( source_id , span) ) . with_message ( & self . reason ) ) ;
290
+ . with_label ( Label :: new ( ( source_path , span) ) . with_message ( & self . reason ) ) ;
288
291
289
292
if let Some ( code) = & self . code {
290
293
report = report. with_code ( code) ;
@@ -312,11 +315,11 @@ impl ErrorMessage {
312
315
}
313
316
314
317
struct FileTreeCache < ' a > {
315
- file_tree : & ' a FileTree ,
318
+ file_tree : & ' a SourceTree ,
316
319
cache : HashMap < PathBuf , Source > ,
317
320
}
318
321
impl < ' a > FileTreeCache < ' a > {
319
- fn new ( file_tree : & ' a FileTree ) -> Self {
322
+ fn new ( file_tree : & ' a SourceTree ) -> Self {
320
323
FileTreeCache {
321
324
file_tree,
322
325
cache : HashMap :: new ( ) ,
@@ -326,7 +329,7 @@ impl<'a> FileTreeCache<'a> {
326
329
327
330
impl < ' a > Cache < PathBuf > for FileTreeCache < ' a > {
328
331
fn fetch ( & mut self , id : & PathBuf ) -> Result < & Source , Box < dyn fmt:: Debug + ' _ > > {
329
- let file_contents = match self . file_tree . files . get ( id) {
332
+ let file_contents = match self . file_tree . sources . get ( id) {
330
333
Some ( v) => v,
331
334
None => return Err ( Box :: new ( format ! ( "Unknown file `{id:?}`" ) ) ) ,
332
335
} ;
@@ -369,13 +372,14 @@ impl From<Span> for Range<usize> {
369
372
}
370
373
}
371
374
372
- impl Add < Span > for Span {
375
+ impl Add < usize > for Span {
373
376
type Output = Span ;
374
377
375
- fn add ( self , rhs : Span ) -> Span {
378
+ fn add ( self , rhs : usize ) -> Span {
376
379
Span {
377
- start : self . start . min ( rhs. start ) ,
378
- end : self . end . max ( rhs. end ) ,
380
+ start : self . start + rhs,
381
+ end : self . end + rhs,
382
+ source_id : self . source_id ,
379
383
}
380
384
}
381
385
}
@@ -420,7 +424,7 @@ impl<T, E: WithErrorInfo> WithErrorInfo for Result<T, E> {
420
424
421
425
impl Debug for Span {
422
426
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
423
- write ! ( f, "span-chars-{} -{}" , self . start, self . end)
427
+ write ! ( f, "{}:{} -{}" , self . source_id , self . start, self . end)
424
428
}
425
429
}
426
430
@@ -445,7 +449,7 @@ impl<'de> Deserialize<'de> for Span {
445
449
type Value = Span ;
446
450
447
451
fn expecting ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
448
- write ! ( f, "A span string of form `span-chars- x-y`" )
452
+ write ! ( f, "A span string of form `file_id: x-y`" )
449
453
}
450
454
451
455
fn visit_str < E > ( self , v : & str ) -> std:: result:: Result < Self :: Value , E >
@@ -454,18 +458,27 @@ impl<'de> Deserialize<'de> for Span {
454
458
{
455
459
use serde:: de;
456
460
457
- if let Some ( span) = v. strip_prefix ( "span-chars-" ) {
458
- if let Some ( ( start, end) ) = span. split_once ( '-' ) {
461
+ if let Some ( ( file_id, char_span) ) = v. split_once ( ':' ) {
462
+ let file_id = file_id
463
+ . parse :: < usize > ( )
464
+ . map_err ( |e| de:: Error :: custom ( e. to_string ( ) ) ) ?;
465
+
466
+ if let Some ( ( start, end) ) = char_span. split_once ( '-' ) {
459
467
let start = start
460
468
. parse :: < usize > ( )
461
469
. map_err ( |e| de:: Error :: custom ( e. to_string ( ) ) ) ?;
462
470
let end = end
463
471
. parse :: < usize > ( )
464
472
. map_err ( |e| de:: Error :: custom ( e. to_string ( ) ) ) ?;
465
473
466
- return Ok ( Span { start, end } ) ;
474
+ return Ok ( Span {
475
+ start,
476
+ end,
477
+ source_id : file_id,
478
+ } ) ;
467
479
}
468
480
}
481
+
469
482
Err ( de:: Error :: custom ( "malformed span" ) )
470
483
}
471
484
0 commit comments