1use crate::Library;
2use crate::diag::FileResult;
3use compose_codespan_reporting::files::Files;
4use compose_syntax::{FileId, Source, Span};
5use std::io::{Read, Write};
6use std::ops::Range;
7
8pub trait World {
9 fn entry_point(&self) -> FileId;
11
12 fn source(&self, file_id: FileId) -> FileResult<Source>;
13
14 fn library(&self) -> &Library;
15
16 fn write(&self, f: &dyn Fn(&mut dyn Write) -> std::io::Result<()>) -> std::io::Result<()>;
17 fn read(&self, f: &dyn Fn(&mut dyn Read) -> std::io::Result<()>) -> std::io::Result<()>;
18
19 fn name(&self, id: FileId) -> String {
20 id.path().0.display().to_string()
21 }
22
23 fn related_source(&self, span: Span) -> Option<Source> {
24 self.source(span.id()?).ok()
25 }
26}
27
28pub struct SyntaxContext<'a> {
29 pub world: &'a dyn World,
30}
31
32
33impl<'a> Files<'a> for &dyn World {
34 type FileId = FileId;
35 type Name = String;
36 type Source = Source;
37
38 fn name(&'a self, id: Self::FileId) -> Result<Self::Name, compose_codespan_reporting::files::Error> {
39 Ok(World::name(*self, id))
40 }
41
42 fn source(
43 &'a self,
44 id: Self::FileId,
45 ) -> Result<Self::Source, compose_codespan_reporting::files::Error> {
46 World::source(*self, id).map_err(|_| compose_codespan_reporting::files::Error::FileMissing)
47 }
48
49 fn line_index(
50 &'a self,
51 id: Self::FileId,
52 byte_index: usize,
53 ) -> Result<usize, compose_codespan_reporting::files::Error> {
54 let source = Files::source(self, id)?;
55 Ok(source
56 .line_starts()
57 .binary_search(&byte_index)
58 .unwrap_or_else(|next_line| next_line - 1))
59 }
60
61 fn line_range(
62 &'a self,
63 id: Self::FileId,
64 line_index: usize,
65 ) -> Result<Range<usize>, compose_codespan_reporting::files::Error> {
66 let source = Files::source(self, id)?;
67 let start = source.line_starts().get(line_index).copied().ok_or(
68 compose_codespan_reporting::files::Error::LineTooLarge {
69 given: line_index,
70 max: source.line_starts().len(),
71 },
72 )?;
73
74 let end = source
75 .line_starts()
76 .get(line_index + 1)
77 .copied()
78 .unwrap_or(source.text().len());
79
80 Ok(start..end)
81 }
82}