Reliably avoid duplicate subtypes in node-types.json
This commit is contained in:
parent
3ac047679c
commit
f0e4d630d5
1 changed files with 32 additions and 73 deletions
|
|
@ -3,7 +3,6 @@ use super::rules::{Alias, AliasMap, Symbol, SymbolType};
|
|||
use crate::error::{Error, Result};
|
||||
use serde_derive::Serialize;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::mem;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub(crate) enum ChildType {
|
||||
|
|
@ -38,7 +37,7 @@ pub(crate) struct NodeInfoJSON {
|
|||
subtypes: Option<Vec<NodeTypeJSON>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Clone, Debug, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub(crate) struct NodeTypeJSON {
|
||||
#[serde(rename = "type")]
|
||||
kind: String,
|
||||
|
|
@ -136,7 +135,7 @@ impl ChildQuantity {
|
|||
/// not associated with fields. Data regarding these children:
|
||||
/// * `types` - The types of named children with no field.
|
||||
/// * `optional` - Do `N` nodes always have at least one named child with no field?
|
||||
/// * `multiple` - Can `N` nodes have multiple named child with no field?
|
||||
/// * `multiple` - Can `N` nodes have multiple named children with no field?
|
||||
///
|
||||
/// Each summary must account for some indirect factors:
|
||||
/// 1. hidden nodes. When a parent node `N` has a hidden child `C`, the visible
|
||||
|
|
@ -350,46 +349,20 @@ pub(crate) fn get_variable_info(
|
|||
}
|
||||
}
|
||||
|
||||
// Update all of the node type lists to eliminate hidden nodes.
|
||||
for supertype_symbol in &syntax_grammar.supertype_symbols {
|
||||
result[supertype_symbol.index]
|
||||
.child_types
|
||||
.retain(child_type_is_visible);
|
||||
}
|
||||
|
||||
// Update all of the node type lists to account for node visiblity:
|
||||
// * Wherever possible, replace lists of subtypes with their supertypes.
|
||||
// * Remove other hidden node types.
|
||||
for i in 0..result.len() {
|
||||
let mut variable_info = VariableInfo::default();
|
||||
mem::swap(&mut variable_info, &mut result[i]);
|
||||
|
||||
// For each named field, make the `types` list more concise by replacing sets of
|
||||
// subtypes with a single supertype. Also remove any hidden node types.
|
||||
for variable_info in result.iter_mut() {
|
||||
for (_, field_info) in variable_info.fields.iter_mut() {
|
||||
for supertype_symbol in &syntax_grammar.supertype_symbols {
|
||||
sorted_vec_replace(
|
||||
&mut field_info.types,
|
||||
&result[supertype_symbol.index].child_types,
|
||||
ChildType::Normal(*supertype_symbol),
|
||||
);
|
||||
}
|
||||
field_info.types.retain(child_type_is_visible);
|
||||
}
|
||||
|
||||
// Do the same thing for the children without fields.
|
||||
for supertype_symbol in &syntax_grammar.supertype_symbols {
|
||||
sorted_vec_replace(
|
||||
&mut variable_info.children_without_fields.types,
|
||||
&result[supertype_symbol.index].child_types,
|
||||
ChildType::Normal(*supertype_symbol),
|
||||
);
|
||||
}
|
||||
variable_info
|
||||
.children_without_fields
|
||||
.types
|
||||
.retain(child_type_is_visible);
|
||||
|
||||
result[i] = variable_info;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
|
@ -481,6 +454,7 @@ pub(crate) fn generate_node_types_json(
|
|||
[None].into_iter().cloned().collect(),
|
||||
);
|
||||
|
||||
let mut subtype_map = HashMap::new();
|
||||
for (i, info) in variable_info.iter().enumerate() {
|
||||
let symbol = Symbol::non_terminal(i);
|
||||
let variable = &syntax_grammar.variables[i];
|
||||
|
|
@ -500,6 +474,13 @@ pub(crate) fn generate_node_types_json(
|
|||
.iter()
|
||||
.map(child_type_to_node_type)
|
||||
.collect::<Vec<_>>();
|
||||
subtype_map.insert(
|
||||
NodeTypeJSON {
|
||||
kind: node_type_json.kind.clone(),
|
||||
named: true,
|
||||
},
|
||||
subtypes.clone(),
|
||||
);
|
||||
subtypes.sort_unstable();
|
||||
subtypes.dedup();
|
||||
node_type_json.subtypes = Some(subtypes);
|
||||
|
|
@ -568,6 +549,15 @@ pub(crate) fn generate_node_types_json(
|
|||
{
|
||||
node_type_json.children = None;
|
||||
}
|
||||
|
||||
if let Some(children) = &mut node_type_json.children {
|
||||
process_supertypes(children, &subtype_map);
|
||||
}
|
||||
if let Some(fields) = &mut node_type_json.fields {
|
||||
for (_, field_info) in fields.iter_mut() {
|
||||
process_supertypes(field_info, &subtype_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut anonymous_node_types = Vec::new();
|
||||
|
|
@ -656,6 +646,17 @@ pub(crate) fn generate_node_types_json(
|
|||
result
|
||||
}
|
||||
|
||||
fn process_supertypes(
|
||||
info: &mut FieldInfoJSON,
|
||||
subtype_map: &HashMap<NodeTypeJSON, Vec<NodeTypeJSON>>,
|
||||
) {
|
||||
for (supertype, subtypes) in subtype_map {
|
||||
if info.types.contains(supertype) {
|
||||
info.types.retain(|t| !subtypes.contains(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn variable_type_for_child_type(
|
||||
child_type: &ChildType,
|
||||
syntax_grammar: &SyntaxGrammar,
|
||||
|
|
@ -692,48 +693,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn sorted_vec_replace<T>(left: &mut Vec<T>, right: &Vec<T>, value: T) -> bool
|
||||
where
|
||||
T: Eq + Ord,
|
||||
{
|
||||
if left.len() == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
for right_elem in right.iter() {
|
||||
while left[i] < *right_elem {
|
||||
i += 1;
|
||||
if i == left.len() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if left[i] != *right_elem {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
left.retain(|left_elem| {
|
||||
if i == right.len() {
|
||||
return true;
|
||||
}
|
||||
while right[i] < *left_elem {
|
||||
i += 1;
|
||||
if i == right.len() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
right[i] != *left_elem
|
||||
});
|
||||
|
||||
if let Err(i) = left.binary_search(&value) {
|
||||
left.insert(i, value);
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue