tree_splicer/
node_types.rs

1//! Read tree-sitter's `node-types.json`.
2//
3// Copied in part from [treeedbgen] and treereduce.
4//
5// [treeedbgen]: https://github.com/langston-barrett/treeedb/blob/1a2fae3509c76cd5a8e1004f808ea800d49d1a19/treeedbgen/src/lib.rs
6
7use std::collections::HashMap;
8
9use serde::{Deserialize, Serialize};
10
11/// node-types.json
12#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
13struct Node {
14    #[serde(rename(deserialize = "type", serialize = "type"))]
15    ty: String,
16    named: bool,
17    #[serde(default)] // empty
18    children: Children,
19    #[serde(default)] // empty
20    fields: HashMap<String, Field>,
21    #[serde(default)] // empty
22    subtypes: Vec<Subtype>,
23}
24
25#[derive(Default, Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
26struct Children {
27    multiple: bool,
28    required: bool,
29    types: Vec<Subtype>,
30}
31
32#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
33struct Field {
34    multiple: bool,
35    required: bool,
36    types: Vec<Subtype>,
37}
38
39#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug)]
40struct Subtype {
41    #[serde(rename(deserialize = "type", serialize = "type"))]
42    ty: String,
43    named: bool,
44}
45
46#[derive(Clone, Debug)]
47pub struct FieldInfo {
48    parent_ty: String,
49    multiple: bool,
50    required: bool,
51}
52
53#[derive(Clone, Debug)]
54pub struct NodeTypes {
55    children: HashMap<String, Children>,
56    subtypes: HashMap<String, Vec<String>>,
57    reverse_fields: HashMap<String, Vec<FieldInfo>>,
58}
59
60fn subtypes(name: &str, nodes: &Vec<Node>) -> Vec<String> {
61    let mut r = vec![name.to_string()];
62    for n in nodes {
63        if n.ty == name {
64            for subty in &n.subtypes {
65                r.push(subty.ty.clone());
66                r.extend(subtypes(&subty.ty, nodes));
67            }
68        }
69    }
70    r
71}
72
73impl NodeTypes {
74    pub fn new(node_types_json_str: &str) -> Result<Self, serde_json::Error> {
75        let nodes: Vec<Node> = serde_json::from_str(node_types_json_str)?;
76        let subtypes: HashMap<_, _> = nodes
77            .iter()
78            .map(|n| (n.ty.clone(), subtypes(&n.ty, &nodes)))
79            .collect();
80        let mut reverse_fields = HashMap::new();
81
82        // For each type of node...
83        for node in &nodes {
84            // Loop through it's fields...
85            for (_field_name, field) in node.fields.iter() {
86                // And save the name of all types that the field could be.
87                for subtype in &field.types {
88                    for subsubty in subtypes.get(&subtype.ty).unwrap_or(&Vec::new()) {
89                        let entry = reverse_fields.entry(subsubty.clone());
90                        entry
91                            .and_modify(|v: &mut Vec<FieldInfo>| {
92                                v.push(FieldInfo {
93                                    parent_ty: node.ty.clone(),
94                                    multiple: field.multiple,
95                                    required: field.required,
96                                });
97                            })
98                            .or_insert_with(|| {
99                                vec![FieldInfo {
100                                    parent_ty: node.ty.clone(),
101                                    multiple: field.multiple,
102                                    required: field.required,
103                                }]
104                            });
105                    }
106                }
107            }
108        }
109        Ok(NodeTypes {
110            children: nodes
111                .iter()
112                .map(|n| (n.ty.clone(), n.children.clone()))
113                .collect(),
114            subtypes,
115            reverse_fields,
116        })
117    }
118
119    /// Defaults to `true` if the real answer can't be determined.
120    fn optional(&self, node_kind: &str, parent_kind: &str) -> bool {
121        if let Some(flds) = self.reverse_fields.get(node_kind) {
122            for fi in flds {
123                if parent_kind == fi.parent_ty && (!fi.multiple || fi.required) {
124                    return false;
125                }
126            }
127        }
128        true
129    }
130
131    /// Defaults to `true` if the real answer can't be determined.
132    pub fn optional_node(&self, node: &tree_sitter::Node) -> bool {
133        if let Some(p) = node.parent() {
134            self.optional(node.kind(), p.kind())
135        } else {
136            true
137        }
138    }
139
140    // TODO(#21): Also include fields, include multiple and not required
141    pub fn list_types(&self, node: &tree_sitter::Node) -> Vec<String> {
142        let mut kinds = Vec::new();
143        if let Some(children) = self.children.get(node.kind()) {
144            if children.multiple && !children.required {
145                for child in &children.types {
146                    kinds.push(child.ty.clone());
147                }
148            }
149        }
150        kinds
151    }
152
153    pub fn subtypes(&self, kind: &String) -> &[String] {
154        self.subtypes.get(kind).expect("Invalid node kind")
155    }
156}