stav/check/schema.rs
1//! The declared structs and sum types of a checked program, for tooling.
2
3use super::Checked;
4use super::load::FileId;
5use super::types::{FieldDef, ParamDef};
6
7/// Every struct and sum type a checked program declares, with the doc
8/// comments of the declarations, their fields and their variants.
9#[derive(Debug, Clone, Default, PartialEq, Eq)]
10pub struct SchemaIndex {
11 /// The structs, in the order they were declared.
12 pub structs: Vec<SchemaStruct>,
13 /// The sum types, in the order they were declared.
14 pub sums: Vec<SchemaSum>,
15}
16
17/// A declared struct.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct SchemaStruct {
20 /// The name of the struct.
21 pub name: String,
22 /// The file that declares it.
23 pub file: FileId,
24 /// The doc comment, without the `##` markers.
25 pub doc: Option<String>,
26 /// The fields in declaration order.
27 pub fields: Vec<SchemaField>,
28}
29
30/// A field of a struct or a payload field of a variant.
31#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct SchemaField {
33 /// The name of the field.
34 pub name: String,
35 /// The type as it is written, refinements included.
36 pub ty: String,
37 /// The doc comment, without the `##` markers.
38 pub doc: Option<String>,
39 /// Whether a value must set the field: it has neither a default nor an
40 /// `Option` type.
41 pub required: bool,
42 /// The block kind of a `block kind` clause.
43 pub block: Option<String>,
44}
45
46/// A declared sum type.
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct SchemaSum {
49 /// The name of the sum type.
50 pub name: String,
51 /// The file that declares it.
52 pub file: FileId,
53 /// The doc comment, without the `##` markers.
54 pub doc: Option<String>,
55 /// The variants in declaration order.
56 pub variants: Vec<SchemaVariant>,
57}
58
59/// A variant of a sum type.
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub struct SchemaVariant {
62 /// The name of the variant.
63 pub name: String,
64 /// The doc comment, without the `##` markers.
65 pub doc: Option<String>,
66 /// The payload fields, or `None` for a variant without payload.
67 pub fields: Option<Vec<SchemaField>>,
68}
69
70impl Checked {
71 /// Returns every declared struct field and sum variant with its doc
72 /// comment, for tooling such as completion and documentation.
73 pub fn schema(&self) -> SchemaIndex {
74 let text = |file: FileId, span: crate::Span| {
75 self.source(file)
76 .and_then(|source| source.get(span.range()))
77 .unwrap_or_default()
78 .to_owned()
79 };
80 let field = |file: FileId, f: &FieldDef| SchemaField {
81 name: f.name.clone(),
82 ty: text(file, f.ty_span),
83 doc: f.doc.clone(),
84 required: f.is_required(&self.types),
85 block: f.block.clone(),
86 };
87 let param = |file: FileId, p: &ParamDef| SchemaField {
88 name: p.name.clone(),
89 ty: text(file, p.ty_span),
90 doc: None,
91 required: p.default.is_none() && self.types.unwrap_option(p.ty).is_none(),
92 block: None,
93 };
94 SchemaIndex {
95 structs: self
96 .types
97 .structs
98 .iter()
99 .map(|s| SchemaStruct {
100 name: s.name.clone(),
101 file: s.file,
102 doc: s.doc.clone(),
103 fields: s.fields.iter().map(|f| field(s.file, f)).collect(),
104 })
105 .collect(),
106 sums: self
107 .types
108 .sums
109 .iter()
110 .map(|s| SchemaSum {
111 name: s.name.clone(),
112 file: s.file,
113 doc: s.doc.clone(),
114 variants: s
115 .variants
116 .iter()
117 .map(|v| SchemaVariant {
118 name: v.name.clone(),
119 doc: v.doc.clone(),
120 fields: v
121 .fields
122 .as_ref()
123 .map(|fields| fields.iter().map(|p| param(s.file, p)).collect()),
124 })
125 .collect(),
126 })
127 .collect(),
128 }
129 }
130}