mirror of
https://github.com/tree-sitter/tree-sitter.git
synced 2026-09-10 07:36:22 -04:00
generate: avoid panicking when a supertype only has hidden external token children
This commit skips adding entries to the subtype map when the subtypes list is empty to avoid a lookup failure in the topological sort during node type generation. Co-authored-by: Amaan Qureshi <git@amaanq.com>
This commit is contained in:
parent
0d4f5cb13f
commit
7c2e757c03
|
|
@ -588,7 +588,13 @@ pub fn generate_node_types_json(
|
|||
kind: node_type_json.kind.clone(),
|
||||
named: true,
|
||||
};
|
||||
subtype_map.push((supertype, subtypes.clone()));
|
||||
|
||||
// We only add to the subtype map if there are visible subtypes.
|
||||
// A supertype may have zero subtypes if its children are all
|
||||
// hidden (e.g., wrapping a hidden external token).
|
||||
if !subtypes.is_empty() {
|
||||
subtype_map.push((supertype, subtypes.clone()));
|
||||
}
|
||||
node_type_json.subtypes = Some(subtypes);
|
||||
} else if !syntax_grammar.variables_to_inline.contains(&symbol) {
|
||||
// If a rule is aliased under multiple names, then its information
|
||||
|
|
@ -1260,6 +1266,49 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
/// A supertype whose only child is a hidden external token
|
||||
/// xgust not cause generation to panic. The subtype map must
|
||||
/// skip entries with empty subtypes to avoid a lookup failure
|
||||
/// in the topological sort.
|
||||
#[test]
|
||||
fn test_node_types_supertype_with_only_hidden_child() {
|
||||
let node_types = get_node_types(&InputGrammar {
|
||||
supertype_symbols: vec!["_type_a".to_string(), "_type_b".to_string()],
|
||||
variables: vec![
|
||||
Variable {
|
||||
name: "v1".to_string(),
|
||||
kind: VariableType::Named,
|
||||
rule: Rule::seq(vec![Rule::named("_type_a"), Rule::named("_type_b")]),
|
||||
},
|
||||
// Supertype A: a normal choice of named subtypes
|
||||
Variable {
|
||||
name: "_type_a".to_string(),
|
||||
kind: VariableType::Hidden,
|
||||
rule: Rule::choice(vec![Rule::named("v2"), Rule::named("v3")]),
|
||||
},
|
||||
Variable {
|
||||
name: "v2".to_string(),
|
||||
kind: VariableType::Named,
|
||||
rule: Rule::string("x"),
|
||||
},
|
||||
Variable {
|
||||
name: "v3".to_string(),
|
||||
kind: VariableType::Named,
|
||||
rule: Rule::string("y"),
|
||||
},
|
||||
// Supertype B: a hidden external token with no subtypes
|
||||
Variable {
|
||||
name: "_type_b".to_string(),
|
||||
kind: VariableType::Hidden,
|
||||
rule: Rule::external(0),
|
||||
},
|
||||
],
|
||||
external_tokens: vec![Rule::named("_hidden_ext")],
|
||||
..Default::default()
|
||||
});
|
||||
assert!(node_types.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_types_for_children_without_fields() {
|
||||
let node_types = get_node_types(&InputGrammar {
|
||||
|
|
|
|||
Loading…
Reference in a new issue