mirror of
https://github.com/github/codeql.git
synced 2026-04-26 09:15:12 +02:00
Merge pull request #261 from github/getPrimaryQlClasses
Implement getPrimaryQlClasses
This commit is contained in:
@@ -127,12 +127,13 @@ pub enum Expression<'a> {
|
||||
Or(Vec<Expression<'a>>),
|
||||
Equals(Box<Expression<'a>>, Box<Expression<'a>>),
|
||||
Dot(Box<Expression<'a>>, &'a str, Vec<Expression<'a>>),
|
||||
Aggregate(
|
||||
&'a str,
|
||||
Vec<FormalParameter<'a>>,
|
||||
Box<Expression<'a>>,
|
||||
Box<Expression<'a>>,
|
||||
),
|
||||
Aggregate {
|
||||
name: &'a str,
|
||||
vars: Vec<FormalParameter<'a>>,
|
||||
range: Option<Box<Expression<'a>>>,
|
||||
expr: Box<Expression<'a>>,
|
||||
second_expr: Option<Box<Expression<'a>>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Expression<'a> {
|
||||
@@ -188,15 +189,31 @@ impl<'a> fmt::Display for Expression<'a> {
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
Expression::Aggregate(n, vars, range, term) => {
|
||||
write!(f, "{}(", n)?;
|
||||
for (index, var) in vars.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(f, ", ")?;
|
||||
Expression::Aggregate {
|
||||
name,
|
||||
vars,
|
||||
range,
|
||||
expr,
|
||||
second_expr,
|
||||
} => {
|
||||
write!(f, "{}(", name)?;
|
||||
if vars.len() > 0 {
|
||||
for (index, var) in vars.iter().enumerate() {
|
||||
if index > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", var)?;
|
||||
}
|
||||
write!(f, "{}", var)?;
|
||||
write!(f, " | ")?;
|
||||
}
|
||||
write!(f, " | {} | {})", range, term)
|
||||
if let Some(range) = range {
|
||||
write!(f, "{} | ", range)?;
|
||||
}
|
||||
write!(f, "{}", expr)?;
|
||||
if let Some(second_expr) = second_expr {
|
||||
write!(f, ", {}", second_expr)?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,27 @@ pub fn create_ast_node_class<'a>(ast_node: &'a str, ast_node_parent: &'a str) ->
|
||||
Box::new(ql::Expression::String("???")),
|
||||
),
|
||||
};
|
||||
let get_primary_ql_classes = ql::Predicate {
|
||||
qldoc: Some(
|
||||
"Gets a comma-separated list of the names of the primary CodeQL \
|
||||
classes to which this element belongs."
|
||||
.to_owned(),
|
||||
),
|
||||
name: "getPrimaryQlClasses",
|
||||
overridden: false,
|
||||
return_type: Some(ql::Type::String),
|
||||
formal_parameters: vec![],
|
||||
body: ql::Expression::Equals(
|
||||
Box::new(ql::Expression::Var("result")),
|
||||
Box::new(ql::Expression::Aggregate {
|
||||
name: "concat",
|
||||
vars: vec![],
|
||||
range: None,
|
||||
expr: Box::new(ql::Expression::Pred("getAPrimaryQlClass", vec![])),
|
||||
second_expr: Some(Box::new(ql::Expression::String(","))),
|
||||
}),
|
||||
),
|
||||
};
|
||||
ql::Class {
|
||||
qldoc: Some(String::from("The base class for all AST nodes")),
|
||||
name: "AstNode",
|
||||
@@ -92,6 +113,7 @@ pub fn create_ast_node_class<'a>(ast_node: &'a str, ast_node_parent: &'a str) ->
|
||||
get_parent_index,
|
||||
get_a_field_or_child,
|
||||
get_a_primary_ql_class,
|
||||
get_primary_ql_classes,
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -410,15 +432,16 @@ fn create_field_getters<'a>(
|
||||
})
|
||||
.collect();
|
||||
(
|
||||
ql::Expression::Aggregate(
|
||||
"exists",
|
||||
vec![ql::FormalParameter {
|
||||
ql::Expression::Aggregate {
|
||||
name: "exists",
|
||||
vars: vec![ql::FormalParameter {
|
||||
name: "value",
|
||||
param_type: ql::Type::Int,
|
||||
}],
|
||||
Box::new(get_value),
|
||||
Box::new(ql::Expression::Or(disjuncts)),
|
||||
),
|
||||
range: Some(Box::new(get_value)),
|
||||
expr: Box::new(ql::Expression::Or(disjuncts)),
|
||||
second_expr: None,
|
||||
},
|
||||
// Since the getter returns a string and not an AstNode, it won't be part of getAFieldOrChild:
|
||||
None,
|
||||
)
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import codeql.ruby.AST
|
||||
import codeql.ruby.ast.internal.Synthesis
|
||||
|
||||
private string getAPrimaryQlClass(AstNode node) {
|
||||
result = node.getAPrimaryQlClass()
|
||||
or
|
||||
not exists(node.getAPrimaryQlClass()) and result = "(none)"
|
||||
}
|
||||
|
||||
query predicate missingParent(AstNode node, string cls) {
|
||||
not exists(node.getParent()) and
|
||||
node.getLocation().getFile().getExtension() != "erb" and
|
||||
not node instanceof Toplevel and
|
||||
cls = getAPrimaryQlClass(node)
|
||||
cls = node.getPrimaryQlClasses()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -22,7 +16,7 @@ private AstNode parent(AstNode child, int desugarLevel) {
|
||||
|
||||
query predicate multipleParents(AstNode node, AstNode parent, string cls) {
|
||||
parent = node.getParent() and
|
||||
cls = getAPrimaryQlClass(parent) and
|
||||
cls = parent.getPrimaryQlClasses() and
|
||||
exists(AstNode one, AstNode two, int desugarLevel |
|
||||
one = parent(node, desugarLevel) and
|
||||
two = parent(node, desugarLevel) and
|
||||
|
||||
@@ -32,6 +32,12 @@ class AstNode extends TAstNode {
|
||||
*/
|
||||
string getAPrimaryQlClass() { result = "???" }
|
||||
|
||||
/**
|
||||
* Gets a comma-separated list of the names of the primary CodeQL classes to
|
||||
* which this element belongs.
|
||||
*/
|
||||
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
|
||||
|
||||
/** Gets the enclosing module, if any. */
|
||||
ModuleBase getEnclosingModule() {
|
||||
exists(Scope::Range s |
|
||||
|
||||
@@ -26,6 +26,9 @@ module Ruby {
|
||||
|
||||
/** Gets the name of the primary QL class for this element. */
|
||||
string getAPrimaryQlClass() { result = "???" }
|
||||
|
||||
/** Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */
|
||||
string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") }
|
||||
}
|
||||
|
||||
/** A token. */
|
||||
@@ -1864,6 +1867,9 @@ module Erb {
|
||||
|
||||
/** Gets the name of the primary QL class for this element. */
|
||||
string getAPrimaryQlClass() { result = "???" }
|
||||
|
||||
/** Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */
|
||||
string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") }
|
||||
}
|
||||
|
||||
/** A token. */
|
||||
|
||||
@@ -18,10 +18,15 @@ class RegExpParent extends TRegExpParent {
|
||||
|
||||
/**
|
||||
* Gets the name of a primary CodeQL class to which this regular
|
||||
* expression
|
||||
* term belongs.
|
||||
* expression term belongs.
|
||||
*/
|
||||
string getAPrimaryQlClass() { result = "RegExpParent" }
|
||||
|
||||
/**
|
||||
* Gets a comma-separated list of the names of the primary CodeQL classes to
|
||||
* which this regular expression term belongs.
|
||||
*/
|
||||
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
|
||||
}
|
||||
|
||||
class RegExpLiteral extends TRegExpLiteral, RegExpParent {
|
||||
|
||||
Reference in New Issue
Block a user