@@ -8,6 +8,15 @@ pub struct NodeType {
88 pub named : bool ,
99}
1010
11+ /// Multiplicity/optionality of a field declaration.
12+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
13+ pub struct FieldCardinality {
14+ /// Whether the field may hold more than one child.
15+ pub multiple : bool ,
16+ /// Whether at least one child must be present.
17+ pub required : bool ,
18+ }
19+
1120/// A schema defining node kinds and field names for the output AST.
1221/// Built from a node-types.yml file, independent of any tree-sitter grammar.
1322///
@@ -32,6 +41,7 @@ pub struct Schema {
3241 kind_names : BTreeMap < KindId , & ' static str > ,
3342 next_kind_id : KindId ,
3443 field_types : BTreeMap < ( String , FieldId ) , Vec < NodeType > > ,
44+ field_cardinalities : BTreeMap < ( String , FieldId ) , FieldCardinality > ,
3545 supertypes : BTreeMap < String , Vec < NodeType > > ,
3646}
3747
@@ -52,6 +62,7 @@ impl Schema {
5262 kind_names : BTreeMap :: new ( ) ,
5363 next_kind_id : 1 , // 0 is reserved
5464 field_types : BTreeMap :: new ( ) ,
65+ field_cardinalities : BTreeMap :: new ( ) ,
5566 supertypes : BTreeMap :: new ( ) ,
5667 }
5768 }
@@ -196,6 +207,42 @@ impl Schema {
196207 . get ( & ( parent_kind. to_string ( ) , field_id) )
197208 }
198209
210+ pub fn set_field_cardinality (
211+ & mut self ,
212+ parent_kind : & str ,
213+ field_id : FieldId ,
214+ cardinality : FieldCardinality ,
215+ ) {
216+ self . field_cardinalities
217+ . insert ( ( parent_kind. to_string ( ) , field_id) , cardinality) ;
218+ }
219+
220+ /// Returns the declared cardinality for a field, if known.
221+ pub fn field_cardinality (
222+ & self ,
223+ parent_kind : & str ,
224+ field_id : FieldId ,
225+ ) -> Option < FieldCardinality > {
226+ self . field_cardinalities
227+ . get ( & ( parent_kind. to_string ( ) , field_id) )
228+ . copied ( )
229+ }
230+
231+ /// Returns an iterator over all `(field_id, field_name)` pairs that are
232+ /// declared as required (`required: true`) for the given `parent_kind`.
233+ pub fn required_fields_for_kind < ' a > (
234+ & ' a self ,
235+ parent_kind : & ' a str ,
236+ ) -> impl Iterator < Item = ( FieldId , Option < & ' static str > ) > + ' a {
237+ self . field_cardinalities
238+ . iter ( )
239+ . filter ( move |( ( kind, _) , card) | kind == parent_kind && card. required )
240+ . map ( move |( ( _, field_id) , _) | {
241+ let name = self . field_name_for_id ( * field_id) ;
242+ ( * field_id, name)
243+ } )
244+ }
245+
199246 pub fn set_supertype_members ( & mut self , supertype : & str , node_types : Vec < NodeType > ) {
200247 self . supertypes . insert ( supertype. to_string ( ) , node_types) ;
201248 }
0 commit comments