Skip to content

Commit 3a045ef

Browse files
authored
Autogenerate QLDoc for TreeSitter.qll
1 parent e57f9e9 commit 3a045ef

3 files changed

Lines changed: 414 additions & 2 deletions

File tree

generator/src/ql.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ impl<'a> fmt::Display for TopLevel<'a> {
1717

1818
#[derive(Clone, Eq, PartialEq, Hash)]
1919
pub struct Class<'a> {
20+
pub qldoc: Option<String>,
2021
pub name: &'a str,
2122
pub is_abstract: bool,
2223
pub supertypes: BTreeSet<Type<'a>>,
@@ -26,6 +27,9 @@ pub struct Class<'a> {
2627

2728
impl<'a> fmt::Display for Class<'a> {
2829
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30+
if let Some(qldoc) = &self.qldoc {
31+
write!(f, "/** {} */", qldoc)?;
32+
}
2933
if self.is_abstract {
3034
write!(f, "abstract ")?;
3135
}
@@ -43,6 +47,7 @@ impl<'a> fmt::Display for Class<'a> {
4347
f,
4448
" {}\n",
4549
Predicate {
50+
qldoc: None,
4651
name: self.name.clone(),
4752
overridden: false,
4853
return_type: None,
@@ -176,6 +181,7 @@ impl<'a> fmt::Display for Expression<'a> {
176181

177182
#[derive(Clone, Eq, PartialEq, Hash)]
178183
pub struct Predicate<'a> {
184+
pub qldoc: Option<String>,
179185
pub name: &'a str,
180186
pub overridden: bool,
181187
pub return_type: Option<Type<'a>>,
@@ -185,6 +191,9 @@ pub struct Predicate<'a> {
185191

186192
impl<'a> fmt::Display for Predicate<'a> {
187193
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
194+
if let Some(qldoc) = &self.qldoc {
195+
write!(f, "/** {} */", qldoc)?;
196+
}
188197
if self.overridden {
189198
write!(f, "override ")?;
190199
}

generator/src/ql_gen.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub fn write(language: &Language, classes: &[ql::TopLevel]) -> std::io::Result<(
2929
fn create_ast_node_class<'a>() -> ql::Class<'a> {
3030
// Default implementation of `toString` calls `this.getAPrimaryQlClass()`
3131
let to_string = ql::Predicate {
32+
qldoc: Some(String::from("Gets a string representation of this element.")),
3233
name: "toString",
3334
overridden: false,
3435
return_type: Some(ql::Type::String),
@@ -43,10 +44,11 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> {
4344
),
4445
};
4546
let get_location =
46-
create_none_predicate("getLocation", false, Some(ql::Type::Normal("Location")));
47+
create_none_predicate(Some(String::from("Gets the location of this element.")), "getLocation", false, Some(ql::Type::Normal("Location")));
4748
let get_a_field_or_child =
48-
create_none_predicate("getAFieldOrChild", false, Some(ql::Type::Normal("AstNode")));
49+
create_none_predicate(Some(String::from("Gets a field or child node of this node.")),"getAFieldOrChild", false, Some(ql::Type::Normal("AstNode")));
4950
let get_parent = ql::Predicate {
51+
qldoc: Some(String::from("Gets the parent of this element.")),
5052
name: "getParent",
5153
overridden: false,
5254
return_type: Some(ql::Type::Normal("AstNode")),
@@ -61,6 +63,7 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> {
6163
),
6264
};
6365
let get_parent_index = ql::Predicate {
66+
qldoc: Some(String::from("Gets the index of this node among the children of its parent.")),
6467
name: "getParentIndex",
6568
overridden: false,
6669
return_type: Some(ql::Type::Int),
@@ -75,6 +78,7 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> {
7578
),
7679
};
7780
let get_a_primary_ql_class = ql::Predicate {
81+
qldoc: Some(String::from("Gets the name of the primary QL class for this element.")),
7882
name: "getAPrimaryQlClass",
7983
overridden: false,
8084
return_type: Some(ql::Type::String),
@@ -85,6 +89,7 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> {
8589
),
8690
};
8791
ql::Class {
92+
qldoc: Some(String::from("The base class for all AST nodes")),
8893
name: "AstNode",
8994
is_abstract: false,
9095
supertypes: vec![ql::Type::AtType("ast_node")].into_iter().collect(),
@@ -103,20 +108,23 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> {
103108
fn create_token_class<'a>() -> ql::Class<'a> {
104109
let tokeninfo_arity = 6;
105110
let get_value = ql::Predicate {
111+
qldoc: Some(String::from("Gets the value of this token.")),
106112
name: "getValue",
107113
overridden: false,
108114
return_type: Some(ql::Type::String),
109115
formal_parameters: vec![],
110116
body: create_get_field_expr_for_column_storage("result", "tokeninfo", 3, tokeninfo_arity),
111117
};
112118
let get_location = ql::Predicate {
119+
qldoc: Some(String::from("Gets the location of this token.")),
113120
name: "getLocation",
114121
overridden: true,
115122
return_type: Some(ql::Type::Normal("Location")),
116123
formal_parameters: vec![],
117124
body: create_get_field_expr_for_column_storage("result", "tokeninfo", 4, tokeninfo_arity),
118125
};
119126
let to_string = ql::Predicate {
127+
qldoc: Some(String::from("Gets a string representation of this element.")),
120128
name: "toString",
121129
overridden: true,
122130
return_type: Some(ql::Type::String),
@@ -127,6 +135,7 @@ fn create_token_class<'a>() -> ql::Class<'a> {
127135
),
128136
};
129137
ql::Class {
138+
qldoc: Some(String::from("A token.")),
130139
name: "Token",
131140
is_abstract: false,
132141
supertypes: vec![ql::Type::AtType("token"), ql::Type::Normal("AstNode")]
@@ -148,6 +157,7 @@ fn create_reserved_word_class<'a>() -> ql::Class<'a> {
148157
let class_name = "ReservedWord";
149158
let get_a_primary_ql_class = create_get_a_primary_ql_class(&class_name);
150159
ql::Class {
160+
qldoc: Some(String::from("A reserved word.")),
151161
name: class_name,
152162
is_abstract: false,
153163
supertypes: vec![ql::Type::AtType(db_name), ql::Type::Normal("Token")]
@@ -160,11 +170,13 @@ fn create_reserved_word_class<'a>() -> ql::Class<'a> {
160170

161171
/// Creates a predicate whose body is `none()`.
162172
fn create_none_predicate<'a>(
173+
qldoc: Option<String>,
163174
name: &'a str,
164175
overridden: bool,
165176
return_type: Option<ql::Type<'a>>,
166177
) -> ql::Predicate<'a> {
167178
ql::Predicate {
179+
qldoc: qldoc,
168180
name: name,
169181
overridden,
170182
return_type,
@@ -177,6 +189,7 @@ fn create_none_predicate<'a>(
177189
/// name.
178190
fn create_get_a_primary_ql_class<'a>(class_name: &'a str) -> ql::Predicate<'a> {
179191
ql::Predicate {
192+
qldoc: Some(String::from("Gets the name of the primary QL class for this element.")),
180193
name: "getAPrimaryQlClass",
181194
overridden: true,
182195
return_type: Some(ql::Type::String),
@@ -196,6 +209,7 @@ fn create_get_a_primary_ql_class<'a>(class_name: &'a str) -> ql::Predicate<'a> {
196209
/// `arity` - the total number of columns in the table
197210
fn create_get_location_predicate<'a>(def_table: &'a str, arity: usize) -> ql::Predicate<'a> {
198211
ql::Predicate {
212+
qldoc: Some(String::from("Gets the location of this element.")),
199213
name: "getLocation",
200214
overridden: true,
201215
return_type: Some(ql::Type::Normal("Location")),
@@ -220,6 +234,7 @@ fn create_get_location_predicate<'a>(def_table: &'a str, arity: usize) -> ql::Pr
220234
/// `def_table` - the name of the table that defines the entity and its text.
221235
fn create_get_text_predicate<'a>(def_table: &'a str) -> ql::Predicate<'a> {
222236
ql::Predicate {
237+
qldoc: Some(String::from("Gets the text content of this element.")),
223238
name: "getText",
224239
overridden: false,
225240
return_type: Some(ql::Type::String),
@@ -419,6 +434,7 @@ fn create_field_getters<'a>(
419434
};
420435
(
421436
ql::Predicate {
437+
qldoc: field.name.as_ref().map(|name| format!("Gets the node corresponding to the field `{}`.", name)),
422438
name: &field.getter_name,
423439
overridden: false,
424440
return_type,
@@ -456,6 +472,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec<ql::TopLevel
456472
supertypes.insert(ql::Type::AtType(&node.dbscheme_name));
457473
supertypes.insert(ql::Type::Normal("Token"));
458474
classes.push(ql::TopLevel::Class(ql::Class {
475+
qldoc: Some(format!("A class representing `{}` tokens.", type_name.kind)),
459476
name: &node.ql_class_name,
460477
is_abstract: false,
461478
supertypes,
@@ -468,6 +485,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec<ql::TopLevel
468485
// It's a tree-sitter supertype node, so we're wrapping a dbscheme
469486
// union type.
470487
classes.push(ql::TopLevel::Class(ql::Class {
488+
qldoc: None,
471489
name: &node.ql_class_name,
472490
is_abstract: false,
473491
supertypes: vec![
@@ -501,6 +519,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec<ql::TopLevel
501519

502520
let main_class_name = &node.ql_class_name;
503521
let mut main_class = ql::Class {
522+
qldoc: Some(format!("A class representing `{}` nodes.", type_name.kind)),
504523
name: &main_class_name,
505524
is_abstract: false,
506525
supertypes: vec![
@@ -543,6 +562,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec<ql::TopLevel
543562
}
544563

545564
main_class.predicates.push(ql::Predicate {
565+
qldoc: Some(String::from("Gets a field or child node of this node.")),
546566
name: "getAFieldOrChild",
547567
overridden: true,
548568
return_type: Some(ql::Type::Normal("AstNode")),

0 commit comments

Comments
 (0)