Skip to main content

tree_sitter_generate/
node_types.rs

1#[cfg(feature = "load")]
2use std::collections::HashSet;
3use std::collections::{BTreeMap, BTreeSet, HashMap};
4
5use serde::Serialize;
6use thiserror::Error;
7
8use super::{
9    grammars::{LexicalGrammar, SyntaxGrammar, VariableType},
10    rules::{Alias, AliasMap, Symbol, SymbolType},
11};
12
13#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub enum ChildType {
15    Normal(Symbol),
16    Aliased(Alias),
17}
18
19#[derive(Clone, Debug, Default, PartialEq, Eq)]
20pub struct FieldInfo {
21    pub quantity: ChildQuantity,
22    pub types: Vec<ChildType>,
23}
24
25#[derive(Clone, Debug, Default, PartialEq, Eq)]
26pub struct VariableInfo {
27    pub fields: HashMap<String, FieldInfo>,
28    pub children: FieldInfo,
29    pub children_without_fields: FieldInfo,
30    pub has_multi_step_production: bool,
31}
32
33#[derive(Debug, Serialize, PartialEq, Eq, Default, PartialOrd, Ord)]
34#[cfg(feature = "load")]
35pub struct NodeInfoJSON {
36    #[serde(rename = "type")]
37    kind: String,
38    named: bool,
39    #[serde(skip_serializing_if = "std::ops::Not::not")]
40    root: bool,
41    #[serde(skip_serializing_if = "std::ops::Not::not")]
42    extra: bool,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    fields: Option<BTreeMap<String, FieldInfoJSON>>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    children: Option<FieldInfoJSON>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    subtypes: Option<Vec<NodeTypeJSON>>,
49}
50
51#[derive(Clone, Debug, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
52#[cfg(feature = "load")]
53pub struct NodeTypeJSON {
54    #[serde(rename = "type")]
55    kind: String,
56    named: bool,
57}
58
59#[derive(Debug, Serialize, PartialEq, Eq, PartialOrd, Ord)]
60#[cfg(feature = "load")]
61pub struct FieldInfoJSON {
62    multiple: bool,
63    required: bool,
64    types: Vec<NodeTypeJSON>,
65}
66
67#[derive(Clone, Copy, Debug, PartialEq, Eq)]
68pub struct ChildQuantity {
69    exists: bool,
70    required: bool,
71    multiple: bool,
72}
73
74#[cfg(feature = "load")]
75impl Default for FieldInfoJSON {
76    fn default() -> Self {
77        Self {
78            multiple: false,
79            required: true,
80            types: Vec::new(),
81        }
82    }
83}
84
85impl Default for ChildQuantity {
86    fn default() -> Self {
87        Self::one()
88    }
89}
90
91impl ChildQuantity {
92    #[must_use]
93    const fn zero() -> Self {
94        Self {
95            exists: false,
96            required: false,
97            multiple: false,
98        }
99    }
100
101    #[must_use]
102    const fn one() -> Self {
103        Self {
104            exists: true,
105            required: true,
106            multiple: false,
107        }
108    }
109
110    const fn append(&mut self, other: Self) {
111        if other.exists {
112            if self.exists || other.multiple {
113                self.multiple = true;
114            }
115            if other.required {
116                self.required = true;
117            }
118            self.exists = true;
119        }
120    }
121
122    const fn union(&mut self, other: Self) -> bool {
123        let mut result = false;
124        if !self.exists && other.exists {
125            result = true;
126            self.exists = true;
127        }
128        if self.required && !other.required {
129            result = true;
130            self.required = false;
131        }
132        if !self.multiple && other.multiple {
133            result = true;
134            self.multiple = true;
135        }
136        result
137    }
138}
139
140pub type VariableInfoResult<T> = Result<T, VariableInfoError>;
141
142#[derive(Debug, Error, Serialize)]
143pub enum VariableInfoError {
144    #[error("Grammar error: Supertype symbols must always have a single visible child, but `{0}` can have multiple")]
145    InvalidSupertype(String),
146}
147
148/// Compute a summary of the public-facing structure of each variable in the
149/// grammar. Each variable in the grammar corresponds to a distinct public-facing
150/// node type.
151///
152/// The information collected about each node type `N` is:
153/// 1. `child_types` - The types of visible children that can appear within `N`.
154/// 2. `fields` - The fields that `N` can have. Data regarding each field:
155///    * `types` - The types of visible children the field can contain.
156///    * `optional` - Do `N` nodes always have this field?
157///    * `multiple` - Can `N` nodes have multiple children for this field?
158/// 3. `children_without_fields` - The *other* named children of `N` that are not associated with
159///    fields. Data regarding these children:
160///    * `types` - The types of named children with no field.
161///    * `optional` - Do `N` nodes always have at least one named child with no field?
162///    * `multiple` - Can `N` nodes have multiple named children with no field?
163///
164/// Each summary must account for some indirect factors:
165/// 1. hidden nodes. When a parent node `N` has a hidden child `C`, the visible children of `C`
166///    *appear* to be direct children of `N`.
167/// 2. aliases. If a parent node type `M` is aliased as some other type `N`, then nodes which
168///    *appear* to have type `N` may have internal structure based on `M`.
169pub fn get_variable_info(
170    syntax_grammar: &SyntaxGrammar,
171    lexical_grammar: &LexicalGrammar,
172    default_aliases: &AliasMap,
173) -> VariableInfoResult<Vec<VariableInfo>> {
174    let child_type_is_visible = |t: &ChildType| {
175        variable_type_for_child_type(t, syntax_grammar, lexical_grammar) >= VariableType::Anonymous
176    };
177
178    let child_type_is_named = |t: &ChildType| {
179        variable_type_for_child_type(t, syntax_grammar, lexical_grammar) == VariableType::Named
180    };
181
182    // Each variable's summary can depend on the summaries of other hidden variables,
183    // and variables can have mutually recursive structure. So we compute the summaries
184    // iteratively, in a loop that terminates only when no more changes are possible.
185    let mut did_change = true;
186    let mut all_initialized = false;
187    let mut result = vec![VariableInfo::default(); syntax_grammar.variables.len()];
188    while did_change {
189        did_change = false;
190
191        for (i, variable) in syntax_grammar.variables.iter().enumerate() {
192            let mut variable_info = result[i].clone();
193
194            // Examine each of the variable's productions. The variable's child types can be
195            // immediately combined across all productions, but the child quantities must be
196            // recorded separately for each production.
197            for production in &variable.productions {
198                let mut production_field_quantities = HashMap::new();
199                let mut production_children_quantity = ChildQuantity::zero();
200                let mut production_children_without_fields_quantity = ChildQuantity::zero();
201                let mut production_has_uninitialized_invisible_children = false;
202
203                if production.steps.len() > 1 {
204                    variable_info.has_multi_step_production = true;
205                }
206
207                for step in &production.steps {
208                    let child_symbol = step.symbol;
209                    let child_type = if let Some(alias) = &step.alias {
210                        ChildType::Aliased(alias.clone())
211                    } else if let Some(alias) = default_aliases.get(&step.symbol) {
212                        ChildType::Aliased(alias.clone())
213                    } else {
214                        ChildType::Normal(child_symbol)
215                    };
216
217                    let child_is_hidden = !child_type_is_visible(&child_type)
218                        && !syntax_grammar.supertype_symbols.contains(&child_symbol);
219
220                    // Maintain the set of all child types for this variable, and the quantity of
221                    // visible children in this production.
222                    did_change |=
223                        extend_sorted(&mut variable_info.children.types, Some(&child_type));
224                    if !child_is_hidden {
225                        production_children_quantity.append(ChildQuantity::one());
226                    }
227
228                    // Maintain the set of child types associated with each field, and the quantity
229                    // of children associated with each field in this production.
230                    if let Some(field_name) = &step.field_name {
231                        let field_info = variable_info
232                            .fields
233                            .entry(field_name.clone())
234                            .or_insert_with(FieldInfo::default);
235                        did_change |= extend_sorted(&mut field_info.types, Some(&child_type));
236
237                        let production_field_quantity = production_field_quantities
238                            .entry(field_name)
239                            .or_insert_with(ChildQuantity::zero);
240
241                        // Inherit the types and quantities of hidden children associated with
242                        // fields.
243                        if child_is_hidden && child_symbol.is_non_terminal() {
244                            let child_variable_info = &result[child_symbol.index];
245                            did_change |= extend_sorted(
246                                &mut field_info.types,
247                                &child_variable_info.children.types,
248                            );
249                            production_field_quantity.append(child_variable_info.children.quantity);
250                        } else {
251                            production_field_quantity.append(ChildQuantity::one());
252                        }
253                    }
254                    // Maintain the set of named children without fields within this variable.
255                    else if child_type_is_named(&child_type) {
256                        production_children_without_fields_quantity.append(ChildQuantity::one());
257                        did_change |= extend_sorted(
258                            &mut variable_info.children_without_fields.types,
259                            Some(&child_type),
260                        );
261                    }
262
263                    // Inherit all child information from hidden children.
264                    if child_is_hidden && child_symbol.is_non_terminal() {
265                        let child_variable_info = &result[child_symbol.index];
266
267                        // If a hidden child can have multiple children, then its parent node can
268                        // appear to have multiple children.
269                        if child_variable_info.has_multi_step_production {
270                            variable_info.has_multi_step_production = true;
271                        }
272
273                        // If a hidden child has fields, then the parent node can appear to have
274                        // those same fields.
275                        for (field_name, child_field_info) in &child_variable_info.fields {
276                            production_field_quantities
277                                .entry(field_name)
278                                .or_insert_with(ChildQuantity::zero)
279                                .append(child_field_info.quantity);
280                            did_change |= extend_sorted(
281                                &mut variable_info
282                                    .fields
283                                    .entry(field_name.clone())
284                                    .or_insert_with(FieldInfo::default)
285                                    .types,
286                                &child_field_info.types,
287                            );
288                        }
289
290                        // If a hidden child has children, then the parent node can appear to have
291                        // those same children.
292                        production_children_quantity.append(child_variable_info.children.quantity);
293                        did_change |= extend_sorted(
294                            &mut variable_info.children.types,
295                            &child_variable_info.children.types,
296                        );
297
298                        // If a hidden child can have named children without fields, then the parent
299                        // node can appear to have those same children.
300                        if step.field_name.is_none() {
301                            let grandchildren_info = &child_variable_info.children_without_fields;
302                            if !grandchildren_info.types.is_empty() {
303                                production_children_without_fields_quantity
304                                    .append(child_variable_info.children_without_fields.quantity);
305                                did_change |= extend_sorted(
306                                    &mut variable_info.children_without_fields.types,
307                                    &child_variable_info.children_without_fields.types,
308                                );
309                            }
310                        }
311                    }
312
313                    // Note whether or not this production contains children whose summaries
314                    // have not yet been computed.
315                    if child_symbol.index >= i && !all_initialized {
316                        production_has_uninitialized_invisible_children = true;
317                    }
318                }
319
320                // If this production's children all have had their summaries initialized,
321                // then expand the quantity information with all of the possibilities introduced
322                // by this production.
323                if !production_has_uninitialized_invisible_children {
324                    did_change |= variable_info
325                        .children
326                        .quantity
327                        .union(production_children_quantity);
328
329                    did_change |= variable_info
330                        .children_without_fields
331                        .quantity
332                        .union(production_children_without_fields_quantity);
333
334                    for (field_name, info) in &mut variable_info.fields {
335                        did_change |= info.quantity.union(
336                            production_field_quantities
337                                .get(field_name)
338                                .copied()
339                                .unwrap_or_else(ChildQuantity::zero),
340                        );
341                    }
342                }
343            }
344
345            result[i] = variable_info;
346        }
347
348        all_initialized = true;
349    }
350
351    for supertype_symbol in &syntax_grammar.supertype_symbols {
352        if result[supertype_symbol.index].has_multi_step_production {
353            let variable = &syntax_grammar.variables[supertype_symbol.index];
354            Err(VariableInfoError::InvalidSupertype(variable.name.clone()))?;
355        }
356    }
357
358    // Update all of the node type lists to eliminate hidden nodes.
359    for supertype_symbol in &syntax_grammar.supertype_symbols {
360        result[supertype_symbol.index]
361            .children
362            .types
363            .retain(child_type_is_visible);
364    }
365    for variable_info in &mut result {
366        for field_info in variable_info.fields.values_mut() {
367            field_info.types.retain(child_type_is_visible);
368        }
369        variable_info.fields.retain(|_, v| !v.types.is_empty());
370        variable_info
371            .children_without_fields
372            .types
373            .retain(child_type_is_visible);
374    }
375
376    Ok(result)
377}
378
379fn get_aliases_by_symbol(
380    syntax_grammar: &SyntaxGrammar,
381    default_aliases: &AliasMap,
382) -> HashMap<Symbol, BTreeSet<Option<Alias>>> {
383    let mut aliases_by_symbol = HashMap::new();
384    for (symbol, alias) in default_aliases {
385        aliases_by_symbol.insert(*symbol, {
386            let mut aliases = BTreeSet::new();
387            aliases.insert(Some(alias.clone()));
388            aliases
389        });
390    }
391    for extra_symbol in &syntax_grammar.extra_symbols {
392        if !default_aliases.contains_key(extra_symbol) {
393            aliases_by_symbol
394                .entry(*extra_symbol)
395                .or_insert_with(BTreeSet::new)
396                .insert(None);
397        }
398    }
399    for variable in &syntax_grammar.variables {
400        for production in &variable.productions {
401            for step in &production.steps {
402                aliases_by_symbol
403                    .entry(step.symbol)
404                    .or_insert_with(BTreeSet::new)
405                    .insert(
406                        step.alias
407                            .as_ref()
408                            .or_else(|| default_aliases.get(&step.symbol))
409                            .cloned(),
410                    );
411            }
412        }
413    }
414    aliases_by_symbol.insert(
415        Symbol::non_terminal(0),
416        std::iter::once(&None).cloned().collect(),
417    );
418    aliases_by_symbol
419}
420
421pub fn get_supertype_symbol_map(
422    syntax_grammar: &SyntaxGrammar,
423    default_aliases: &AliasMap,
424    variable_info: &[VariableInfo],
425) -> BTreeMap<Symbol, Vec<ChildType>> {
426    let aliases_by_symbol = get_aliases_by_symbol(syntax_grammar, default_aliases);
427    let mut supertype_symbol_map = BTreeMap::new();
428
429    let mut symbols_by_alias = HashMap::new();
430    for (symbol, aliases) in &aliases_by_symbol {
431        for alias in aliases.iter().flatten() {
432            symbols_by_alias
433                .entry(alias)
434                .or_insert_with(Vec::new)
435                .push(*symbol);
436        }
437    }
438
439    for (i, info) in variable_info.iter().enumerate() {
440        let symbol = Symbol::non_terminal(i);
441        if syntax_grammar.supertype_symbols.contains(&symbol) {
442            let subtypes = info.children.types.clone();
443            supertype_symbol_map.insert(symbol, subtypes);
444        }
445    }
446    supertype_symbol_map
447}
448
449#[cfg(feature = "load")]
450pub type SuperTypeCycleResult<T> = Result<T, SuperTypeCycleError>;
451
452#[derive(Debug, Error, Serialize)]
453pub struct SuperTypeCycleError {
454    items: Vec<String>,
455}
456
457impl std::fmt::Display for SuperTypeCycleError {
458    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
459        write!(f, "Dependency cycle detected in node types:")?;
460        for (i, item) in self.items.iter().enumerate() {
461            write!(f, " {item}")?;
462            if i < self.items.len() - 1 {
463                write!(f, ",")?;
464            }
465        }
466
467        Ok(())
468    }
469}
470
471#[cfg(feature = "load")]
472pub fn generate_node_types_json(
473    syntax_grammar: &SyntaxGrammar,
474    lexical_grammar: &LexicalGrammar,
475    default_aliases: &AliasMap,
476    variable_info: &[VariableInfo],
477) -> SuperTypeCycleResult<Vec<NodeInfoJSON>> {
478    let mut node_types_json = BTreeMap::new();
479
480    let child_type_to_node_type = |child_type: &ChildType| match child_type {
481        ChildType::Aliased(alias) => NodeTypeJSON {
482            kind: alias.value.clone(),
483            named: alias.is_named,
484        },
485        ChildType::Normal(symbol) => {
486            if let Some(alias) = default_aliases.get(symbol) {
487                NodeTypeJSON {
488                    kind: alias.value.clone(),
489                    named: alias.is_named,
490                }
491            } else {
492                match symbol.kind {
493                    SymbolType::NonTerminal => {
494                        let variable = &syntax_grammar.variables[symbol.index];
495                        NodeTypeJSON {
496                            kind: variable.name.clone(),
497                            named: variable.kind != VariableType::Anonymous,
498                        }
499                    }
500                    SymbolType::Terminal => {
501                        let variable = &lexical_grammar.variables[symbol.index];
502                        NodeTypeJSON {
503                            kind: variable.name.clone(),
504                            named: variable.kind != VariableType::Anonymous,
505                        }
506                    }
507                    SymbolType::External => {
508                        let variable = &syntax_grammar.external_tokens[symbol.index];
509                        NodeTypeJSON {
510                            kind: variable.name.clone(),
511                            named: variable.kind != VariableType::Anonymous,
512                        }
513                    }
514                    _ => panic!("Unexpected symbol type"),
515                }
516            }
517        }
518    };
519
520    let populate_field_info_json = |json: &mut FieldInfoJSON, info: &FieldInfo| {
521        if info.types.is_empty() {
522            json.required = false;
523        } else {
524            json.multiple |= info.quantity.multiple;
525            json.required &= info.quantity.required;
526            json.types
527                .extend(info.types.iter().map(child_type_to_node_type));
528            json.types.sort_unstable();
529            json.types.dedup();
530        }
531    };
532
533    let aliases_by_symbol = get_aliases_by_symbol(syntax_grammar, default_aliases);
534
535    let empty = BTreeSet::new();
536    let extra_names = syntax_grammar
537        .extra_symbols
538        .iter()
539        .flat_map(|symbol| {
540            aliases_by_symbol
541                .get(symbol)
542                .unwrap_or(&empty)
543                .iter()
544                .map(|alias| {
545                    alias.as_ref().map_or(
546                        match symbol.kind {
547                            SymbolType::NonTerminal => &syntax_grammar.variables[symbol.index].name,
548                            SymbolType::Terminal => &lexical_grammar.variables[symbol.index].name,
549                            SymbolType::External => {
550                                &syntax_grammar.external_tokens[symbol.index].name
551                            }
552                            _ => unreachable!(),
553                        },
554                        |alias| &alias.value,
555                    )
556                })
557        })
558        .collect::<HashSet<_>>();
559
560    let mut subtype_map = Vec::new();
561    for (i, info) in variable_info.iter().enumerate() {
562        let symbol = Symbol::non_terminal(i);
563        let variable = &syntax_grammar.variables[i];
564        if syntax_grammar.supertype_symbols.contains(&symbol) {
565            let node_type_json =
566                node_types_json
567                    .entry(variable.name.clone())
568                    .or_insert_with(|| NodeInfoJSON {
569                        kind: variable.name.clone(),
570                        named: true,
571                        root: false,
572                        extra: extra_names.contains(&variable.name),
573                        fields: None,
574                        children: None,
575                        subtypes: None,
576                    });
577            let mut subtypes = info
578                .children
579                .types
580                .iter()
581                .map(child_type_to_node_type)
582                .collect::<Vec<_>>();
583            subtypes.sort_unstable();
584            subtypes.dedup();
585            let supertype = NodeTypeJSON {
586                kind: node_type_json.kind.clone(),
587                named: true,
588            };
589
590            // We only add to the subtype map if there are visible subtypes.
591            // A supertype may have zero subtypes if its children are all
592            // hidden (e.g., wrapping a hidden external token).
593            if !subtypes.is_empty() {
594                subtype_map.push((supertype, subtypes.clone()));
595            }
596            node_type_json.subtypes = Some(subtypes);
597        } else if !syntax_grammar.variables_to_inline.contains(&symbol) {
598            // If a rule is aliased under multiple names, then its information
599            // contributes to multiple entries in the final JSON.
600            for alias in aliases_by_symbol.get(&symbol).unwrap_or(&BTreeSet::new()) {
601                let kind;
602                let is_named;
603                if let Some(alias) = alias {
604                    kind = &alias.value;
605                    is_named = alias.is_named;
606                } else if variable.kind.is_visible() {
607                    kind = &variable.name;
608                    is_named = variable.kind == VariableType::Named;
609                } else {
610                    continue;
611                }
612
613                // There may already be an entry with this name, because multiple
614                // rules may be aliased with the same name.
615                let mut node_type_existed = true;
616                let node_type_json = node_types_json.entry(kind.clone()).or_insert_with(|| {
617                    node_type_existed = false;
618                    NodeInfoJSON {
619                        kind: kind.clone(),
620                        named: is_named,
621                        root: i == 0,
622                        extra: extra_names.contains(&kind),
623                        fields: Some(BTreeMap::new()),
624                        children: None,
625                        subtypes: None,
626                    }
627                });
628
629                let fields_json = node_type_json.fields.as_mut().unwrap();
630                for (new_field, field_info) in &info.fields {
631                    let field_json = fields_json.entry(new_field.clone()).or_insert_with(|| {
632                        // If another rule is aliased with the same name, and does *not* have this
633                        // field, then this field cannot be required.
634                        let mut field_json = FieldInfoJSON::default();
635                        if node_type_existed {
636                            field_json.required = false;
637                        }
638                        field_json
639                    });
640                    populate_field_info_json(field_json, field_info);
641                }
642
643                // If another rule is aliased with the same name, any fields that aren't present in
644                // this cannot be required.
645                for (existing_field, field_json) in fields_json.iter_mut() {
646                    if !info.fields.contains_key(existing_field) {
647                        field_json.required = false;
648                    }
649                }
650
651                populate_field_info_json(
652                    node_type_json
653                        .children
654                        .get_or_insert(FieldInfoJSON::default()),
655                    &info.children_without_fields,
656                );
657            }
658        }
659    }
660
661    // Sort the subtype map topologically so that subtypes are listed before their supertypes.
662    let mut sorted_kinds = Vec::with_capacity(subtype_map.len());
663    let mut top_sort = topological_sort::TopologicalSort::<String>::new();
664    for (supertype, subtypes) in &subtype_map {
665        for subtype in subtypes {
666            top_sort.add_dependency(subtype.kind.clone(), supertype.kind.clone());
667        }
668    }
669    loop {
670        let mut next_kinds = top_sort.pop_all();
671        match (next_kinds.is_empty(), top_sort.is_empty()) {
672            (true, true) => break,
673            (true, false) => {
674                let mut items = top_sort.collect::<Vec<String>>();
675                items.sort();
676                return Err(SuperTypeCycleError { items });
677            }
678            (false, _) => {
679                next_kinds.sort();
680                sorted_kinds.extend(next_kinds);
681            }
682        }
683    }
684    subtype_map.sort_by(|a, b| {
685        let a_idx = sorted_kinds.iter().position(|n| n.eq(&a.0.kind)).unwrap();
686        let b_idx = sorted_kinds.iter().position(|n| n.eq(&b.0.kind)).unwrap();
687        a_idx.cmp(&b_idx)
688    });
689
690    for node_type_json in node_types_json.values_mut() {
691        if node_type_json
692            .children
693            .as_ref()
694            .is_some_and(|c| c.types.is_empty())
695        {
696            node_type_json.children = None;
697        }
698
699        if let Some(children) = &mut node_type_json.children {
700            process_supertypes(children, &subtype_map);
701        }
702        if let Some(fields) = &mut node_type_json.fields {
703            for field_info in fields.values_mut() {
704                process_supertypes(field_info, &subtype_map);
705            }
706        }
707    }
708
709    let mut anonymous_node_types = Vec::new();
710
711    let regular_tokens = lexical_grammar
712        .variables
713        .iter()
714        .enumerate()
715        .flat_map(|(i, variable)| {
716            aliases_by_symbol
717                .get(&Symbol::terminal(i))
718                .unwrap_or(&empty)
719                .iter()
720                .map(move |alias| {
721                    alias
722                        .as_ref()
723                        .map_or((&variable.name, variable.kind), |alias| {
724                            (&alias.value, alias.kind())
725                        })
726                })
727        });
728    let external_tokens =
729        syntax_grammar
730            .external_tokens
731            .iter()
732            .enumerate()
733            .flat_map(|(i, token)| {
734                aliases_by_symbol
735                    .get(&Symbol::external(i))
736                    .unwrap_or(&empty)
737                    .iter()
738                    .map(move |alias| {
739                        alias.as_ref().map_or((&token.name, token.kind), |alias| {
740                            (&alias.value, alias.kind())
741                        })
742                    })
743            });
744
745    for (name, kind) in regular_tokens.chain(external_tokens) {
746        match kind {
747            VariableType::Named => {
748                let node_type_json =
749                    node_types_json
750                        .entry(name.clone())
751                        .or_insert_with(|| NodeInfoJSON {
752                            kind: name.clone(),
753                            named: true,
754                            root: false,
755                            extra: extra_names.contains(&name),
756                            fields: None,
757                            children: None,
758                            subtypes: None,
759                        });
760                if let Some(children) = &mut node_type_json.children {
761                    children.required = false;
762                }
763                if let Some(fields) = &mut node_type_json.fields {
764                    for field in fields.values_mut() {
765                        field.required = false;
766                    }
767                }
768            }
769            VariableType::Anonymous => anonymous_node_types.push(NodeInfoJSON {
770                kind: name.clone(),
771                named: false,
772                root: false,
773                extra: extra_names.contains(&name),
774                fields: None,
775                children: None,
776                subtypes: None,
777            }),
778            _ => {}
779        }
780    }
781
782    let mut result = node_types_json.into_iter().map(|e| e.1).collect::<Vec<_>>();
783    result.extend(anonymous_node_types);
784    result.sort_unstable_by(|a, b| {
785        b.subtypes
786            .is_some()
787            .cmp(&a.subtypes.is_some())
788            .then_with(|| {
789                let a_is_leaf = a.children.is_none() && a.fields.is_none();
790                let b_is_leaf = b.children.is_none() && b.fields.is_none();
791                a_is_leaf.cmp(&b_is_leaf)
792            })
793            .then_with(|| a.kind.cmp(&b.kind))
794            .then_with(|| a.named.cmp(&b.named))
795            .then_with(|| a.root.cmp(&b.root))
796            .then_with(|| a.extra.cmp(&b.extra))
797    });
798    result.dedup();
799    Ok(result)
800}
801
802#[cfg(feature = "load")]
803fn process_supertypes(info: &mut FieldInfoJSON, subtype_map: &[(NodeTypeJSON, Vec<NodeTypeJSON>)]) {
804    for (supertype, subtypes) in subtype_map {
805        if info.types.contains(supertype) {
806            info.types.retain(|t| !subtypes.contains(t));
807        }
808    }
809}
810
811fn variable_type_for_child_type(
812    child_type: &ChildType,
813    syntax_grammar: &SyntaxGrammar,
814    lexical_grammar: &LexicalGrammar,
815) -> VariableType {
816    match child_type {
817        ChildType::Aliased(alias) => alias.kind(),
818        ChildType::Normal(symbol) => {
819            if syntax_grammar.supertype_symbols.contains(symbol) {
820                VariableType::Named
821            } else if syntax_grammar.variables_to_inline.contains(symbol) {
822                VariableType::Hidden
823            } else {
824                match symbol.kind {
825                    SymbolType::NonTerminal => syntax_grammar.variables[symbol.index].kind,
826                    SymbolType::Terminal => lexical_grammar.variables[symbol.index].kind,
827                    SymbolType::External => syntax_grammar.external_tokens[symbol.index].kind,
828                    _ => VariableType::Hidden,
829                }
830            }
831        }
832    }
833}
834
835fn extend_sorted<'a, T>(vec: &mut Vec<T>, values: impl IntoIterator<Item = &'a T>) -> bool
836where
837    T: 'a + Clone + Eq + Ord,
838{
839    values.into_iter().fold(false, |acc, value| {
840        if let Err(i) = vec.binary_search(value) {
841            vec.insert(i, value.clone());
842            true
843        } else {
844            acc
845        }
846    })
847}
848
849#[cfg(all(test, feature = "load"))]
850mod tests {
851    use super::*;
852    use crate::{
853        grammars::{
854            InputGrammar, LexicalVariable, Production, ProductionStep, SyntaxVariable, Variable,
855        },
856        prepare_grammar::prepare_grammar,
857        rules::Rule,
858    };
859
860    #[test]
861    fn test_node_types_simple() {
862        let node_types = get_node_types(&InputGrammar {
863            variables: vec![
864                Variable {
865                    name: "v1".to_string(),
866                    kind: VariableType::Named,
867                    rule: Rule::seq(vec![
868                        Rule::field("f1".to_string(), Rule::named("v2")),
869                        Rule::field("f2".to_string(), Rule::string(";")),
870                    ]),
871                },
872                Variable {
873                    name: "v2".to_string(),
874                    kind: VariableType::Named,
875                    rule: Rule::string("x"),
876                },
877                // This rule is not reachable from the start symbol
878                // so it won't be present in the node_types
879                Variable {
880                    name: "v3".to_string(),
881                    kind: VariableType::Named,
882                    rule: Rule::string("y"),
883                },
884            ],
885            ..Default::default()
886        })
887        .unwrap();
888
889        assert_eq!(node_types.len(), 3);
890
891        assert_eq!(
892            node_types[0],
893            NodeInfoJSON {
894                kind: "v1".to_string(),
895                named: true,
896                root: true,
897                extra: false,
898                subtypes: None,
899                children: None,
900                fields: Some(
901                    vec![
902                        (
903                            "f1".to_string(),
904                            FieldInfoJSON {
905                                multiple: false,
906                                required: true,
907                                types: vec![NodeTypeJSON {
908                                    kind: "v2".to_string(),
909                                    named: true,
910                                }]
911                            }
912                        ),
913                        (
914                            "f2".to_string(),
915                            FieldInfoJSON {
916                                multiple: false,
917                                required: true,
918                                types: vec![NodeTypeJSON {
919                                    kind: ";".to_string(),
920                                    named: false,
921                                }]
922                            }
923                        ),
924                    ]
925                    .into_iter()
926                    .collect()
927                )
928            }
929        );
930        assert_eq!(
931            node_types[1],
932            NodeInfoJSON {
933                kind: ";".to_string(),
934                named: false,
935                root: false,
936                extra: false,
937                subtypes: None,
938                children: None,
939                fields: None
940            }
941        );
942        assert_eq!(
943            node_types[2],
944            NodeInfoJSON {
945                kind: "v2".to_string(),
946                named: true,
947                root: false,
948                extra: false,
949                subtypes: None,
950                children: None,
951                fields: None
952            }
953        );
954    }
955
956    #[test]
957    fn test_node_types_simple_extras() {
958        let node_types = get_node_types(&InputGrammar {
959            extra_symbols: vec![Rule::named("v3")],
960            variables: vec![
961                Variable {
962                    name: "v1".to_string(),
963                    kind: VariableType::Named,
964                    rule: Rule::seq(vec![
965                        Rule::field("f1".to_string(), Rule::named("v2")),
966                        Rule::field("f2".to_string(), Rule::string(";")),
967                    ]),
968                },
969                Variable {
970                    name: "v2".to_string(),
971                    kind: VariableType::Named,
972                    rule: Rule::string("x"),
973                },
974                // This rule is not reachable from the start symbol, but
975                // it is reachable from the 'extra_symbols' so it
976                // should be present in the node_types.
977                // But because it's only a literal, it will get replaced by
978                // a lexical variable.
979                Variable {
980                    name: "v3".to_string(),
981                    kind: VariableType::Named,
982                    rule: Rule::string("y"),
983                },
984            ],
985            ..Default::default()
986        })
987        .unwrap();
988
989        assert_eq!(node_types.len(), 4);
990
991        assert_eq!(
992            node_types[0],
993            NodeInfoJSON {
994                kind: "v1".to_string(),
995                named: true,
996                root: true,
997                extra: false,
998                subtypes: None,
999                children: None,
1000                fields: Some(
1001                    vec![
1002                        (
1003                            "f1".to_string(),
1004                            FieldInfoJSON {
1005                                multiple: false,
1006                                required: true,
1007                                types: vec![NodeTypeJSON {
1008                                    kind: "v2".to_string(),
1009                                    named: true,
1010                                }]
1011                            }
1012                        ),
1013                        (
1014                            "f2".to_string(),
1015                            FieldInfoJSON {
1016                                multiple: false,
1017                                required: true,
1018                                types: vec![NodeTypeJSON {
1019                                    kind: ";".to_string(),
1020                                    named: false,
1021                                }]
1022                            }
1023                        ),
1024                    ]
1025                    .into_iter()
1026                    .collect()
1027                )
1028            }
1029        );
1030        assert_eq!(
1031            node_types[1],
1032            NodeInfoJSON {
1033                kind: ";".to_string(),
1034                named: false,
1035                root: false,
1036                extra: false,
1037                subtypes: None,
1038                children: None,
1039                fields: None
1040            }
1041        );
1042        assert_eq!(
1043            node_types[2],
1044            NodeInfoJSON {
1045                kind: "v2".to_string(),
1046                named: true,
1047                root: false,
1048                extra: false,
1049                subtypes: None,
1050                children: None,
1051                fields: None
1052            }
1053        );
1054        assert_eq!(
1055            node_types[3],
1056            NodeInfoJSON {
1057                kind: "v3".to_string(),
1058                named: true,
1059                root: false,
1060                extra: true,
1061                subtypes: None,
1062                children: None,
1063                fields: None
1064            }
1065        );
1066    }
1067
1068    #[test]
1069    fn test_node_types_deeper_extras() {
1070        let node_types = get_node_types(&InputGrammar {
1071            extra_symbols: vec![Rule::named("v3")],
1072            variables: vec![
1073                Variable {
1074                    name: "v1".to_string(),
1075                    kind: VariableType::Named,
1076                    rule: Rule::seq(vec![
1077                        Rule::field("f1".to_string(), Rule::named("v2")),
1078                        Rule::field("f2".to_string(), Rule::string(";")),
1079                    ]),
1080                },
1081                Variable {
1082                    name: "v2".to_string(),
1083                    kind: VariableType::Named,
1084                    rule: Rule::string("x"),
1085                },
1086                // This rule is not reachable from the start symbol, but
1087                // it is reachable from the 'extra_symbols' so it
1088                // should be present in the node_types.
1089                // Because it is not just a literal, it won't get replaced
1090                // by a lexical variable.
1091                Variable {
1092                    name: "v3".to_string(),
1093                    kind: VariableType::Named,
1094                    rule: Rule::seq(vec![Rule::string("y"), Rule::repeat(Rule::string("z"))]),
1095                },
1096            ],
1097            ..Default::default()
1098        })
1099        .unwrap();
1100
1101        assert_eq!(node_types.len(), 6);
1102
1103        assert_eq!(
1104            node_types[0],
1105            NodeInfoJSON {
1106                kind: "v1".to_string(),
1107                named: true,
1108                root: true,
1109                extra: false,
1110                subtypes: None,
1111                children: None,
1112                fields: Some(
1113                    vec![
1114                        (
1115                            "f1".to_string(),
1116                            FieldInfoJSON {
1117                                multiple: false,
1118                                required: true,
1119                                types: vec![NodeTypeJSON {
1120                                    kind: "v2".to_string(),
1121                                    named: true,
1122                                }]
1123                            }
1124                        ),
1125                        (
1126                            "f2".to_string(),
1127                            FieldInfoJSON {
1128                                multiple: false,
1129                                required: true,
1130                                types: vec![NodeTypeJSON {
1131                                    kind: ";".to_string(),
1132                                    named: false,
1133                                }]
1134                            }
1135                        ),
1136                    ]
1137                    .into_iter()
1138                    .collect()
1139                )
1140            }
1141        );
1142        assert_eq!(
1143            node_types[1],
1144            NodeInfoJSON {
1145                kind: "v3".to_string(),
1146                named: true,
1147                root: false,
1148                extra: true,
1149                subtypes: None,
1150                children: None,
1151                fields: Some(BTreeMap::default())
1152            }
1153        );
1154        assert_eq!(
1155            node_types[2],
1156            NodeInfoJSON {
1157                kind: ";".to_string(),
1158                named: false,
1159                root: false,
1160                extra: false,
1161                subtypes: None,
1162                children: None,
1163                fields: None
1164            }
1165        );
1166        assert_eq!(
1167            node_types[3],
1168            NodeInfoJSON {
1169                kind: "v2".to_string(),
1170                named: true,
1171                root: false,
1172                extra: false,
1173                subtypes: None,
1174                children: None,
1175                fields: None
1176            }
1177        );
1178    }
1179
1180    #[test]
1181    fn test_node_types_with_supertypes() {
1182        let node_types = get_node_types(&InputGrammar {
1183            supertype_symbols: vec!["_v2".to_string()],
1184            variables: vec![
1185                Variable {
1186                    name: "v1".to_string(),
1187                    kind: VariableType::Named,
1188                    rule: Rule::field("f1".to_string(), Rule::named("_v2")),
1189                },
1190                Variable {
1191                    name: "_v2".to_string(),
1192                    kind: VariableType::Hidden,
1193                    rule: Rule::choice(vec![
1194                        Rule::named("v3"),
1195                        Rule::named("v4"),
1196                        Rule::string("*"),
1197                    ]),
1198                },
1199                Variable {
1200                    name: "v3".to_string(),
1201                    kind: VariableType::Named,
1202                    rule: Rule::string("x"),
1203                },
1204                Variable {
1205                    name: "v4".to_string(),
1206                    kind: VariableType::Named,
1207                    rule: Rule::string("y"),
1208                },
1209            ],
1210            ..Default::default()
1211        })
1212        .unwrap();
1213
1214        assert_eq!(
1215            node_types[0],
1216            NodeInfoJSON {
1217                kind: "_v2".to_string(),
1218                named: true,
1219                root: false,
1220                extra: false,
1221                fields: None,
1222                children: None,
1223                subtypes: Some(vec![
1224                    NodeTypeJSON {
1225                        kind: "*".to_string(),
1226                        named: false,
1227                    },
1228                    NodeTypeJSON {
1229                        kind: "v3".to_string(),
1230                        named: true,
1231                    },
1232                    NodeTypeJSON {
1233                        kind: "v4".to_string(),
1234                        named: true,
1235                    },
1236                ]),
1237            }
1238        );
1239        assert_eq!(
1240            node_types[1],
1241            NodeInfoJSON {
1242                kind: "v1".to_string(),
1243                named: true,
1244                root: true,
1245                extra: false,
1246                subtypes: None,
1247                children: None,
1248                fields: Some(
1249                    vec![(
1250                        "f1".to_string(),
1251                        FieldInfoJSON {
1252                            multiple: false,
1253                            required: true,
1254                            types: vec![NodeTypeJSON {
1255                                kind: "_v2".to_string(),
1256                                named: true,
1257                            }]
1258                        }
1259                    ),]
1260                    .into_iter()
1261                    .collect()
1262                )
1263            }
1264        );
1265    }
1266
1267    /// A supertype whose only child is a hidden external token
1268    /// xgust not cause generation to panic. The subtype map must
1269    /// skip entries with empty subtypes to avoid a lookup failure
1270    /// in the topological sort.
1271    #[test]
1272    fn test_node_types_supertype_with_only_hidden_child() {
1273        let node_types = get_node_types(&InputGrammar {
1274            supertype_symbols: vec!["_type_a".to_string(), "_type_b".to_string()],
1275            variables: vec![
1276                Variable {
1277                    name: "v1".to_string(),
1278                    kind: VariableType::Named,
1279                    rule: Rule::seq(vec![Rule::named("_type_a"), Rule::named("_type_b")]),
1280                },
1281                // Supertype A: a normal choice of named subtypes
1282                Variable {
1283                    name: "_type_a".to_string(),
1284                    kind: VariableType::Hidden,
1285                    rule: Rule::choice(vec![Rule::named("v2"), Rule::named("v3")]),
1286                },
1287                Variable {
1288                    name: "v2".to_string(),
1289                    kind: VariableType::Named,
1290                    rule: Rule::string("x"),
1291                },
1292                Variable {
1293                    name: "v3".to_string(),
1294                    kind: VariableType::Named,
1295                    rule: Rule::string("y"),
1296                },
1297                // Supertype B: a hidden external token with no subtypes
1298                Variable {
1299                    name: "_type_b".to_string(),
1300                    kind: VariableType::Hidden,
1301                    rule: Rule::external(0),
1302                },
1303            ],
1304            external_tokens: vec![Rule::named("_hidden_ext")],
1305            ..Default::default()
1306        });
1307        assert!(node_types.is_ok());
1308    }
1309
1310    #[test]
1311    fn test_node_types_for_children_without_fields() {
1312        let node_types = get_node_types(&InputGrammar {
1313            variables: vec![
1314                Variable {
1315                    name: "v1".to_string(),
1316                    kind: VariableType::Named,
1317                    rule: Rule::seq(vec![
1318                        Rule::named("v2"),
1319                        Rule::field("f1".to_string(), Rule::named("v3")),
1320                        Rule::named("v4"),
1321                    ]),
1322                },
1323                Variable {
1324                    name: "v2".to_string(),
1325                    kind: VariableType::Named,
1326                    rule: Rule::seq(vec![
1327                        Rule::string("{"),
1328                        Rule::choice(vec![Rule::named("v3"), Rule::Blank]),
1329                        Rule::string("}"),
1330                    ]),
1331                },
1332                Variable {
1333                    name: "v3".to_string(),
1334                    kind: VariableType::Named,
1335                    rule: Rule::string("x"),
1336                },
1337                Variable {
1338                    name: "v4".to_string(),
1339                    kind: VariableType::Named,
1340                    rule: Rule::string("y"),
1341                },
1342            ],
1343            ..Default::default()
1344        })
1345        .unwrap();
1346
1347        assert_eq!(
1348            node_types[0],
1349            NodeInfoJSON {
1350                kind: "v1".to_string(),
1351                named: true,
1352                root: true,
1353                extra: false,
1354                subtypes: None,
1355                children: Some(FieldInfoJSON {
1356                    multiple: true,
1357                    required: true,
1358                    types: vec![
1359                        NodeTypeJSON {
1360                            kind: "v2".to_string(),
1361                            named: true,
1362                        },
1363                        NodeTypeJSON {
1364                            kind: "v4".to_string(),
1365                            named: true,
1366                        },
1367                    ]
1368                }),
1369                fields: Some(
1370                    vec![(
1371                        "f1".to_string(),
1372                        FieldInfoJSON {
1373                            multiple: false,
1374                            required: true,
1375                            types: vec![NodeTypeJSON {
1376                                kind: "v3".to_string(),
1377                                named: true,
1378                            }]
1379                        }
1380                    ),]
1381                    .into_iter()
1382                    .collect()
1383                )
1384            }
1385        );
1386        assert_eq!(
1387            node_types[1],
1388            NodeInfoJSON {
1389                kind: "v2".to_string(),
1390                named: true,
1391                root: false,
1392                extra: false,
1393                subtypes: None,
1394                children: Some(FieldInfoJSON {
1395                    multiple: false,
1396                    required: false,
1397                    types: vec![NodeTypeJSON {
1398                        kind: "v3".to_string(),
1399                        named: true,
1400                    },]
1401                }),
1402                fields: Some(BTreeMap::new()),
1403            }
1404        );
1405    }
1406
1407    #[test]
1408    fn test_node_types_with_inlined_rules() {
1409        let node_types = get_node_types(&InputGrammar {
1410            variables_to_inline: vec!["v2".to_string()],
1411            variables: vec![
1412                Variable {
1413                    name: "v1".to_string(),
1414                    kind: VariableType::Named,
1415                    rule: Rule::seq(vec![Rule::named("v2"), Rule::named("v3")]),
1416                },
1417                // v2 should not appear in the node types, since it is inlined
1418                Variable {
1419                    name: "v2".to_string(),
1420                    kind: VariableType::Named,
1421                    rule: Rule::alias(Rule::string("a"), "x".to_string(), true),
1422                },
1423                Variable {
1424                    name: "v3".to_string(),
1425                    kind: VariableType::Named,
1426                    rule: Rule::string("b"),
1427                },
1428            ],
1429            ..Default::default()
1430        })
1431        .unwrap();
1432
1433        assert_eq!(
1434            node_types[0],
1435            NodeInfoJSON {
1436                kind: "v1".to_string(),
1437                named: true,
1438                root: true,
1439                extra: false,
1440                subtypes: None,
1441                children: Some(FieldInfoJSON {
1442                    multiple: true,
1443                    required: true,
1444                    types: vec![
1445                        NodeTypeJSON {
1446                            kind: "v3".to_string(),
1447                            named: true,
1448                        },
1449                        NodeTypeJSON {
1450                            kind: "x".to_string(),
1451                            named: true,
1452                        },
1453                    ]
1454                }),
1455                fields: Some(BTreeMap::new()),
1456            }
1457        );
1458    }
1459
1460    #[test]
1461    fn test_node_types_for_aliased_nodes() {
1462        let node_types = get_node_types(&InputGrammar {
1463            variables: vec![
1464                Variable {
1465                    name: "thing".to_string(),
1466                    kind: VariableType::Named,
1467                    rule: Rule::choice(vec![Rule::named("type"), Rule::named("expression")]),
1468                },
1469                Variable {
1470                    name: "type".to_string(),
1471                    kind: VariableType::Named,
1472                    rule: Rule::choice(vec![
1473                        Rule::alias(
1474                            Rule::named("identifier"),
1475                            "type_identifier".to_string(),
1476                            true,
1477                        ),
1478                        Rule::string("void"),
1479                    ]),
1480                },
1481                Variable {
1482                    name: "expression".to_string(),
1483                    kind: VariableType::Named,
1484                    rule: Rule::choice(vec![
1485                        Rule::named("identifier"),
1486                        Rule::alias(
1487                            Rule::named("foo_identifier"),
1488                            "identifier".to_string(),
1489                            true,
1490                        ),
1491                    ]),
1492                },
1493                Variable {
1494                    name: "identifier".to_string(),
1495                    kind: VariableType::Named,
1496                    rule: Rule::pattern("\\w+", ""),
1497                },
1498                Variable {
1499                    name: "foo_identifier".to_string(),
1500                    kind: VariableType::Named,
1501                    rule: Rule::pattern("[\\w-]+", ""),
1502                },
1503            ],
1504            ..Default::default()
1505        })
1506        .unwrap();
1507
1508        assert_eq!(node_types.iter().find(|t| t.kind == "foo_identifier"), None);
1509        assert_eq!(
1510            node_types.iter().find(|t| t.kind == "identifier"),
1511            Some(&NodeInfoJSON {
1512                kind: "identifier".to_string(),
1513                named: true,
1514                root: false,
1515                extra: false,
1516                subtypes: None,
1517                children: None,
1518                fields: None,
1519            })
1520        );
1521        assert_eq!(
1522            node_types.iter().find(|t| t.kind == "type_identifier"),
1523            Some(&NodeInfoJSON {
1524                kind: "type_identifier".to_string(),
1525                named: true,
1526                root: false,
1527                extra: false,
1528                subtypes: None,
1529                children: None,
1530                fields: None,
1531            })
1532        );
1533    }
1534
1535    #[test]
1536    fn test_node_types_with_multiple_valued_fields() {
1537        let node_types = get_node_types(&InputGrammar {
1538            variables: vec![
1539                Variable {
1540                    name: "a".to_string(),
1541                    kind: VariableType::Named,
1542                    rule: Rule::seq(vec![
1543                        Rule::choice(vec![
1544                            Rule::Blank,
1545                            Rule::repeat(Rule::field("f1".to_string(), Rule::named("b"))),
1546                        ]),
1547                        Rule::repeat(Rule::named("c")),
1548                    ]),
1549                },
1550                Variable {
1551                    name: "b".to_string(),
1552                    kind: VariableType::Named,
1553                    rule: Rule::string("b"),
1554                },
1555                Variable {
1556                    name: "c".to_string(),
1557                    kind: VariableType::Named,
1558                    rule: Rule::string("c"),
1559                },
1560            ],
1561            ..Default::default()
1562        })
1563        .unwrap();
1564
1565        assert_eq!(
1566            node_types[0],
1567            NodeInfoJSON {
1568                kind: "a".to_string(),
1569                named: true,
1570                root: true,
1571                extra: false,
1572                subtypes: None,
1573                children: Some(FieldInfoJSON {
1574                    multiple: true,
1575                    required: true,
1576                    types: vec![NodeTypeJSON {
1577                        kind: "c".to_string(),
1578                        named: true,
1579                    },]
1580                }),
1581                fields: Some(
1582                    vec![(
1583                        "f1".to_string(),
1584                        FieldInfoJSON {
1585                            multiple: true,
1586                            required: false,
1587                            types: vec![NodeTypeJSON {
1588                                kind: "b".to_string(),
1589                                named: true,
1590                            }]
1591                        }
1592                    )]
1593                    .into_iter()
1594                    .collect()
1595                ),
1596            }
1597        );
1598    }
1599
1600    #[test]
1601    fn test_node_types_with_fields_on_hidden_tokens() {
1602        let node_types = get_node_types(&InputGrammar {
1603            variables: vec![Variable {
1604                name: "script".to_string(),
1605                kind: VariableType::Named,
1606                rule: Rule::seq(vec![
1607                    Rule::field("a".to_string(), Rule::pattern("hi", "")),
1608                    Rule::field("b".to_string(), Rule::pattern("bye", "")),
1609                ]),
1610            }],
1611            ..Default::default()
1612        })
1613        .unwrap();
1614
1615        assert_eq!(
1616            node_types,
1617            [NodeInfoJSON {
1618                kind: "script".to_string(),
1619                named: true,
1620                root: true,
1621                extra: false,
1622                fields: Some(BTreeMap::new()),
1623                children: None,
1624                subtypes: None
1625            }]
1626        );
1627    }
1628
1629    #[test]
1630    fn test_node_types_with_multiple_rules_same_alias_name() {
1631        let node_types = get_node_types(&InputGrammar {
1632            variables: vec![
1633                Variable {
1634                    name: "script".to_string(),
1635                    kind: VariableType::Named,
1636                    rule: Rule::choice(vec![
1637                        Rule::named("a"),
1638                        // Rule `b` is aliased as rule `a`
1639                        Rule::alias(Rule::named("b"), "a".to_string(), true),
1640                    ]),
1641                },
1642                Variable {
1643                    name: "a".to_string(),
1644                    kind: VariableType::Named,
1645                    rule: Rule::seq(vec![
1646                        Rule::field("f1".to_string(), Rule::string("1")),
1647                        Rule::field("f2".to_string(), Rule::string("2")),
1648                    ]),
1649                },
1650                Variable {
1651                    name: "b".to_string(),
1652                    kind: VariableType::Named,
1653                    rule: Rule::seq(vec![
1654                        Rule::field("f2".to_string(), Rule::string("22")),
1655                        Rule::field("f2".to_string(), Rule::string("222")),
1656                        Rule::field("f3".to_string(), Rule::string("3")),
1657                    ]),
1658                },
1659            ],
1660            ..Default::default()
1661        })
1662        .unwrap();
1663
1664        assert_eq!(
1665            &node_types
1666                .iter()
1667                .map(|t| t.kind.as_str())
1668                .collect::<Vec<_>>(),
1669            &["a", "script", "1", "2", "22", "222", "3"]
1670        );
1671
1672        assert_eq!(
1673            &node_types[0..2],
1674            &[
1675                // A combination of the types for `a` and `b`.
1676                NodeInfoJSON {
1677                    kind: "a".to_string(),
1678                    named: true,
1679                    root: false,
1680                    extra: false,
1681                    subtypes: None,
1682                    children: None,
1683                    fields: Some(
1684                        vec![
1685                            (
1686                                "f1".to_string(),
1687                                FieldInfoJSON {
1688                                    multiple: false,
1689                                    required: false,
1690                                    types: vec![NodeTypeJSON {
1691                                        kind: "1".to_string(),
1692                                        named: false,
1693                                    }]
1694                                }
1695                            ),
1696                            (
1697                                "f2".to_string(),
1698                                FieldInfoJSON {
1699                                    multiple: true,
1700                                    required: true,
1701                                    types: vec![
1702                                        NodeTypeJSON {
1703                                            kind: "2".to_string(),
1704                                            named: false,
1705                                        },
1706                                        NodeTypeJSON {
1707                                            kind: "22".to_string(),
1708                                            named: false,
1709                                        },
1710                                        NodeTypeJSON {
1711                                            kind: "222".to_string(),
1712                                            named: false,
1713                                        }
1714                                    ]
1715                                },
1716                            ),
1717                            (
1718                                "f3".to_string(),
1719                                FieldInfoJSON {
1720                                    multiple: false,
1721                                    required: false,
1722                                    types: vec![NodeTypeJSON {
1723                                        kind: "3".to_string(),
1724                                        named: false,
1725                                    }]
1726                                }
1727                            ),
1728                        ]
1729                        .into_iter()
1730                        .collect()
1731                    ),
1732                },
1733                NodeInfoJSON {
1734                    kind: "script".to_string(),
1735                    named: true,
1736                    root: true,
1737                    extra: false,
1738                    subtypes: None,
1739                    // Only one node
1740                    children: Some(FieldInfoJSON {
1741                        multiple: false,
1742                        required: true,
1743                        types: vec![NodeTypeJSON {
1744                            kind: "a".to_string(),
1745                            named: true,
1746                        }]
1747                    }),
1748                    fields: Some(BTreeMap::new()),
1749                }
1750            ]
1751        );
1752    }
1753
1754    #[test]
1755    fn test_node_types_with_tokens_aliased_to_match_rules() {
1756        let node_types = get_node_types(&InputGrammar {
1757            variables: vec![
1758                Variable {
1759                    name: "a".to_string(),
1760                    kind: VariableType::Named,
1761                    rule: Rule::seq(vec![Rule::named("b"), Rule::named("c")]),
1762                },
1763                // Ordinarily, `b` nodes have two named `c` children.
1764                Variable {
1765                    name: "b".to_string(),
1766                    kind: VariableType::Named,
1767                    rule: Rule::seq(vec![Rule::named("c"), Rule::string("B"), Rule::named("c")]),
1768                },
1769                Variable {
1770                    name: "c".to_string(),
1771                    kind: VariableType::Named,
1772                    rule: Rule::choice(vec![
1773                        Rule::string("C"),
1774                        // This token is aliased as a `b`, which will produce a `b` node
1775                        // with no children.
1776                        Rule::alias(Rule::string("D"), "b".to_string(), true),
1777                    ]),
1778                },
1779            ],
1780            ..Default::default()
1781        })
1782        .unwrap();
1783
1784        assert_eq!(
1785            node_types.iter().map(|n| &n.kind).collect::<Vec<_>>(),
1786            &["a", "b", "c", "B", "C"]
1787        );
1788        assert_eq!(
1789            node_types[1],
1790            NodeInfoJSON {
1791                kind: "b".to_string(),
1792                named: true,
1793                root: false,
1794                extra: false,
1795                subtypes: None,
1796                children: Some(FieldInfoJSON {
1797                    multiple: true,
1798                    required: false,
1799                    types: vec![NodeTypeJSON {
1800                        kind: "c".to_string(),
1801                        named: true,
1802                    }]
1803                }),
1804                fields: Some(BTreeMap::new()),
1805            }
1806        );
1807    }
1808
1809    #[test]
1810    fn test_get_variable_info() {
1811        let variable_info = get_variable_info(
1812            &build_syntax_grammar(
1813                vec![
1814                    // Required field `field1` has only one node type.
1815                    SyntaxVariable {
1816                        name: "rule0".to_string(),
1817                        kind: VariableType::Named,
1818                        productions: vec![Production {
1819                            dynamic_precedence: 0,
1820                            steps: vec![
1821                                ProductionStep::new(Symbol::terminal(0)),
1822                                ProductionStep::new(Symbol::non_terminal(1))
1823                                    .with_field_name("field1"),
1824                            ],
1825                        }],
1826                    },
1827                    // Hidden node
1828                    SyntaxVariable {
1829                        name: "_rule1".to_string(),
1830                        kind: VariableType::Hidden,
1831                        productions: vec![Production {
1832                            dynamic_precedence: 0,
1833                            steps: vec![ProductionStep::new(Symbol::terminal(1))],
1834                        }],
1835                    },
1836                    // Optional field `field2` can have two possible node types.
1837                    SyntaxVariable {
1838                        name: "rule2".to_string(),
1839                        kind: VariableType::Named,
1840                        productions: vec![
1841                            Production {
1842                                dynamic_precedence: 0,
1843                                steps: vec![ProductionStep::new(Symbol::terminal(0))],
1844                            },
1845                            Production {
1846                                dynamic_precedence: 0,
1847                                steps: vec![
1848                                    ProductionStep::new(Symbol::terminal(0)),
1849                                    ProductionStep::new(Symbol::terminal(2))
1850                                        .with_field_name("field2"),
1851                                ],
1852                            },
1853                            Production {
1854                                dynamic_precedence: 0,
1855                                steps: vec![
1856                                    ProductionStep::new(Symbol::terminal(0)),
1857                                    ProductionStep::new(Symbol::terminal(3))
1858                                        .with_field_name("field2"),
1859                                ],
1860                            },
1861                        ],
1862                    },
1863                ],
1864                vec![],
1865            ),
1866            &build_lexical_grammar(),
1867            &AliasMap::new(),
1868        )
1869        .unwrap();
1870
1871        assert_eq!(
1872            variable_info[0].fields,
1873            vec![(
1874                "field1".to_string(),
1875                FieldInfo {
1876                    quantity: ChildQuantity {
1877                        exists: true,
1878                        required: true,
1879                        multiple: false,
1880                    },
1881                    types: vec![ChildType::Normal(Symbol::terminal(1))],
1882                }
1883            )]
1884            .into_iter()
1885            .collect::<HashMap<_, _>>()
1886        );
1887
1888        assert_eq!(
1889            variable_info[2].fields,
1890            vec![(
1891                "field2".to_string(),
1892                FieldInfo {
1893                    quantity: ChildQuantity {
1894                        exists: true,
1895                        required: false,
1896                        multiple: false,
1897                    },
1898                    types: vec![
1899                        ChildType::Normal(Symbol::terminal(2)),
1900                        ChildType::Normal(Symbol::terminal(3)),
1901                    ],
1902                }
1903            )]
1904            .into_iter()
1905            .collect::<HashMap<_, _>>()
1906        );
1907    }
1908
1909    #[test]
1910    fn test_get_variable_info_with_repetitions_inside_fields() {
1911        let variable_info = get_variable_info(
1912            &build_syntax_grammar(
1913                vec![
1914                    // Field associated with a repetition.
1915                    SyntaxVariable {
1916                        name: "rule0".to_string(),
1917                        kind: VariableType::Named,
1918                        productions: vec![
1919                            Production {
1920                                dynamic_precedence: 0,
1921                                steps: vec![ProductionStep::new(Symbol::non_terminal(1))
1922                                    .with_field_name("field1")],
1923                            },
1924                            Production {
1925                                dynamic_precedence: 0,
1926                                steps: vec![],
1927                            },
1928                        ],
1929                    },
1930                    // Repetition node
1931                    SyntaxVariable {
1932                        name: "_rule0_repeat".to_string(),
1933                        kind: VariableType::Hidden,
1934                        productions: vec![
1935                            Production {
1936                                dynamic_precedence: 0,
1937                                steps: vec![ProductionStep::new(Symbol::terminal(1))],
1938                            },
1939                            Production {
1940                                dynamic_precedence: 0,
1941                                steps: vec![
1942                                    ProductionStep::new(Symbol::non_terminal(1)),
1943                                    ProductionStep::new(Symbol::non_terminal(1)),
1944                                ],
1945                            },
1946                        ],
1947                    },
1948                ],
1949                vec![],
1950            ),
1951            &build_lexical_grammar(),
1952            &AliasMap::new(),
1953        )
1954        .unwrap();
1955
1956        assert_eq!(
1957            variable_info[0].fields,
1958            vec![(
1959                "field1".to_string(),
1960                FieldInfo {
1961                    quantity: ChildQuantity {
1962                        exists: true,
1963                        required: false,
1964                        multiple: true,
1965                    },
1966                    types: vec![ChildType::Normal(Symbol::terminal(1))],
1967                }
1968            )]
1969            .into_iter()
1970            .collect::<HashMap<_, _>>()
1971        );
1972    }
1973
1974    #[test]
1975    fn test_get_variable_info_with_inherited_fields() {
1976        let variable_info = get_variable_info(
1977            &build_syntax_grammar(
1978                vec![
1979                    SyntaxVariable {
1980                        name: "rule0".to_string(),
1981                        kind: VariableType::Named,
1982                        productions: vec![
1983                            Production {
1984                                dynamic_precedence: 0,
1985                                steps: vec![
1986                                    ProductionStep::new(Symbol::terminal(0)),
1987                                    ProductionStep::new(Symbol::non_terminal(1)),
1988                                    ProductionStep::new(Symbol::terminal(1)),
1989                                ],
1990                            },
1991                            Production {
1992                                dynamic_precedence: 0,
1993                                steps: vec![ProductionStep::new(Symbol::non_terminal(1))],
1994                            },
1995                        ],
1996                    },
1997                    // Hidden node with fields
1998                    SyntaxVariable {
1999                        name: "_rule1".to_string(),
2000                        kind: VariableType::Hidden,
2001                        productions: vec![Production {
2002                            dynamic_precedence: 0,
2003                            steps: vec![
2004                                ProductionStep::new(Symbol::terminal(2)).with_alias(".", false),
2005                                ProductionStep::new(Symbol::terminal(3)).with_field_name("field1"),
2006                            ],
2007                        }],
2008                    },
2009                ],
2010                vec![],
2011            ),
2012            &build_lexical_grammar(),
2013            &AliasMap::new(),
2014        )
2015        .unwrap();
2016
2017        assert_eq!(
2018            variable_info[0].fields,
2019            vec![(
2020                "field1".to_string(),
2021                FieldInfo {
2022                    quantity: ChildQuantity {
2023                        exists: true,
2024                        required: true,
2025                        multiple: false,
2026                    },
2027                    types: vec![ChildType::Normal(Symbol::terminal(3))],
2028                }
2029            )]
2030            .into_iter()
2031            .collect::<HashMap<_, _>>()
2032        );
2033
2034        assert_eq!(
2035            variable_info[0].children_without_fields,
2036            FieldInfo {
2037                quantity: ChildQuantity {
2038                    exists: true,
2039                    required: false,
2040                    multiple: true,
2041                },
2042                types: vec![
2043                    ChildType::Normal(Symbol::terminal(0)),
2044                    ChildType::Normal(Symbol::terminal(1)),
2045                ],
2046            }
2047        );
2048    }
2049
2050    #[test]
2051    fn test_get_variable_info_with_supertypes() {
2052        let variable_info = get_variable_info(
2053            &build_syntax_grammar(
2054                vec![
2055                    SyntaxVariable {
2056                        name: "rule0".to_string(),
2057                        kind: VariableType::Named,
2058                        productions: vec![Production {
2059                            dynamic_precedence: 0,
2060                            steps: vec![
2061                                ProductionStep::new(Symbol::terminal(0)),
2062                                ProductionStep::new(Symbol::non_terminal(1))
2063                                    .with_field_name("field1"),
2064                                ProductionStep::new(Symbol::terminal(1)),
2065                            ],
2066                        }],
2067                    },
2068                    SyntaxVariable {
2069                        name: "_rule1".to_string(),
2070                        kind: VariableType::Hidden,
2071                        productions: vec![
2072                            Production {
2073                                dynamic_precedence: 0,
2074                                steps: vec![ProductionStep::new(Symbol::terminal(2))],
2075                            },
2076                            Production {
2077                                dynamic_precedence: 0,
2078                                steps: vec![ProductionStep::new(Symbol::terminal(3))],
2079                            },
2080                        ],
2081                    },
2082                ],
2083                // _rule1 is a supertype
2084                vec![Symbol::non_terminal(1)],
2085            ),
2086            &build_lexical_grammar(),
2087            &AliasMap::new(),
2088        )
2089        .unwrap();
2090
2091        assert_eq!(
2092            variable_info[0].fields,
2093            vec![(
2094                "field1".to_string(),
2095                FieldInfo {
2096                    quantity: ChildQuantity {
2097                        exists: true,
2098                        required: true,
2099                        multiple: false,
2100                    },
2101                    types: vec![ChildType::Normal(Symbol::non_terminal(1))],
2102                }
2103            )]
2104            .into_iter()
2105            .collect::<HashMap<_, _>>()
2106        );
2107    }
2108
2109    fn get_node_types(grammar: &InputGrammar) -> SuperTypeCycleResult<Vec<NodeInfoJSON>> {
2110        let (syntax_grammar, lexical_grammar, _, default_aliases) =
2111            prepare_grammar(grammar).unwrap();
2112        let variable_info =
2113            get_variable_info(&syntax_grammar, &lexical_grammar, &default_aliases).unwrap();
2114        generate_node_types_json(
2115            &syntax_grammar,
2116            &lexical_grammar,
2117            &default_aliases,
2118            &variable_info,
2119        )
2120    }
2121
2122    fn build_syntax_grammar(
2123        variables: Vec<SyntaxVariable>,
2124        supertype_symbols: Vec<Symbol>,
2125    ) -> SyntaxGrammar {
2126        SyntaxGrammar {
2127            variables,
2128            supertype_symbols,
2129            ..SyntaxGrammar::default()
2130        }
2131    }
2132
2133    fn build_lexical_grammar() -> LexicalGrammar {
2134        let mut lexical_grammar = LexicalGrammar::default();
2135        for i in 0..10 {
2136            lexical_grammar.variables.push(LexicalVariable {
2137                name: format!("token_{i}"),
2138                kind: VariableType::Named,
2139                implicit_precedence: 0,
2140                start_state: 0,
2141            });
2142        }
2143        lexical_grammar
2144    }
2145}