Skip to main content

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}