mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Rust: move body skipping logic to code generation
This commit is contained in:
@@ -114,7 +114,9 @@ fn node_src_to_schema_class(
|
||||
let (ty, child) = match &f.ty {
|
||||
FieldType::String => ("optional[string]".to_string(), false),
|
||||
FieldType::Predicate => ("predicate".to_string(), false),
|
||||
FieldType::Optional(ty) => (format!("optional[\"{}\"]", class_name(ty)), true),
|
||||
FieldType::Optional(ty) | FieldType::Body(ty) => {
|
||||
(format!("optional[\"{}\"]", class_name(ty)), true)
|
||||
}
|
||||
FieldType::List(ty) => (format!("list[\"{}\"]", class_name(ty)), true),
|
||||
};
|
||||
SchemaField {
|
||||
@@ -169,6 +171,7 @@ enum FieldType {
|
||||
String,
|
||||
Predicate,
|
||||
Optional(String),
|
||||
Body(String),
|
||||
List(String),
|
||||
}
|
||||
|
||||
@@ -177,158 +180,93 @@ struct FieldInfo {
|
||||
ty: FieldType,
|
||||
}
|
||||
|
||||
impl FieldInfo {
|
||||
pub fn optional(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Optional(ty.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Body(ty.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string(name: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::String,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn predicate(name: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::Predicate,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list(name: &str, ty: &str) -> FieldInfo {
|
||||
FieldInfo {
|
||||
name: name.to_string(),
|
||||
ty: FieldType::List(ty.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_additional_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
|
||||
match node.name.as_str() {
|
||||
"Name" | "NameRef" | "Lifetime" => vec![FieldInfo {
|
||||
name: "text".to_string(),
|
||||
ty: FieldType::String,
|
||||
}],
|
||||
"Abi" => vec![FieldInfo {
|
||||
name: "abi_string".to_string(),
|
||||
ty: FieldType::String,
|
||||
}],
|
||||
"Literal" => vec![FieldInfo {
|
||||
name: "text_value".to_string(),
|
||||
ty: FieldType::String,
|
||||
}],
|
||||
"PrefixExpr" => vec![FieldInfo {
|
||||
name: "operator_name".to_string(),
|
||||
ty: FieldType::String,
|
||||
}],
|
||||
"Name" | "NameRef" | "Lifetime" => vec![FieldInfo::string("text")],
|
||||
"Abi" => vec![FieldInfo::string("abi_string")],
|
||||
"Literal" => vec![FieldInfo::string("text_value")],
|
||||
"PrefixExpr" => vec![FieldInfo::string("operator_name")],
|
||||
"BinExpr" => vec![
|
||||
FieldInfo {
|
||||
name: "lhs".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "rhs".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "operator_name".to_string(),
|
||||
ty: FieldType::String,
|
||||
},
|
||||
FieldInfo::optional("lhs", "Expr"),
|
||||
FieldInfo::optional("rhs", "Expr"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"IfExpr" => vec![
|
||||
FieldInfo {
|
||||
name: "then_branch".to_string(),
|
||||
ty: FieldType::Optional("BlockExpr".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "else_branch".to_string(),
|
||||
ty: FieldType::Optional("ElseBranch".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "condition".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
},
|
||||
FieldInfo::optional("then_branch", "BlockExpr"),
|
||||
FieldInfo::optional("else_branch", "ElseBranch"),
|
||||
FieldInfo::optional("condition", "Expr"),
|
||||
],
|
||||
"RangeExpr" => vec![
|
||||
FieldInfo {
|
||||
name: "start".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "end".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "operator_name".to_string(),
|
||||
ty: FieldType::String,
|
||||
},
|
||||
FieldInfo::optional("start", "Expr"),
|
||||
FieldInfo::optional("end", "Expr"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"RangePat" => vec![
|
||||
FieldInfo {
|
||||
name: "start".to_string(),
|
||||
ty: FieldType::Optional("Pat".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "end".to_string(),
|
||||
ty: FieldType::Optional("Pat".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "operator_name".to_string(),
|
||||
ty: FieldType::String,
|
||||
},
|
||||
FieldInfo::optional("start", "Pat"),
|
||||
FieldInfo::optional("end", "Pat"),
|
||||
FieldInfo::string("operator_name"),
|
||||
],
|
||||
"IndexExpr" => vec![
|
||||
FieldInfo {
|
||||
name: "index".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "base".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
},
|
||||
FieldInfo::optional("index", "Expr"),
|
||||
FieldInfo::optional("base", "Expr"),
|
||||
],
|
||||
"Impl" => vec![
|
||||
FieldInfo {
|
||||
name: "trait_".to_string(),
|
||||
ty: FieldType::Optional("Type".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "self_ty".to_string(),
|
||||
ty: FieldType::Optional("Type".to_string()),
|
||||
},
|
||||
FieldInfo::optional("trait_", "Type"),
|
||||
FieldInfo::optional("self_ty", "Type"),
|
||||
],
|
||||
"ForExpr" => vec![FieldInfo {
|
||||
name: "iterable".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
}],
|
||||
"WhileExpr" => vec![FieldInfo {
|
||||
name: "condition".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
}],
|
||||
"MatchGuard" => vec![FieldInfo {
|
||||
name: "condition".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
}],
|
||||
"ForExpr" => vec![FieldInfo::optional("iterable", "Expr")],
|
||||
"WhileExpr" => vec![FieldInfo::optional("condition", "Expr")],
|
||||
"MatchGuard" => vec![FieldInfo::optional("condition", "Expr")],
|
||||
"MacroDef" => vec![
|
||||
FieldInfo {
|
||||
name: "args".to_string(),
|
||||
ty: FieldType::Optional("TokenTree".to_string()),
|
||||
},
|
||||
FieldInfo {
|
||||
name: "body".to_string(),
|
||||
ty: FieldType::Optional("TokenTree".to_string()),
|
||||
},
|
||||
FieldInfo::optional("args", "TokenTree"),
|
||||
FieldInfo::optional("body", "TokenTree"),
|
||||
],
|
||||
"FormatArgsExpr" => vec![FieldInfo {
|
||||
name: "args".to_string(),
|
||||
ty: FieldType::List("FormatArgsArg".to_string()),
|
||||
}],
|
||||
"ArgList" => vec![FieldInfo {
|
||||
name: "args".to_string(),
|
||||
ty: FieldType::List("Expr".to_string()),
|
||||
}],
|
||||
"Fn" => vec![FieldInfo {
|
||||
name: "body".to_string(),
|
||||
ty: FieldType::Optional("BlockExpr".to_string()),
|
||||
}],
|
||||
"Const" => vec![FieldInfo {
|
||||
name: "body".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
}],
|
||||
"Static" => vec![FieldInfo {
|
||||
name: "body".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
}],
|
||||
"ClosureExpr" => vec![FieldInfo {
|
||||
name: "body".to_string(),
|
||||
ty: FieldType::Optional("Expr".to_string()),
|
||||
}],
|
||||
"ArrayExpr" => vec![FieldInfo {
|
||||
name: "is_semicolon".to_string(),
|
||||
ty: FieldType::Predicate,
|
||||
}],
|
||||
"SelfParam" => vec![FieldInfo {
|
||||
name: "is_amp".to_string(),
|
||||
ty: FieldType::Predicate,
|
||||
}],
|
||||
"UseTree" => vec![FieldInfo {
|
||||
name: "is_star".to_string(),
|
||||
ty: FieldType::Predicate,
|
||||
}],
|
||||
"FormatArgsExpr" => vec![FieldInfo::list("args", "FormatArgsArg")],
|
||||
"ArgList" => vec![FieldInfo::list("args", "Expr")],
|
||||
"Fn" => vec![FieldInfo::body("body", "BlockExpr")],
|
||||
"Const" => vec![FieldInfo::body("body", "Expr")],
|
||||
"Static" => vec![FieldInfo::body("body", "Expr")],
|
||||
"ClosureExpr" => vec![FieldInfo::optional("body", "Expr")],
|
||||
"ArrayExpr" => vec![FieldInfo::predicate("is_semicolon")],
|
||||
"SelfParam" => vec![FieldInfo::predicate("is_amp")],
|
||||
"UseTree" => vec![FieldInfo::predicate("is_star")],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
@@ -356,6 +294,10 @@ fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
|
||||
("ArrayExpr", "expr") // The ArrayExpr type also has an 'exprs' field
|
||||
| ("PathSegment", "ty" | "path_type") // these are broken, handling them manually
|
||||
=> continue,
|
||||
("Param", "pat") => {
|
||||
result.push(FieldInfo::body("pat", "Pat"));
|
||||
continue;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
let ty = match field {
|
||||
@@ -374,54 +316,26 @@ fn get_fields(node: &AstNodeSrc) -> Vec<FieldInfo> {
|
||||
}
|
||||
for trait_ in &node.traits {
|
||||
match trait_.as_str() {
|
||||
"HasAttrs" => result.push(FieldInfo {
|
||||
name: "attrs".to_owned(),
|
||||
ty: FieldType::List("Attr".to_owned()),
|
||||
}),
|
||||
"HasName" => result.push(FieldInfo {
|
||||
name: "name".to_owned(),
|
||||
ty: FieldType::Optional("Name".to_owned()),
|
||||
}),
|
||||
"HasVisibility" => result.push(FieldInfo {
|
||||
name: "visibility".to_owned(),
|
||||
ty: FieldType::Optional("Visibility".to_owned()),
|
||||
}),
|
||||
"HasAttrs" => result.push(FieldInfo::list("attrs", "Attr")),
|
||||
"HasName" => result.push(FieldInfo::optional("name", "Name")),
|
||||
"HasVisibility" => result.push(FieldInfo::optional("visibility", "Visibility")),
|
||||
"HasGenericParams" => {
|
||||
result.push(FieldInfo {
|
||||
name: "generic_param_list".to_owned(),
|
||||
ty: FieldType::Optional("GenericParamList".to_owned()),
|
||||
});
|
||||
result.push(FieldInfo {
|
||||
name: "where_clause".to_owned(),
|
||||
ty: FieldType::Optional("WhereClause".to_owned()),
|
||||
})
|
||||
result.push(FieldInfo::optional(
|
||||
"generic_param_list",
|
||||
"GenericParamList",
|
||||
));
|
||||
result.push(FieldInfo::optional("where_clause", "WhereClause"))
|
||||
}
|
||||
"HasGenericArgs" => result.push(FieldInfo {
|
||||
name: "generic_arg_list".to_owned(),
|
||||
ty: FieldType::Optional("GenericArgList".to_owned()),
|
||||
}),
|
||||
"HasTypeBounds" => result.push(FieldInfo {
|
||||
name: "type_bound_list".to_owned(),
|
||||
ty: FieldType::Optional("TypeBoundList".to_owned()),
|
||||
}),
|
||||
"HasModuleItem" => result.push(FieldInfo {
|
||||
name: "items".to_owned(),
|
||||
ty: FieldType::List("Item".to_owned()),
|
||||
}),
|
||||
"HasGenericArgs" => {
|
||||
result.push(FieldInfo::optional("generic_arg_list", "GenericArgList"))
|
||||
}
|
||||
"HasTypeBounds" => result.push(FieldInfo::optional("type_bound_list", "TypeBoundList")),
|
||||
"HasModuleItem" => result.push(FieldInfo::list("items", "Item")),
|
||||
"HasLoopBody" => {
|
||||
result.push(FieldInfo {
|
||||
name: "label".to_owned(),
|
||||
ty: FieldType::Optional("Label".to_owned()),
|
||||
});
|
||||
result.push(FieldInfo {
|
||||
name: "loop_body".to_owned(),
|
||||
ty: FieldType::Optional("BlockExpr".to_owned()),
|
||||
})
|
||||
result.push(FieldInfo::optional("label", "Label"));
|
||||
result.push(FieldInfo::optional("loop_body", "BlockExpr"))
|
||||
}
|
||||
"HasArgList" => result.push(FieldInfo {
|
||||
name: "arg_list".to_owned(),
|
||||
ty: FieldType::Optional("ArgList".to_owned()),
|
||||
}),
|
||||
"HasArgList" => result.push(FieldInfo::optional("arg_list", "ArgList")),
|
||||
"HasDocComments" => {}
|
||||
|
||||
_ => panic!("Unknown trait {}", trait_),
|
||||
@@ -455,6 +369,7 @@ struct ExtractorNodeFieldInfo {
|
||||
predicate: bool,
|
||||
optional: bool,
|
||||
list: bool,
|
||||
body: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -518,6 +433,13 @@ fn field_info_to_extractor_info(name: &str, field: &FieldInfo) -> ExtractorNodeF
|
||||
optional: true,
|
||||
..Default::default()
|
||||
},
|
||||
FieldType::Body(ty) => ExtractorNodeFieldInfo {
|
||||
name,
|
||||
method: field.name.clone(),
|
||||
snake_case_ty: to_lower_snake_case(ty),
|
||||
body: true,
|
||||
..Default::default()
|
||||
},
|
||||
FieldType::List(ty) => ExtractorNodeFieldInfo {
|
||||
name,
|
||||
method: field.name.clone(),
|
||||
|
||||
@@ -34,23 +34,27 @@ impl Translator<'_> {
|
||||
{{#nodes}}
|
||||
|
||||
pub(crate) fn emit_{{snake_case_name}}(&mut self, node: &ast::{{ast_name}}) -> Option<Label<generated::{{name}}>> {
|
||||
if self.should_be_excluded(node) { return None; }
|
||||
{{#has_attrs}}
|
||||
if self.should_be_excluded_attrs(node) { return None; }
|
||||
if self.should_be_excluded(node) { return None; }
|
||||
{{/has_attrs}}
|
||||
{{#fields}}
|
||||
{{#predicate}}
|
||||
let {{name}} = node.{{method}}().is_some();
|
||||
{{/predicate}}
|
||||
{{#string}}
|
||||
let {{name}} = node.try_get_text();
|
||||
{{/string}}
|
||||
{{#list}}
|
||||
let {{name}} = node.{{method}}().filter_map(|x| self.emit_{{snake_case_ty}}(&x)).collect();
|
||||
{{/list}}
|
||||
{{#optional}}
|
||||
let {{name}} = node.{{method}}().and_then(|x| self.emit_{{snake_case_ty}}(&x));
|
||||
{{/optional}}
|
||||
let {{name}} =
|
||||
{{#predicate}}
|
||||
node.{{method}}().is_some()
|
||||
{{/predicate}}
|
||||
{{#string}}
|
||||
node.try_get_text()
|
||||
{{/string}}
|
||||
{{#list}}
|
||||
node.{{method}}().filter_map(|x| self.emit_{{snake_case_ty}}(&x)).collect()
|
||||
{{/list}}
|
||||
{{#optional}}
|
||||
node.{{method}}().and_then(|x| self.emit_{{snake_case_ty}}(&x))
|
||||
{{/optional}}
|
||||
{{#body}}
|
||||
if self.should_skip_bodies() { None } else { node.{{method}}().and_then(|x| self.emit_{{snake_case_ty}}(&x)) }
|
||||
{{/body}}
|
||||
;
|
||||
{{/fields}}
|
||||
let label = self.trap.emit(generated::{{name}} {
|
||||
id: TrapId::Star,
|
||||
|
||||
Reference in New Issue
Block a user