mirror of
https://github.com/github/codeql.git
synced 2026-02-20 00:43:44 +01:00
Merge pull request #71 from github/kinds
Create disjoint db types for different operators
This commit is contained in:
@@ -246,6 +246,12 @@ fn full_id_for_folder(path: &Path) -> String {
|
||||
format!("{};folder", normalize_path(path))
|
||||
}
|
||||
|
||||
struct ChildNode {
|
||||
field_name: Option<&'static str>,
|
||||
label: Label,
|
||||
type_name: TypeName,
|
||||
}
|
||||
|
||||
struct Visitor<'a> {
|
||||
/// The file path of the source code (as string)
|
||||
path: String,
|
||||
@@ -262,13 +268,13 @@ struct Visitor<'a> {
|
||||
toplevel_child_counter: usize,
|
||||
/// A lookup table from type name to node types
|
||||
schema: &'a NodeTypeMap,
|
||||
/// A stack for gathering information from child nodes. Whenever a node is entered
|
||||
/// the parent's [Label], child counter, and an empty list is pushed. All children append their data
|
||||
/// (field name, label, type) to the the list. When the visitor leaves a node the list
|
||||
/// containing the child data is popped from the stack and matched against the dbscheme
|
||||
/// for the node. If the expectations are met the corresponding row definitions are
|
||||
/// added to the trap_output.
|
||||
stack: Vec<(Label, usize, Vec<(Option<&'static str>, Label, TypeName)>)>,
|
||||
/// A stack for gathering information from child nodes. Whenever a node is
|
||||
/// entered the parent's [Label], child counter, and an empty list is pushed.
|
||||
/// All children append their data to the the list. When the visitor leaves a
|
||||
/// node the list containing the child data is popped from the stack and
|
||||
/// matched against the dbscheme for the node. If the expectations are met
|
||||
/// the corresponding row definitions are added to the trap_output.
|
||||
stack: Vec<(Label, usize, Vec<ChildNode>)>,
|
||||
}
|
||||
|
||||
impl Visitor<'_> {
|
||||
@@ -349,7 +355,7 @@ impl Visitor<'_> {
|
||||
fields,
|
||||
name: table_name,
|
||||
} => {
|
||||
if let Some(args) = self.complex_node(&node, fields, child_nodes, id) {
|
||||
if let Some(args) = self.complex_node(&node, fields, &child_nodes, id) {
|
||||
let mut all_args = Vec::new();
|
||||
all_args.push(Arg::Label(id));
|
||||
all_args.push(Arg::Label(parent_id));
|
||||
@@ -373,14 +379,14 @@ impl Visitor<'_> {
|
||||
// Extra nodes are independent root nodes and do not belong to the parent node
|
||||
// Therefore we should not register them in the parent vector
|
||||
if let Some(parent) = self.stack.last_mut() {
|
||||
parent.2.push((
|
||||
parent.2.push(ChildNode {
|
||||
field_name,
|
||||
id,
|
||||
TypeName {
|
||||
label: id,
|
||||
type_name: TypeName {
|
||||
kind: node.kind().to_owned(),
|
||||
named: node.is_named(),
|
||||
},
|
||||
))
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -389,38 +395,47 @@ impl Visitor<'_> {
|
||||
&mut self,
|
||||
node: &Node,
|
||||
fields: &Vec<Field>,
|
||||
child_nodes: Vec<(Option<&str>, Label, TypeName)>,
|
||||
child_nodes: &Vec<ChildNode>,
|
||||
parent_id: Label,
|
||||
) -> Option<Vec<Arg>> {
|
||||
let mut map: Map<&Option<String>, (&Field, Vec<Label>)> = std::collections::BTreeMap::new();
|
||||
let mut map: Map<&Option<String>, (&Field, Vec<Arg>)> = Map::new();
|
||||
for field in fields {
|
||||
map.insert(&field.name, (field, Vec::new()));
|
||||
}
|
||||
for (child_field, child_id, child_type) in child_nodes {
|
||||
if let Some((field, values)) = map.get_mut(&child_field.map(|x| x.to_owned())) {
|
||||
for child_node in child_nodes {
|
||||
if let Some((field, values)) = map.get_mut(&child_node.field_name.map(|x| x.to_owned()))
|
||||
{
|
||||
//TODO: handle error and missing nodes
|
||||
if self.type_matches(&child_type, &field.type_info) {
|
||||
values.push(child_id);
|
||||
if self.type_matches(&child_node.type_name, &field.type_info) {
|
||||
if let node_types::FieldTypeInfo::ReservedWordInt(int_mapping) =
|
||||
&field.type_info
|
||||
{
|
||||
// We can safely unwrap because type_matches checks the key is in the map.
|
||||
let (int_value, _) = int_mapping.get(&child_node.type_name.kind).unwrap();
|
||||
values.push(Arg::Int(*int_value));
|
||||
} else {
|
||||
values.push(Arg::Label(child_node.label));
|
||||
}
|
||||
} else if field.name.is_some() {
|
||||
error!(
|
||||
"{}:{}: type mismatch for field {}::{} with type {:?} != {:?}",
|
||||
&self.path,
|
||||
node.start_position().row + 1,
|
||||
node.kind(),
|
||||
child_field.unwrap_or("child"),
|
||||
child_type,
|
||||
child_node.field_name.unwrap_or("child"),
|
||||
child_node.type_name,
|
||||
field.type_info
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if child_field.is_some() || child_type.named {
|
||||
if child_node.field_name.is_some() || child_node.type_name.named {
|
||||
error!(
|
||||
"{}:{}: value for unknown field: {}::{} and type {:?}",
|
||||
&self.path,
|
||||
node.start_position().row + 1,
|
||||
node.kind(),
|
||||
&child_field.unwrap_or("child"),
|
||||
&child_type
|
||||
&child_node.field_name.unwrap_or("child"),
|
||||
&child_node.type_name
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -428,18 +443,18 @@ impl Visitor<'_> {
|
||||
let mut args = Vec::new();
|
||||
let mut is_valid = true;
|
||||
for field in fields {
|
||||
let child_ids = &map.get(&field.name).unwrap().1;
|
||||
let child_values = &map.get(&field.name).unwrap().1;
|
||||
match &field.storage {
|
||||
Storage::Column { name: column_name } => {
|
||||
if child_ids.len() == 1 {
|
||||
args.push(Arg::Label(*child_ids.first().unwrap()));
|
||||
if child_values.len() == 1 {
|
||||
args.push(child_values.first().unwrap().clone());
|
||||
} else {
|
||||
is_valid = false;
|
||||
error!(
|
||||
"{}:{}: {} for field: {}::{}",
|
||||
&self.path,
|
||||
node.start_position().row + 1,
|
||||
if child_ids.is_empty() {
|
||||
if child_values.is_empty() {
|
||||
"missing value"
|
||||
} else {
|
||||
"too many values"
|
||||
@@ -453,7 +468,7 @@ impl Visitor<'_> {
|
||||
name: table_name,
|
||||
has_index,
|
||||
} => {
|
||||
for (index, child_id) in child_ids.iter().enumerate() {
|
||||
for (index, child_value) in child_values.iter().enumerate() {
|
||||
if !*has_index && index > 0 {
|
||||
error!(
|
||||
"{}:{}: too many values for field: {}::{}",
|
||||
@@ -469,7 +484,7 @@ impl Visitor<'_> {
|
||||
if *has_index {
|
||||
args.push(Arg::Int(index))
|
||||
}
|
||||
args.push(Arg::Label(*child_id));
|
||||
args.push(child_value.clone());
|
||||
self.trap_writer.add_tuple(&table_name, args);
|
||||
}
|
||||
}
|
||||
@@ -500,6 +515,10 @@ impl Visitor<'_> {
|
||||
node_types::FieldTypeInfo::Multiple { types, .. } => {
|
||||
return self.type_matches_set(tp, types);
|
||||
}
|
||||
|
||||
node_types::FieldTypeInfo::ReservedWordInt(int_mapping) => {
|
||||
return !tp.named && int_mapping.contains_key(&tp.kind)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
@@ -658,7 +677,7 @@ impl fmt::Display for Index {
|
||||
}
|
||||
|
||||
// Some untyped argument to a TrapEntry.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
enum Arg {
|
||||
Label(Label),
|
||||
Int(usize),
|
||||
|
||||
@@ -12,13 +12,13 @@ use std::path::PathBuf;
|
||||
use tracing::{error, info};
|
||||
|
||||
/// Given the name of the parent node, and its field information, returns a pair,
|
||||
/// the first of which is the name of the field's type. The second is an optional
|
||||
/// dbscheme entry that should be added, representing a union of all the possible
|
||||
/// types the field can take.
|
||||
/// the first of which is the field's type. The second is an optional dbscheme
|
||||
/// entry that should be added.
|
||||
fn make_field_type<'a>(
|
||||
parent_name: &'a str,
|
||||
field: &'a node_types::Field,
|
||||
nodes: &'a node_types::NodeTypeMap,
|
||||
) -> (&'a str, Option<dbscheme::Entry<'a>>) {
|
||||
) -> (ql::Type<'a>, Option<dbscheme::Entry<'a>>) {
|
||||
match &field.type_info {
|
||||
node_types::FieldTypeInfo::Multiple {
|
||||
types,
|
||||
@@ -32,14 +32,34 @@ fn make_field_type<'a>(
|
||||
.map(|t| nodes.get(t).unwrap().dbscheme_name.as_str())
|
||||
.collect();
|
||||
(
|
||||
&dbscheme_union,
|
||||
ql::Type::AtType(&dbscheme_union),
|
||||
Some(dbscheme::Entry::Union(dbscheme::Union {
|
||||
name: dbscheme_union,
|
||||
members,
|
||||
})),
|
||||
)
|
||||
}
|
||||
node_types::FieldTypeInfo::Single(t) => (&nodes.get(&t).unwrap().dbscheme_name, None),
|
||||
node_types::FieldTypeInfo::Single(t) => {
|
||||
let dbscheme_name = &nodes.get(&t).unwrap().dbscheme_name;
|
||||
(ql::Type::AtType(dbscheme_name), None)
|
||||
}
|
||||
node_types::FieldTypeInfo::ReservedWordInt(int_mapping) => {
|
||||
// The field will be an `int` in the db, and we add a case split to
|
||||
// create other db types for each integer value.
|
||||
let mut branches: Vec<(usize, &'a str)> = Vec::new();
|
||||
for (_, (value, name)) in int_mapping {
|
||||
branches.push((*value, name));
|
||||
}
|
||||
let case = dbscheme::Entry::Case(dbscheme::Case {
|
||||
name: parent_name,
|
||||
column: match &field.storage {
|
||||
node_types::Storage::Column { name } => name,
|
||||
node_types::Storage::Table { name, .. } => name,
|
||||
},
|
||||
branches,
|
||||
});
|
||||
(ql::Type::Int, Some(case))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +72,7 @@ fn add_field_for_table_storage<'a>(
|
||||
let parent_name = &nodes.get(&field.parent).unwrap().dbscheme_name;
|
||||
// This field can appear zero or multiple times, so put
|
||||
// it in an auxiliary table.
|
||||
let (field_type_name, field_type_entry) = make_field_type(&field, nodes);
|
||||
let (field_ql_type, field_type_entry) = make_field_type(parent_name, &field, nodes);
|
||||
let parent_column = dbscheme::Column {
|
||||
unique: !has_index,
|
||||
db_type: dbscheme::DbColumnType::Int,
|
||||
@@ -70,8 +90,11 @@ fn add_field_for_table_storage<'a>(
|
||||
let field_column = dbscheme::Column {
|
||||
unique: true,
|
||||
db_type: dbscheme::DbColumnType::Int,
|
||||
name: field_type_name,
|
||||
ql_type: ql::Type::AtType(field_type_name),
|
||||
name: match &field.name {
|
||||
None => "child",
|
||||
Some(name) => name,
|
||||
},
|
||||
ql_type: field_ql_type,
|
||||
ql_type_is_ref: true,
|
||||
};
|
||||
let field_table = dbscheme::Table {
|
||||
@@ -93,19 +116,20 @@ fn add_field_for_table_storage<'a>(
|
||||
}
|
||||
|
||||
fn add_field_for_column_storage<'a>(
|
||||
parent_name: &'a str,
|
||||
field: &'a node_types::Field,
|
||||
column_name: &'a str,
|
||||
nodes: &'a node_types::NodeTypeMap,
|
||||
) -> (dbscheme::Column<'a>, Option<dbscheme::Entry<'a>>) {
|
||||
// This field must appear exactly once, so we add it as
|
||||
// a column to the main table for the node type.
|
||||
let (field_type_name, field_type_entry) = make_field_type(&field, nodes);
|
||||
let (field_ql_type, field_type_entry) = make_field_type(parent_name, &field, nodes);
|
||||
(
|
||||
dbscheme::Column {
|
||||
unique: false,
|
||||
db_type: dbscheme::DbColumnType::Int,
|
||||
name: column_name,
|
||||
ql_type: ql::Type::AtType(field_type_name),
|
||||
ql_type: field_ql_type,
|
||||
ql_type_is_ref: true,
|
||||
},
|
||||
field_type_entry,
|
||||
@@ -185,9 +209,13 @@ fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec<dbscheme::Entry<
|
||||
// auxiliary tables or columns in the defining table for them.
|
||||
for field in fields {
|
||||
match &field.storage {
|
||||
node_types::Storage::Column { name } => {
|
||||
let (field_column, field_type_entry) =
|
||||
add_field_for_column_storage(field, name, nodes);
|
||||
node_types::Storage::Column { name: column_name } => {
|
||||
let (field_column, field_type_entry) = add_field_for_column_storage(
|
||||
&node.dbscheme_name,
|
||||
field,
|
||||
column_name,
|
||||
nodes,
|
||||
);
|
||||
if let Some(field_type_entry) = field_type_entry {
|
||||
entries.push(field_type_entry);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,9 @@ impl<'a> fmt::Display for Type<'a> {
|
||||
pub enum Expression<'a> {
|
||||
Var(&'a str),
|
||||
String(&'a str),
|
||||
Integer(usize),
|
||||
Pred(&'a str, Vec<Expression<'a>>),
|
||||
And(Vec<Expression<'a>>),
|
||||
Or(Vec<Expression<'a>>),
|
||||
Equals(Box<Expression<'a>>, Box<Expression<'a>>),
|
||||
Dot(Box<Expression<'a>>, &'a str, Vec<Expression<'a>>),
|
||||
@@ -110,6 +112,7 @@ impl<'a> fmt::Display for Expression<'a> {
|
||||
match self {
|
||||
Expression::Var(x) => write!(f, "{}", x),
|
||||
Expression::String(s) => write!(f, "\"{}\"", s),
|
||||
Expression::Integer(n) => write!(f, "{}", n),
|
||||
Expression::Pred(n, args) => {
|
||||
write!(f, "{}(", n)?;
|
||||
for (index, arg) in args.iter().enumerate() {
|
||||
@@ -120,6 +123,19 @@ impl<'a> fmt::Display for Expression<'a> {
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
Expression::And(conjuncts) => {
|
||||
if conjuncts.is_empty() {
|
||||
write!(f, "any()")
|
||||
} else {
|
||||
for (index, conjunct) in conjuncts.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(f, " and ")?;
|
||||
}
|
||||
write!(f, "({})", conjunct)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Expression::Or(disjuncts) => {
|
||||
if disjuncts.is_empty() {
|
||||
write!(f, "none()")
|
||||
|
||||
@@ -80,28 +80,28 @@ fn create_token_class<'a>() -> ql::Class<'a> {
|
||||
overridden: true,
|
||||
return_type: Some(ql::Type::Normal("AstNode")),
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage("tokeninfo", 0, 8),
|
||||
body: create_get_field_expr_for_column_storage("result", "tokeninfo", 0, 8),
|
||||
};
|
||||
let get_parent_index = ql::Predicate {
|
||||
name: "getParentIndex",
|
||||
overridden: true,
|
||||
return_type: Some(ql::Type::Int),
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage("tokeninfo", 1, 8),
|
||||
body: create_get_field_expr_for_column_storage("result", "tokeninfo", 1, 8),
|
||||
};
|
||||
let get_value = ql::Predicate {
|
||||
name: "getValue",
|
||||
overridden: false,
|
||||
return_type: Some(ql::Type::String),
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage("tokeninfo", 5, 8),
|
||||
body: create_get_field_expr_for_column_storage("result", "tokeninfo", 5, 8),
|
||||
};
|
||||
let get_location = ql::Predicate {
|
||||
name: "getLocation",
|
||||
overridden: true,
|
||||
return_type: Some(ql::Type::Normal("Location")),
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage("tokeninfo", 6, 8),
|
||||
body: create_get_field_expr_for_column_storage("result", "tokeninfo", 6, 8),
|
||||
};
|
||||
let to_string = ql::Predicate {
|
||||
name: "toString",
|
||||
@@ -228,10 +228,12 @@ fn create_get_text_predicate<'a>(def_table: &'a str) -> ql::Predicate<'a> {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `result_var_name` - the name of the variable to which the resulting value should be bound
|
||||
/// * `table_name` - the name of parent's defining table
|
||||
/// * `column_index` - the index in that table that defines the field
|
||||
/// * `arity` - the total number of columns in the table
|
||||
fn create_get_field_expr_for_column_storage<'a>(
|
||||
result_var_name: &'a str,
|
||||
table_name: &'a str,
|
||||
column_index: usize,
|
||||
arity: usize,
|
||||
@@ -243,7 +245,7 @@ fn create_get_field_expr_for_column_storage<'a>(
|
||||
[
|
||||
vec![ql::Expression::Var("this")],
|
||||
vec![ql::Expression::Var("_"); num_underscores_before],
|
||||
vec![ql::Expression::Var("result")],
|
||||
vec![ql::Expression::Var(result_var_name)],
|
||||
vec![ql::Expression::Var("_"); num_underscores_after],
|
||||
]
|
||||
.concat(),
|
||||
@@ -254,6 +256,7 @@ fn create_get_field_expr_for_column_storage<'a>(
|
||||
/// auxiliary table. The index name can be "_" so the expression will hold for
|
||||
/// all indices.
|
||||
fn create_get_field_expr_for_table_storage<'a>(
|
||||
result_var_name: &'a str,
|
||||
table_name: &'a str,
|
||||
index_var_name: Option<&'a str>,
|
||||
) -> ql::Expression<'a> {
|
||||
@@ -263,7 +266,7 @@ fn create_get_field_expr_for_table_storage<'a>(
|
||||
Some(index_var_name) => vec![
|
||||
ql::Expression::Var("this"),
|
||||
ql::Expression::Var(index_var_name),
|
||||
ql::Expression::Var("result"),
|
||||
ql::Expression::Var(result_var_name),
|
||||
],
|
||||
None => vec![ql::Expression::Var("this"), ql::Expression::Var("result")],
|
||||
},
|
||||
@@ -271,9 +274,9 @@ fn create_get_field_expr_for_table_storage<'a>(
|
||||
}
|
||||
|
||||
/// Creates a pair consisting of a predicate to get the given field, and an
|
||||
/// expression that will get the same field. When the field can occur multiple
|
||||
/// times, the predicate will take an index argument, while the expression will
|
||||
/// use the "don't care" expression to hold for all occurrences.
|
||||
/// optional expression that will get the same field. When the field can occur
|
||||
/// multiple times, the predicate will take an index argument, while the
|
||||
/// expression will use the "don't care" expression to hold for all occurrences.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
@@ -291,65 +294,128 @@ fn create_field_getters<'a>(
|
||||
main_table_column_index: &mut usize,
|
||||
field: &'a node_types::Field,
|
||||
nodes: &'a node_types::NodeTypeMap,
|
||||
) -> (ql::Predicate<'a>, ql::Expression<'a>) {
|
||||
let return_type = Some(ql::Type::Normal(match &field.type_info {
|
||||
node_types::FieldTypeInfo::Single(t) => &nodes.get(&t).unwrap().ql_class_name,
|
||||
) -> (ql::Predicate<'a>, Option<ql::Expression<'a>>) {
|
||||
let return_type = match &field.type_info {
|
||||
node_types::FieldTypeInfo::Single(t) => {
|
||||
Some(ql::Type::Normal(&nodes.get(&t).unwrap().ql_class_name))
|
||||
}
|
||||
node_types::FieldTypeInfo::Multiple {
|
||||
types: _,
|
||||
dbscheme_union: _,
|
||||
ql_class,
|
||||
} => &ql_class,
|
||||
}));
|
||||
match &field.storage {
|
||||
} => Some(ql::Type::Normal(&ql_class)),
|
||||
node_types::FieldTypeInfo::ReservedWordInt(_) => Some(ql::Type::String),
|
||||
};
|
||||
let formal_parameters = match &field.storage {
|
||||
node_types::Storage::Column { .. } => vec![],
|
||||
node_types::Storage::Table { has_index, .. } => {
|
||||
if *has_index {
|
||||
vec![ql::FormalParameter {
|
||||
name: "i",
|
||||
param_type: ql::Type::Int,
|
||||
}]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// For the expression to get a value, what variable name should the result
|
||||
// be bound to?
|
||||
let get_value_result_var_name = match &field.type_info {
|
||||
node_types::FieldTypeInfo::ReservedWordInt(_) => "value",
|
||||
node_types::FieldTypeInfo::Single(_) => "result",
|
||||
node_types::FieldTypeInfo::Multiple { .. } => "result",
|
||||
};
|
||||
|
||||
// Two expressions for getting the value. One that's suitable use in the
|
||||
// getter predicate (where there may be a specific index), and another for
|
||||
// use in `getAFieldOrChild` (where we use a "don't care" expression to
|
||||
// match any index).
|
||||
let (get_value, get_value_any_index) = match &field.storage {
|
||||
node_types::Storage::Column { name: _ } => {
|
||||
let result = (
|
||||
ql::Predicate {
|
||||
name: &field.getter_name,
|
||||
overridden: false,
|
||||
return_type,
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage(
|
||||
&main_table_name,
|
||||
*main_table_column_index,
|
||||
main_table_arity,
|
||||
),
|
||||
},
|
||||
let column_index = *main_table_column_index;
|
||||
*main_table_column_index += 1;
|
||||
(
|
||||
create_get_field_expr_for_column_storage(
|
||||
get_value_result_var_name,
|
||||
&main_table_name,
|
||||
*main_table_column_index,
|
||||
column_index,
|
||||
main_table_arity,
|
||||
),
|
||||
);
|
||||
*main_table_column_index += 1;
|
||||
result
|
||||
create_get_field_expr_for_column_storage(
|
||||
get_value_result_var_name,
|
||||
&main_table_name,
|
||||
column_index,
|
||||
main_table_arity,
|
||||
),
|
||||
)
|
||||
}
|
||||
node_types::Storage::Table {
|
||||
name: field_table_name,
|
||||
has_index,
|
||||
} => (
|
||||
ql::Predicate {
|
||||
name: &field.getter_name,
|
||||
overridden: false,
|
||||
return_type,
|
||||
formal_parameters: if *has_index {
|
||||
vec![ql::FormalParameter {
|
||||
name: "i",
|
||||
param_type: ql::Type::Int,
|
||||
}]
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
body: create_get_field_expr_for_table_storage(
|
||||
&field_table_name,
|
||||
if *has_index { Some("i") } else { None },
|
||||
),
|
||||
},
|
||||
create_get_field_expr_for_table_storage(
|
||||
get_value_result_var_name,
|
||||
&field_table_name,
|
||||
if *has_index { Some("i") } else { None },
|
||||
),
|
||||
create_get_field_expr_for_table_storage(
|
||||
get_value_result_var_name,
|
||||
&field_table_name,
|
||||
if *has_index { Some("_") } else { None },
|
||||
),
|
||||
),
|
||||
}
|
||||
};
|
||||
let (body, optional_expr) = match &field.type_info {
|
||||
node_types::FieldTypeInfo::ReservedWordInt(int_mapping) => {
|
||||
// Create an expression that binds the corresponding string to `result` for each `value`, e.g.:
|
||||
// result = "foo" and value = 0 or
|
||||
// result = "bar" and value = 1 or
|
||||
// result = "baz" and value = 2
|
||||
let disjuncts = int_mapping
|
||||
.iter()
|
||||
.map(|(token_str, (value, _))| {
|
||||
ql::Expression::And(vec![
|
||||
ql::Expression::Equals(
|
||||
Box::new(ql::Expression::Var("result")),
|
||||
Box::new(ql::Expression::String(token_str)),
|
||||
),
|
||||
ql::Expression::Equals(
|
||||
Box::new(ql::Expression::Var("value")),
|
||||
Box::new(ql::Expression::Integer(*value)),
|
||||
),
|
||||
])
|
||||
})
|
||||
.collect();
|
||||
(
|
||||
ql::Expression::Aggregate(
|
||||
"exists",
|
||||
vec![ql::FormalParameter {
|
||||
name: "value",
|
||||
param_type: ql::Type::Int,
|
||||
}],
|
||||
Box::new(get_value),
|
||||
Box::new(ql::Expression::Or(disjuncts)),
|
||||
),
|
||||
// Since the getter returns a string and not an AstNode, it won't be part of getAFieldOrChild:
|
||||
None,
|
||||
)
|
||||
}
|
||||
node_types::FieldTypeInfo::Single(_) | node_types::FieldTypeInfo::Multiple { .. } => {
|
||||
(get_value, Some(get_value_any_index))
|
||||
}
|
||||
};
|
||||
(
|
||||
ql::Predicate {
|
||||
name: &field.getter_name,
|
||||
overridden: false,
|
||||
return_type,
|
||||
formal_parameters,
|
||||
body,
|
||||
},
|
||||
optional_expr,
|
||||
)
|
||||
}
|
||||
|
||||
/// Converts the given node types into CodeQL classes wrapping the dbscheme.
|
||||
@@ -462,7 +528,9 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec<ql::TopLevel
|
||||
nodes,
|
||||
);
|
||||
main_class.predicates.push(get_pred);
|
||||
get_child_exprs.push(get_child_expr);
|
||||
if let Some(get_child_expr) = get_child_expr {
|
||||
get_child_exprs.push(get_child_expr)
|
||||
}
|
||||
}
|
||||
|
||||
main_class.predicates.push(ql::Predicate {
|
||||
@@ -471,6 +539,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec<ql::TopLevel
|
||||
return_type: Some(ql::Type::Normal("AstNode")),
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage(
|
||||
"result",
|
||||
&main_table_name,
|
||||
0,
|
||||
main_table_arity,
|
||||
@@ -483,6 +552,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec<ql::TopLevel
|
||||
return_type: Some(ql::Type::Int),
|
||||
formal_parameters: vec![],
|
||||
body: create_get_field_expr_for_column_storage(
|
||||
"result",
|
||||
&main_table_name,
|
||||
1,
|
||||
main_table_arity,
|
||||
|
||||
@@ -41,6 +41,10 @@ pub enum FieldTypeInfo {
|
||||
dbscheme_union: String,
|
||||
ql_class: String,
|
||||
},
|
||||
|
||||
/// The field can be one of several tokens, so the db type will be an `int`
|
||||
/// with a `case @foo.kind` for each possiblity.
|
||||
ReservedWordInt(BTreeMap<String, (usize, String)>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -74,12 +78,12 @@ pub enum Storage {
|
||||
pub fn read_node_types(node_types_path: &Path) -> std::io::Result<NodeTypeMap> {
|
||||
let file = fs::File::open(node_types_path)?;
|
||||
let node_types = serde_json::from_reader(file)?;
|
||||
Ok(convert_nodes(node_types))
|
||||
Ok(convert_nodes(&node_types))
|
||||
}
|
||||
|
||||
pub fn read_node_types_str(node_types_json: &str) -> std::io::Result<NodeTypeMap> {
|
||||
let node_types = serde_json::from_str(node_types_json)?;
|
||||
Ok(convert_nodes(node_types))
|
||||
Ok(convert_nodes(&node_types))
|
||||
}
|
||||
|
||||
fn convert_type(node_type: &NodeType) -> TypeName {
|
||||
@@ -94,9 +98,23 @@ fn convert_types(node_types: &Vec<NodeType>) -> Set<TypeName> {
|
||||
std::collections::BTreeSet::from(iter)
|
||||
}
|
||||
|
||||
pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
|
||||
pub fn convert_nodes(nodes: &Vec<NodeInfo>) -> NodeTypeMap {
|
||||
let mut entries = NodeTypeMap::new();
|
||||
let mut token_kinds = Set::new();
|
||||
|
||||
// First, find all the token kinds
|
||||
for node in nodes {
|
||||
if node.subtypes.is_none() {
|
||||
if node.fields.as_ref().map_or(0, |x| x.len()) == 0 && node.children.is_none() {
|
||||
let type_name = TypeName {
|
||||
kind: node.kind.clone(),
|
||||
named: node.named,
|
||||
};
|
||||
token_kinds.insert(type_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for node in nodes {
|
||||
let flattened_name = &node_type_name(&node.kind, node.named);
|
||||
let dbscheme_name = escape_name(&flattened_name);
|
||||
@@ -106,7 +124,7 @@ pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
|
||||
// type.
|
||||
entries.insert(
|
||||
TypeName {
|
||||
kind: node.kind,
|
||||
kind: node.kind.clone(),
|
||||
named: node.named,
|
||||
},
|
||||
Entry {
|
||||
@@ -118,15 +136,11 @@ pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
|
||||
},
|
||||
);
|
||||
} else if node.fields.as_ref().map_or(0, |x| x.len()) == 0 && node.children.is_none() {
|
||||
let type_name = TypeName {
|
||||
kind: node.kind,
|
||||
named: node.named,
|
||||
};
|
||||
token_kinds.insert(type_name);
|
||||
// Token kind, handled above.
|
||||
} else {
|
||||
// It's a product type, defined by a table.
|
||||
let type_name = TypeName {
|
||||
kind: node.kind,
|
||||
kind: node.kind.clone(),
|
||||
named: node.named,
|
||||
};
|
||||
let table_name = escape_name(&(format!("{}_def", &flattened_name)));
|
||||
@@ -141,12 +155,13 @@ pub fn convert_nodes(nodes: Vec<NodeInfo>) -> NodeTypeMap {
|
||||
Some(field_name.to_string()),
|
||||
field_info,
|
||||
&mut fields,
|
||||
&token_kinds,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(children) = &node.children {
|
||||
// Treat children as if they were a field called 'child'.
|
||||
add_field(&type_name, None, children, &mut fields);
|
||||
add_field(&type_name, None, children, &mut fields, &token_kinds);
|
||||
}
|
||||
entries.insert(
|
||||
type_name,
|
||||
@@ -188,6 +203,7 @@ fn add_field(
|
||||
field_name: Option<String>,
|
||||
field_info: &FieldInfo,
|
||||
fields: &mut Vec<Field>,
|
||||
token_kinds: &Set<TypeName>,
|
||||
) {
|
||||
let parent_flattened_name = node_type_name(&parent_type_name.kind, parent_type_name.named);
|
||||
let storage = if !field_info.multiple && field_info.required {
|
||||
@@ -209,12 +225,30 @@ fn add_field(
|
||||
name: field_table_name,
|
||||
}
|
||||
};
|
||||
let type_info = if field_info.types.len() == 1 {
|
||||
FieldTypeInfo::Single(convert_type(field_info.types.iter().next().unwrap()))
|
||||
let converted_types = convert_types(&field_info.types);
|
||||
let type_info = if field_info
|
||||
.types
|
||||
.iter()
|
||||
.all(|t| !t.named && token_kinds.contains(&convert_type(t)))
|
||||
{
|
||||
// All possible types for this field are reserved words. The db
|
||||
// representation will be an `int` with a `case @foo.field = ...` to
|
||||
// enumerate the possible values.
|
||||
let mut counter = 0;
|
||||
let mut field_token_ints: BTreeMap<String, (usize, String)> = BTreeMap::new();
|
||||
for t in converted_types {
|
||||
let dbscheme_variant_name =
|
||||
escape_name(&format!("{}_{}", parent_flattened_name, t.kind));
|
||||
field_token_ints.insert(t.kind.to_owned(), (counter, dbscheme_variant_name));
|
||||
counter += 1;
|
||||
}
|
||||
FieldTypeInfo::ReservedWordInt(field_token_ints)
|
||||
} else if field_info.types.len() == 1 {
|
||||
FieldTypeInfo::Single(converted_types.into_iter().next().unwrap())
|
||||
} else {
|
||||
// The dbscheme type for this field will be a union. In QL, it'll just be AstNode.
|
||||
FieldTypeInfo::Multiple {
|
||||
types: convert_types(&field_info.types),
|
||||
types: converted_types,
|
||||
dbscheme_union: format!(
|
||||
"{}_{}_type",
|
||||
&parent_flattened_name,
|
||||
|
||||
@@ -178,7 +178,59 @@ module Generated {
|
||||
|
||||
AstNode getLeft() { binary_def(this, _, _, result, _, _, _) }
|
||||
|
||||
AstNode getOperator() { binary_def(this, _, _, _, result, _, _) }
|
||||
string getOperator() {
|
||||
exists(int value | binary_def(this, _, _, _, value, _, _) |
|
||||
result = "!=" and value = 0
|
||||
or
|
||||
result = "!~" and value = 1
|
||||
or
|
||||
result = "%" and value = 2
|
||||
or
|
||||
result = "&" and value = 3
|
||||
or
|
||||
result = "&&" and value = 4
|
||||
or
|
||||
result = "*" and value = 5
|
||||
or
|
||||
result = "**" and value = 6
|
||||
or
|
||||
result = "+" and value = 7
|
||||
or
|
||||
result = "-" and value = 8
|
||||
or
|
||||
result = "/" and value = 9
|
||||
or
|
||||
result = "<" and value = 10
|
||||
or
|
||||
result = "<<" and value = 11
|
||||
or
|
||||
result = "<=" and value = 12
|
||||
or
|
||||
result = "<=>" and value = 13
|
||||
or
|
||||
result = "==" and value = 14
|
||||
or
|
||||
result = "===" and value = 15
|
||||
or
|
||||
result = "=~" and value = 16
|
||||
or
|
||||
result = ">" and value = 17
|
||||
or
|
||||
result = ">=" and value = 18
|
||||
or
|
||||
result = ">>" and value = 19
|
||||
or
|
||||
result = "^" and value = 20
|
||||
or
|
||||
result = "and" and value = 21
|
||||
or
|
||||
result = "or" and value = 22
|
||||
or
|
||||
result = "|" and value = 23
|
||||
or
|
||||
result = "||" and value = 24
|
||||
)
|
||||
}
|
||||
|
||||
AstNode getRight() { binary_def(this, _, _, _, _, result, _) }
|
||||
|
||||
@@ -187,9 +239,7 @@ module Generated {
|
||||
override int getParentIndex() { binary_def(this, _, result, _, _, _, _) }
|
||||
|
||||
override AstNode getAFieldOrChild() {
|
||||
binary_def(this, _, _, result, _, _, _) or
|
||||
binary_def(this, _, _, _, result, _, _) or
|
||||
binary_def(this, _, _, _, _, result, _)
|
||||
binary_def(this, _, _, result, _, _, _) or binary_def(this, _, _, _, _, result, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,7 +937,35 @@ module Generated {
|
||||
|
||||
UnderscoreLhs getLeft() { operator_assignment_def(this, _, _, result, _, _, _) }
|
||||
|
||||
AstNode getOperator() { operator_assignment_def(this, _, _, _, result, _, _) }
|
||||
string getOperator() {
|
||||
exists(int value | operator_assignment_def(this, _, _, _, value, _, _) |
|
||||
result = "%=" and value = 0
|
||||
or
|
||||
result = "&&=" and value = 1
|
||||
or
|
||||
result = "&=" and value = 2
|
||||
or
|
||||
result = "**=" and value = 3
|
||||
or
|
||||
result = "*=" and value = 4
|
||||
or
|
||||
result = "+=" and value = 5
|
||||
or
|
||||
result = "-=" and value = 6
|
||||
or
|
||||
result = "/=" and value = 7
|
||||
or
|
||||
result = "<<=" and value = 8
|
||||
or
|
||||
result = ">>=" and value = 9
|
||||
or
|
||||
result = "^=" and value = 10
|
||||
or
|
||||
result = "|=" and value = 11
|
||||
or
|
||||
result = "||=" and value = 12
|
||||
)
|
||||
}
|
||||
|
||||
AstNode getRight() { operator_assignment_def(this, _, _, _, _, result, _) }
|
||||
|
||||
@@ -897,7 +975,6 @@ module Generated {
|
||||
|
||||
override AstNode getAFieldOrChild() {
|
||||
operator_assignment_def(this, _, _, result, _, _, _) or
|
||||
operator_assignment_def(this, _, _, _, result, _, _) or
|
||||
operator_assignment_def(this, _, _, _, _, result, _)
|
||||
}
|
||||
}
|
||||
@@ -1355,15 +1432,27 @@ module Generated {
|
||||
|
||||
AstNode getOperand() { unary_def(this, _, _, result, _, _) }
|
||||
|
||||
AstNode getOperator() { unary_def(this, _, _, _, result, _) }
|
||||
string getOperator() {
|
||||
exists(int value | unary_def(this, _, _, _, value, _) |
|
||||
result = "!" and value = 0
|
||||
or
|
||||
result = "+" and value = 1
|
||||
or
|
||||
result = "-" and value = 2
|
||||
or
|
||||
result = "defined?" and value = 3
|
||||
or
|
||||
result = "not" and value = 4
|
||||
or
|
||||
result = "~" and value = 5
|
||||
)
|
||||
}
|
||||
|
||||
override AstNode getParent() { unary_def(this, result, _, _, _, _) }
|
||||
|
||||
override int getParentIndex() { unary_def(this, _, result, _, _, _) }
|
||||
|
||||
override AstNode getAFieldOrChild() {
|
||||
unary_def(this, _, _, result, _, _) or unary_def(this, _, _, _, result, _)
|
||||
}
|
||||
override AstNode getAFieldOrChild() { unary_def(this, _, _, result, _, _) }
|
||||
}
|
||||
|
||||
class Undef extends @undef, AstNode {
|
||||
|
||||
@@ -74,7 +74,7 @@ alias_def(
|
||||
argument_list_child(
|
||||
int argument_list: @argument_list ref,
|
||||
int index: int ref,
|
||||
unique int argument_list_child_type: @argument_list_child_type ref
|
||||
unique int child: @argument_list_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -91,7 +91,7 @@ argument_list_def(
|
||||
array_child(
|
||||
int array: @array ref,
|
||||
int index: int ref,
|
||||
unique int array_child_type: @array_child_type ref
|
||||
unique int child: @array_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -122,7 +122,7 @@ assignment_def(
|
||||
bare_string_child(
|
||||
int bare_string: @bare_string ref,
|
||||
int index: int ref,
|
||||
unique int bare_string_child_type: @bare_string_child_type ref
|
||||
unique int child: @bare_string_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -139,7 +139,7 @@ bare_string_def(
|
||||
bare_symbol_child(
|
||||
int bare_symbol: @bare_symbol ref,
|
||||
int index: int ref,
|
||||
unique int bare_symbol_child_type: @bare_symbol_child_type ref
|
||||
unique int child: @bare_symbol_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -156,7 +156,7 @@ bare_symbol_def(
|
||||
begin_child(
|
||||
int begin: @begin ref,
|
||||
int index: int ref,
|
||||
unique int begin_child_type: @begin_child_type ref
|
||||
unique int child: @begin_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -173,7 +173,7 @@ begin_def(
|
||||
begin_block_child(
|
||||
int begin_block: @begin_block ref,
|
||||
int index: int ref,
|
||||
unique int begin_block_child_type: @begin_block_child_type ref
|
||||
unique int child: @begin_block_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -186,7 +186,34 @@ begin_block_def(
|
||||
|
||||
@binary_left_type = @break | @call | @next | @return | @underscore_arg | @yield
|
||||
|
||||
@binary_operator_type = @reserved_word
|
||||
case @binary.operator of
|
||||
0 = @binary_bangequal
|
||||
| 1 = @binary_bangtilde
|
||||
| 2 = @binary_percent
|
||||
| 3 = @binary_ampersand
|
||||
| 4 = @binary_ampersandampersand
|
||||
| 5 = @binary_star
|
||||
| 6 = @binary_starstar
|
||||
| 7 = @binary_plus
|
||||
| 8 = @binary_minus
|
||||
| 9 = @binary_slash
|
||||
| 10 = @binary_langle
|
||||
| 11 = @binary_langlelangle
|
||||
| 12 = @binary_langleequal
|
||||
| 13 = @binary_langleequalrangle
|
||||
| 14 = @binary_equalequal
|
||||
| 15 = @binary_equalequalequal
|
||||
| 16 = @binary_equaltilde
|
||||
| 17 = @binary_rangle
|
||||
| 18 = @binary_rangleequal
|
||||
| 19 = @binary_ranglerangle
|
||||
| 20 = @binary_caret
|
||||
| 21 = @binary_and
|
||||
| 22 = @binary_or
|
||||
| 23 = @binary_pipe
|
||||
| 24 = @binary_pipepipe
|
||||
;
|
||||
|
||||
|
||||
@binary_right_type = @break | @call | @next | @return | @underscore_arg | @yield
|
||||
|
||||
@@ -196,14 +223,14 @@ binary_def(
|
||||
int parent: @ast_node_parent ref,
|
||||
int parent_index: int ref,
|
||||
int left: @binary_left_type ref,
|
||||
int operator: @binary_operator_type ref,
|
||||
int operator: int ref,
|
||||
int right: @binary_right_type ref,
|
||||
int loc: @location ref
|
||||
);
|
||||
|
||||
block_parameters(
|
||||
unique int block: @block ref,
|
||||
unique int block_parameters: @block_parameters ref
|
||||
unique int parameters: @block_parameters ref
|
||||
);
|
||||
|
||||
@block_child_type = @token_empty_statement | @underscore_statement
|
||||
@@ -212,7 +239,7 @@ block_parameters(
|
||||
block_child(
|
||||
int block: @block ref,
|
||||
int index: int ref,
|
||||
unique int block_child_type: @block_child_type ref
|
||||
unique int child: @block_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -247,7 +274,7 @@ block_parameter_def(
|
||||
block_parameters_child(
|
||||
int block_parameters: @block_parameters ref,
|
||||
int index: int ref,
|
||||
unique int block_parameters_child_type: @block_parameters_child_type ref
|
||||
unique int child: @block_parameters_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -260,7 +287,7 @@ block_parameters_def(
|
||||
|
||||
break_child(
|
||||
unique int break: @break ref,
|
||||
unique int argument_list: @argument_list ref
|
||||
unique int child: @argument_list ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -273,14 +300,14 @@ break_def(
|
||||
|
||||
call_arguments(
|
||||
unique int call: @call ref,
|
||||
unique int argument_list: @argument_list ref
|
||||
unique int arguments: @argument_list ref
|
||||
);
|
||||
|
||||
@call_block_type = @block | @do_block
|
||||
|
||||
call_block(
|
||||
unique int call: @call ref,
|
||||
unique int call_block_type: @call_block_type ref
|
||||
unique int block: @call_block_type ref
|
||||
);
|
||||
|
||||
@call_method_type = @argument_list | @scope_resolution | @token_operator | @underscore_variable
|
||||
@@ -289,7 +316,7 @@ call_block(
|
||||
|
||||
call_receiver(
|
||||
unique int call: @call ref,
|
||||
unique int call_receiver_type: @call_receiver_type ref
|
||||
unique int receiver: @call_receiver_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -303,7 +330,7 @@ call_def(
|
||||
|
||||
case_value(
|
||||
unique int case__: @case__ ref,
|
||||
unique int underscore_statement: @underscore_statement ref
|
||||
unique int value: @underscore_statement ref
|
||||
);
|
||||
|
||||
@case_child_type = @else | @when
|
||||
@@ -312,7 +339,7 @@ case_value(
|
||||
case_child(
|
||||
int case__: @case__ ref,
|
||||
int index: int ref,
|
||||
unique int case_child_type: @case_child_type ref
|
||||
unique int child: @case_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -327,7 +354,7 @@ case_def(
|
||||
chained_string_child(
|
||||
int chained_string: @chained_string ref,
|
||||
int index: int ref,
|
||||
unique int string__: @string__ ref
|
||||
unique int child: @string__ ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -346,7 +373,7 @@ chained_string_def(
|
||||
class_child(
|
||||
int class: @class ref,
|
||||
int index: int ref,
|
||||
unique int class_child_type: @class_child_type ref
|
||||
unique int child: @class_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -375,7 +402,7 @@ conditional_def(
|
||||
destructured_left_assignment_child(
|
||||
int destructured_left_assignment: @destructured_left_assignment ref,
|
||||
int index: int ref,
|
||||
unique int destructured_left_assignment_child_type: @destructured_left_assignment_child_type ref
|
||||
unique int child: @destructured_left_assignment_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -392,7 +419,7 @@ destructured_left_assignment_def(
|
||||
destructured_parameter_child(
|
||||
int destructured_parameter: @destructured_parameter ref,
|
||||
int index: int ref,
|
||||
unique int destructured_parameter_child_type: @destructured_parameter_child_type ref
|
||||
unique int child: @destructured_parameter_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -409,7 +436,7 @@ destructured_parameter_def(
|
||||
do_child(
|
||||
int do: @do ref,
|
||||
int index: int ref,
|
||||
unique int do_child_type: @do_child_type ref
|
||||
unique int child: @do_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -422,7 +449,7 @@ do_def(
|
||||
|
||||
do_block_parameters(
|
||||
unique int do_block: @do_block ref,
|
||||
unique int block_parameters: @block_parameters ref
|
||||
unique int parameters: @block_parameters ref
|
||||
);
|
||||
|
||||
@do_block_child_type = @else | @ensure | @rescue | @token_empty_statement | @underscore_statement
|
||||
@@ -431,7 +458,7 @@ do_block_parameters(
|
||||
do_block_child(
|
||||
int do_block: @do_block ref,
|
||||
int index: int ref,
|
||||
unique int do_block_child_type: @do_block_child_type ref
|
||||
unique int child: @do_block_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -448,7 +475,7 @@ do_block_def(
|
||||
element_reference_child(
|
||||
int element_reference: @element_reference ref,
|
||||
int index: int ref,
|
||||
unique int element_reference_child_type: @element_reference_child_type ref
|
||||
unique int child: @element_reference_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -466,7 +493,7 @@ element_reference_def(
|
||||
else_child(
|
||||
int else: @else ref,
|
||||
int index: int ref,
|
||||
unique int else_child_type: @else_child_type ref
|
||||
unique int child: @else_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -481,12 +508,12 @@ else_def(
|
||||
|
||||
elsif_alternative(
|
||||
unique int elsif: @elsif ref,
|
||||
unique int elsif_alternative_type: @elsif_alternative_type ref
|
||||
unique int alternative: @elsif_alternative_type ref
|
||||
);
|
||||
|
||||
elsif_consequence(
|
||||
unique int elsif: @elsif ref,
|
||||
unique int then: @then ref
|
||||
unique int consequence: @then ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -504,7 +531,7 @@ elsif_def(
|
||||
end_block_child(
|
||||
int end_block: @end_block ref,
|
||||
int index: int ref,
|
||||
unique int end_block_child_type: @end_block_child_type ref
|
||||
unique int child: @end_block_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -521,7 +548,7 @@ end_block_def(
|
||||
ensure_child(
|
||||
int ensure: @ensure ref,
|
||||
int index: int ref,
|
||||
unique int ensure_child_type: @ensure_child_type ref
|
||||
unique int child: @ensure_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -547,7 +574,7 @@ exception_variable_def(
|
||||
exceptions_child(
|
||||
int exceptions: @exceptions ref,
|
||||
int index: int ref,
|
||||
unique int exceptions_child_type: @exceptions_child_type ref
|
||||
unique int child: @exceptions_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -564,7 +591,7 @@ exceptions_def(
|
||||
for_pattern(
|
||||
int for: @for ref,
|
||||
int index: int ref,
|
||||
unique int for_pattern_type: @for_pattern_type ref
|
||||
unique int pattern: @for_pattern_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -583,7 +610,7 @@ for_def(
|
||||
hash_child(
|
||||
int hash: @hash ref,
|
||||
int index: int ref,
|
||||
unique int hash_child_type: @hash_child_type ref
|
||||
unique int child: @hash_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -605,7 +632,7 @@ hash_splat_argument_def(
|
||||
|
||||
hash_splat_parameter_name(
|
||||
unique int hash_splat_parameter: @hash_splat_parameter ref,
|
||||
unique int token_identifier: @token_identifier ref
|
||||
unique int name: @token_identifier ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -622,7 +649,7 @@ hash_splat_parameter_def(
|
||||
heredoc_body_child(
|
||||
int heredoc_body: @heredoc_body ref,
|
||||
int index: int ref,
|
||||
unique int heredoc_body_child_type: @heredoc_body_child_type ref
|
||||
unique int child: @heredoc_body_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -637,12 +664,12 @@ heredoc_body_def(
|
||||
|
||||
if_alternative(
|
||||
unique int if: @if ref,
|
||||
unique int if_alternative_type: @if_alternative_type ref
|
||||
unique int alternative: @if_alternative_type ref
|
||||
);
|
||||
|
||||
if_consequence(
|
||||
unique int if: @if ref,
|
||||
unique int then: @then ref
|
||||
unique int consequence: @then ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -686,7 +713,7 @@ interpolation_def(
|
||||
|
||||
keyword_parameter_value(
|
||||
unique int keyword_parameter: @keyword_parameter ref,
|
||||
unique int underscore_arg: @underscore_arg ref
|
||||
unique int value: @underscore_arg ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -702,7 +729,7 @@ keyword_parameter_def(
|
||||
|
||||
lambda_parameters(
|
||||
unique int lambda: @lambda ref,
|
||||
unique int lambda_parameters: @lambda_parameters ref
|
||||
unique int parameters: @lambda_parameters ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -720,7 +747,7 @@ lambda_def(
|
||||
lambda_parameters_child(
|
||||
int lambda_parameters: @lambda_parameters ref,
|
||||
int index: int ref,
|
||||
unique int lambda_parameters_child_type: @lambda_parameters_child_type ref
|
||||
unique int child: @lambda_parameters_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -737,7 +764,7 @@ lambda_parameters_def(
|
||||
left_assignment_list_child(
|
||||
int left_assignment_list: @left_assignment_list ref,
|
||||
int index: int ref,
|
||||
unique int left_assignment_list_child_type: @left_assignment_list_child_type ref
|
||||
unique int child: @left_assignment_list_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -750,7 +777,7 @@ left_assignment_list_def(
|
||||
|
||||
method_parameters(
|
||||
unique int method: @method ref,
|
||||
unique int method_parameters: @method_parameters ref
|
||||
unique int parameters: @method_parameters ref
|
||||
);
|
||||
|
||||
@method_child_type = @else | @ensure | @rescue | @token_empty_statement | @underscore_statement
|
||||
@@ -759,7 +786,7 @@ method_parameters(
|
||||
method_child(
|
||||
int method: @method ref,
|
||||
int index: int ref,
|
||||
unique int method_child_type: @method_child_type ref
|
||||
unique int child: @method_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -777,7 +804,7 @@ method_def(
|
||||
method_parameters_child(
|
||||
int method_parameters: @method_parameters ref,
|
||||
int index: int ref,
|
||||
unique int method_parameters_child_type: @method_parameters_child_type ref
|
||||
unique int child: @method_parameters_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -796,7 +823,7 @@ method_parameters_def(
|
||||
module_child(
|
||||
int module: @module ref,
|
||||
int index: int ref,
|
||||
unique int module_child_type: @module_child_type ref
|
||||
unique int child: @module_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -810,7 +837,7 @@ module_def(
|
||||
|
||||
next_child(
|
||||
unique int next: @next ref,
|
||||
unique int argument_list: @argument_list ref
|
||||
unique int child: @argument_list ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -821,7 +848,22 @@ next_def(
|
||||
int loc: @location ref
|
||||
);
|
||||
|
||||
@operator_assignment_operator_type = @reserved_word
|
||||
case @operator_assignment.operator of
|
||||
0 = @operator_assignment_percentequal
|
||||
| 1 = @operator_assignment_ampersandampersandequal
|
||||
| 2 = @operator_assignment_ampersandequal
|
||||
| 3 = @operator_assignment_starstarequal
|
||||
| 4 = @operator_assignment_starequal
|
||||
| 5 = @operator_assignment_plusequal
|
||||
| 6 = @operator_assignment_minusequal
|
||||
| 7 = @operator_assignment_slashequal
|
||||
| 8 = @operator_assignment_langlelangleequal
|
||||
| 9 = @operator_assignment_ranglerangleequal
|
||||
| 10 = @operator_assignment_caretequal
|
||||
| 11 = @operator_assignment_pipeequal
|
||||
| 12 = @operator_assignment_pipepipeequal
|
||||
;
|
||||
|
||||
|
||||
@operator_assignment_right_type = @break | @call | @next | @return | @underscore_arg | @yield
|
||||
|
||||
@@ -831,7 +873,7 @@ operator_assignment_def(
|
||||
int parent: @ast_node_parent ref,
|
||||
int parent_index: int ref,
|
||||
int left: @underscore_lhs ref,
|
||||
int operator: @operator_assignment_operator_type ref,
|
||||
int operator: int ref,
|
||||
int right: @operator_assignment_right_type ref,
|
||||
int loc: @location ref
|
||||
);
|
||||
@@ -864,7 +906,7 @@ pair_def(
|
||||
parenthesized_statements_child(
|
||||
int parenthesized_statements: @parenthesized_statements ref,
|
||||
int index: int ref,
|
||||
unique int parenthesized_statements_child_type: @parenthesized_statements_child_type ref
|
||||
unique int child: @parenthesized_statements_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -892,7 +934,7 @@ pattern_def(
|
||||
program_child(
|
||||
int program: @program ref,
|
||||
int index: int ref,
|
||||
unique int program_child_type: @program_child_type ref
|
||||
unique int child: @program_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -907,7 +949,7 @@ program_def(
|
||||
range_child(
|
||||
int range: @range ref,
|
||||
int index: int ref,
|
||||
unique int underscore_arg: @underscore_arg ref
|
||||
unique int child: @underscore_arg ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -931,7 +973,7 @@ rational_def(
|
||||
|
||||
redo_child(
|
||||
unique int redo: @redo ref,
|
||||
unique int argument_list: @argument_list ref
|
||||
unique int child: @argument_list ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -948,7 +990,7 @@ redo_def(
|
||||
regex_child(
|
||||
int regex: @regex ref,
|
||||
int index: int ref,
|
||||
unique int regex_child_type: @regex_child_type ref
|
||||
unique int child: @regex_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -961,7 +1003,7 @@ regex_def(
|
||||
|
||||
rescue_body(
|
||||
unique int rescue: @rescue ref,
|
||||
unique int then: @then ref
|
||||
unique int body: @then ref
|
||||
);
|
||||
|
||||
rescue_exceptions(
|
||||
@@ -971,7 +1013,7 @@ rescue_exceptions(
|
||||
|
||||
rescue_variable(
|
||||
unique int rescue: @rescue ref,
|
||||
unique int exception_variable: @exception_variable ref
|
||||
unique int variable: @exception_variable ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -996,7 +1038,7 @@ rescue_modifier_def(
|
||||
|
||||
rest_assignment_child(
|
||||
unique int rest_assignment: @rest_assignment ref,
|
||||
unique int underscore_lhs: @underscore_lhs ref
|
||||
unique int child: @underscore_lhs ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1009,7 +1051,7 @@ rest_assignment_def(
|
||||
|
||||
retry_child(
|
||||
unique int retry: @retry ref,
|
||||
unique int argument_list: @argument_list ref
|
||||
unique int child: @argument_list ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1022,7 +1064,7 @@ retry_def(
|
||||
|
||||
return_child(
|
||||
unique int return: @return ref,
|
||||
unique int argument_list: @argument_list ref
|
||||
unique int child: @argument_list ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1039,7 +1081,7 @@ return_def(
|
||||
right_assignment_list_child(
|
||||
int right_assignment_list: @right_assignment_list ref,
|
||||
int index: int ref,
|
||||
unique int right_assignment_list_child_type: @right_assignment_list_child_type ref
|
||||
unique int child: @right_assignment_list_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1054,7 +1096,7 @@ right_assignment_list_def(
|
||||
|
||||
scope_resolution_scope(
|
||||
unique int scope_resolution: @scope_resolution ref,
|
||||
unique int underscore_primary: @underscore_primary ref
|
||||
unique int scope: @underscore_primary ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1081,7 +1123,7 @@ setter_def(
|
||||
singleton_class_child(
|
||||
int singleton_class: @singleton_class ref,
|
||||
int index: int ref,
|
||||
unique int singleton_class_child_type: @singleton_class_child_type ref
|
||||
unique int child: @singleton_class_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1097,7 +1139,7 @@ singleton_class_def(
|
||||
|
||||
singleton_method_parameters(
|
||||
unique int singleton_method: @singleton_method ref,
|
||||
unique int method_parameters: @method_parameters ref
|
||||
unique int parameters: @method_parameters ref
|
||||
);
|
||||
|
||||
@singleton_method_child_type = @else | @ensure | @rescue | @token_empty_statement | @underscore_statement
|
||||
@@ -1106,7 +1148,7 @@ singleton_method_parameters(
|
||||
singleton_method_child(
|
||||
int singleton_method: @singleton_method ref,
|
||||
int index: int ref,
|
||||
unique int singleton_method_child_type: @singleton_method_child_type ref
|
||||
unique int child: @singleton_method_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1130,7 +1172,7 @@ splat_argument_def(
|
||||
|
||||
splat_parameter_name(
|
||||
unique int splat_parameter: @splat_parameter ref,
|
||||
unique int token_identifier: @token_identifier ref
|
||||
unique int name: @token_identifier ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1147,7 +1189,7 @@ splat_parameter_def(
|
||||
string_child(
|
||||
int string__: @string__ ref,
|
||||
int index: int ref,
|
||||
unique int string_child_type: @string_child_type ref
|
||||
unique int child: @string_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1162,7 +1204,7 @@ string_def(
|
||||
string_array_child(
|
||||
int string_array: @string_array ref,
|
||||
int index: int ref,
|
||||
unique int bare_string: @bare_string ref
|
||||
unique int child: @bare_string ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1179,7 +1221,7 @@ string_array_def(
|
||||
subshell_child(
|
||||
int subshell: @subshell ref,
|
||||
int index: int ref,
|
||||
unique int subshell_child_type: @subshell_child_type ref
|
||||
unique int child: @subshell_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1207,7 +1249,7 @@ superclass_def(
|
||||
symbol_child(
|
||||
int symbol: @symbol ref,
|
||||
int index: int ref,
|
||||
unique int symbol_child_type: @symbol_child_type ref
|
||||
unique int child: @symbol_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1222,7 +1264,7 @@ symbol_def(
|
||||
symbol_array_child(
|
||||
int symbol_array: @symbol_array ref,
|
||||
int index: int ref,
|
||||
unique int bare_symbol: @bare_symbol ref
|
||||
unique int child: @bare_symbol ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1239,7 +1281,7 @@ symbol_array_def(
|
||||
then_child(
|
||||
int then: @then ref,
|
||||
int index: int ref,
|
||||
unique int then_child_type: @then_child_type ref
|
||||
unique int child: @then_child_type ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1252,7 +1294,15 @@ then_def(
|
||||
|
||||
@unary_operand_type = @break | @call | @next | @parenthesized_statements | @return | @token_float | @token_integer | @underscore_arg | @yield
|
||||
|
||||
@unary_operator_type = @reserved_word
|
||||
case @unary.operator of
|
||||
0 = @unary_bang
|
||||
| 1 = @unary_plus
|
||||
| 2 = @unary_minus
|
||||
| 3 = @unary_definedquestion
|
||||
| 4 = @unary_not
|
||||
| 5 = @unary_tilde
|
||||
;
|
||||
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
unary_def(
|
||||
@@ -1260,7 +1310,7 @@ unary_def(
|
||||
int parent: @ast_node_parent ref,
|
||||
int parent_index: int ref,
|
||||
int operand: @unary_operand_type ref,
|
||||
int operator: @unary_operator_type ref,
|
||||
int operator: int ref,
|
||||
int loc: @location ref
|
||||
);
|
||||
|
||||
@@ -1268,7 +1318,7 @@ unary_def(
|
||||
undef_child(
|
||||
int undef: @undef ref,
|
||||
int index: int ref,
|
||||
unique int underscore_method_name: @underscore_method_name ref
|
||||
unique int child: @underscore_method_name ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1283,12 +1333,12 @@ undef_def(
|
||||
|
||||
unless_alternative(
|
||||
unique int unless: @unless ref,
|
||||
unique int unless_alternative_type: @unless_alternative_type ref
|
||||
unique int alternative: @unless_alternative_type ref
|
||||
);
|
||||
|
||||
unless_consequence(
|
||||
unique int unless: @unless ref,
|
||||
unique int then: @then ref
|
||||
unique int consequence: @then ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
@@ -1336,7 +1386,7 @@ until_modifier_def(
|
||||
|
||||
when_body(
|
||||
unique int when: @when ref,
|
||||
unique int then: @then ref
|
||||
unique int body: @then ref
|
||||
);
|
||||
|
||||
#keyset[when, index]
|
||||
@@ -1378,7 +1428,7 @@ while_modifier_def(
|
||||
|
||||
yield_child(
|
||||
unique int yield: @yield ref,
|
||||
unique int argument_list: @argument_list ref
|
||||
unique int child: @argument_list ref
|
||||
);
|
||||
|
||||
#keyset[parent, parent_index]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user