cratestack_parser/directives.rs
1//! The multi-file directives (`part`, `part of`, `import`), returned beside
2//! the `Schema` and never part of it (docs/design/multi-file-schemas.md
3//! section 2), so `print-ir` and the serialized IR of every existing schema
4//! stay byte-identical.
5
6use cratestack_core::SourceSpan;
7
8/// One `part "…"`, `part of "…"` or `import "…"` line.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct PathDirective {
11 /// The path exactly as written between the quotes.
12 pub path: String,
13 /// Covers exactly the text between the quotes.
14 pub path_span: SourceSpan,
15 /// The trimmed directive line.
16 pub span: SourceSpan,
17}
18
19/// Every multi-file directive one file declares.
20#[derive(Debug, Clone, Default, PartialEq, Eq)]
21pub struct FileDirectives {
22 /// `part "…"`, in source order.
23 pub parts: Vec<PathDirective>,
24 /// `part of "…"`.
25 pub part_of: Option<PathDirective>,
26 /// `import "…"`, in source order.
27 pub imports: Vec<PathDirective>,
28 /// The `transport` line, if written: `Schema` stores only the style (#993).
29 pub(crate) transport_span: Option<SourceSpan>,
30 /// Each `extension` block's name and span: `Schema` keeps only the set.
31 pub(crate) extension_spans: Vec<(String, SourceSpan)>,
32}
33
34impl FileDirectives {
35 /// True when the file declares no `part`, `part of` or `import`.
36 pub fn is_empty(&self) -> bool {
37 self.parts.is_empty() && self.part_of.is_none() && self.imports.is_empty()
38 }
39
40 /// The span of the file's `transport` line, if it has one.
41 pub fn transport_span(&self) -> Option<SourceSpan> {
42 self.transport_span
43 }
44
45 /// Records one `extension` block; returns nothing, keeps `Schema` the same.
46 pub(crate) fn declare_extension(
47 &mut self,
48 into: &mut std::collections::BTreeSet<cratestack_core::ExtensionKind>,
49 kind: cratestack_core::ExtensionKind,
50 block: &cratestack_core::ConfigBlock,
51 ) {
52 into.insert(kind);
53 self.extension_spans.push((block.name.clone(), block.span));
54 }
55}