Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2465c1b

Browse files
committedJan 11, 2025·
Restructure the tables to allow more customizations
1 parent 9400824 commit 2465c1b

File tree

15 files changed

+205
-127
lines changed

15 files changed

+205
-127
lines changed
 

‎Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ gitql-ast = "0.31.0"
2020
gitql-parser = "0.34.0"
2121
gitql-engine = "0.35.0"
2222
clang-sys = "1.8.1"
23+
dyn-clone = "1.0.17"

‎docs/ASTFunctions.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
### AST function node functions
2+
3+
| Function | Parameters | Return | Description |
4+
| :-------------: | :----------------: | :----: | :----------------------------------: |
5+
| is_virtual | (n : FunctionType) | Bool | True if the function is virtual |
6+
| is_pure_virtual | (n : FunctionType) | Bool | True if the function is pure virtual |

‎src/clang_ql/data_provider.rs

+3-47
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::clang_ql::visitors::function;
1717
use crate::clang_ql::visitors::global;
1818
use crate::clang_ql::visitors::unions;
1919

20+
use super::values::FunctionValue;
2021
use super::values::SourceLocValue;
2122

2223
pub struct ClangDataProvider {
@@ -238,58 +239,13 @@ fn select_functions(
238239
continue;
239240
}
240241

241-
if column_name == "args_count" {
242-
values.push(Box::new(IntValue::new(function.arguments_count as i64)));
243-
continue;
244-
}
245-
246-
if column_name == "class_name" {
247-
values.push(Box::new(TextValue::new(function.class_name.to_owned())));
248-
continue;
249-
}
250-
251242
if column_name == "return_type" {
252243
values.push(Box::new(TextValue::new(function.return_type.to_owned())));
253244
continue;
254245
}
255246

256-
if column_name == "is_method" {
257-
values.push(Box::new(BoolValue::new(function.is_method)));
258-
continue;
259-
}
260-
261-
if column_name == "is_virtual" {
262-
values.push(Box::new(BoolValue::new(function.is_virtual)));
263-
continue;
264-
}
265-
266-
if column_name == "is_pure_virtual" {
267-
values.push(Box::new(BoolValue::new(function.is_pure_virtual)));
268-
continue;
269-
}
270-
271-
if column_name == "is_static" {
272-
values.push(Box::new(BoolValue::new(function.is_static)));
273-
continue;
274-
}
275-
276-
if column_name == "is_const" {
277-
values.push(Box::new(BoolValue::new(function.is_const)));
278-
continue;
279-
}
280-
281-
if column_name == "has_template" {
282-
values.push(Box::new(BoolValue::new(function.has_template)));
283-
continue;
284-
}
285-
286-
if column_name == "access_modifier" {
287-
values.push(Box::new(IntValue::new(function.access_modifier as i64)));
288-
continue;
289-
}
290-
291-
if column_name == "is_variadic" {
292-
values.push(Box::new(BoolValue::new(function.is_variadic)));
247+
if column_name == "ast_function" {
248+
values.push(Box::new(FunctionValue::new(function.clone())));
293249
continue;
294250
}
295251

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use std::collections::HashMap;
2+
3+
use clang_sys::clang_CXXMethod_isPureVirtual;
4+
use clang_sys::clang_CXXMethod_isVirtual;
5+
use gitql_ast::types::boolean::BoolType;
6+
use gitql_core::signature::Signature;
7+
use gitql_core::signature::StandardFunction;
8+
use gitql_core::values::base::Value;
9+
use gitql_core::values::boolean::BoolValue;
10+
11+
use crate::clang_ql::types::FunctionType;
12+
use crate::clang_ql::values::FunctionValue;
13+
14+
#[inline(always)]
15+
pub fn register_ast_function_functions(map: &mut HashMap<&'static str, StandardFunction>) {
16+
map.insert("is_virtual", function_is_virtual);
17+
map.insert("is_pure_virtual", is_pure_virtual);
18+
}
19+
20+
#[inline(always)]
21+
pub fn register_ast_function_signatures(map: &mut HashMap<&'static str, Signature>) {
22+
map.insert(
23+
"is_virtual",
24+
Signature::with_return(Box::new(BoolType)).add_parameter(Box::new(FunctionType)),
25+
);
26+
27+
map.insert(
28+
"is_pure_virtual",
29+
Signature::with_return(Box::new(BoolType)).add_parameter(Box::new(FunctionType)),
30+
);
31+
}
32+
33+
fn function_is_virtual(values: &[Box<dyn Value>]) -> Box<dyn Value> {
34+
let ast_node = values[0].as_any().downcast_ref::<FunctionValue>().unwrap();
35+
let is_virtual = unsafe { clang_CXXMethod_isVirtual(ast_node.node.cursor) != 0 };
36+
Box::new(BoolValue::new(is_virtual))
37+
}
38+
39+
fn is_pure_virtual(values: &[Box<dyn Value>]) -> Box<dyn Value> {
40+
let ast_node = values[0].as_any().downcast_ref::<FunctionValue>().unwrap();
41+
let is_virtual = unsafe { clang_CXXMethod_isPureVirtual(ast_node.node.cursor) != 0 };
42+
Box::new(BoolValue::new(is_virtual))
43+
}

‎src/clang_ql/functions/ast/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
mod functions;
2+
use functions::register_ast_function_functions;
3+
use functions::register_ast_function_signatures;
4+
5+
use std::collections::HashMap;
6+
7+
use gitql_core::signature::Signature;
8+
use gitql_core::signature::StandardFunction;
9+
10+
#[inline(always)]
11+
pub fn register_ast_functions(map: &mut HashMap<&'static str, StandardFunction>) {
12+
register_ast_function_functions(map);
13+
}
14+
15+
#[inline(always)]
16+
pub fn register_ast_signatures(map: &mut HashMap<&'static str, Signature>) {
17+
register_ast_function_signatures(map);
18+
}

‎src/clang_ql/functions/mod.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::collections::HashMap;
2+
use std::sync::OnceLock;
3+
4+
use gitql_core::signature::Signature;
5+
use gitql_core::signature::StandardFunction;
6+
use gitql_std::standard::standard_function_signatures;
7+
use gitql_std::standard::standard_functions;
8+
9+
mod ast;
10+
11+
#[inline(always)]
12+
pub fn clang_ql_functions() -> &'static HashMap<&'static str, StandardFunction> {
13+
static HASHMAP: OnceLock<HashMap<&'static str, StandardFunction>> = OnceLock::new();
14+
HASHMAP.get_or_init(|| {
15+
let mut map = standard_functions().to_owned();
16+
ast::register_ast_functions(&mut map);
17+
map
18+
})
19+
}
20+
21+
#[inline(always)]
22+
pub fn clang_ql_functions_signatures() -> HashMap<&'static str, Signature> {
23+
let mut map = standard_function_signatures().to_owned();
24+
ast::register_ast_signatures(&mut map);
25+
map
26+
}

‎src/clang_ql/matchers/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use dyn_clone::DynClone;
2+
3+
use super::values::FunctionNode;
4+
5+
dyn_clone::clone_trait_object!(FunctionMatcher);
6+
7+
pub trait FunctionMatcher: DynClone {
8+
fn is_match(&self, function: FunctionNode) -> bool;
9+
}

‎src/clang_ql/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
pub mod clang_parser;
22
pub mod data_provider;
3+
pub mod matchers;
34
pub mod schema;
5+
pub mod functions;
46
pub mod types;
57
pub mod values;
68
pub mod visitors;

‎src/clang_ql/schema.rs

+7-25
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,23 @@ use gitql_core::environment::Environment;
99
use gitql_core::schema::Schema;
1010
use gitql_std::aggregation::aggregation_function_signatures;
1111
use gitql_std::aggregation::aggregation_functions;
12-
use gitql_std::standard::standard_function_signatures;
13-
use gitql_std::standard::standard_functions;
1412
use gitql_std::window::window_function_signatures;
1513
use gitql_std::window::window_functions;
1614

15+
use super::functions::clang_ql_functions;
16+
use super::functions::clang_ql_functions_signatures;
17+
use super::types::FunctionType;
1718
use super::types::SourceLocType;
1819

1920
fn tables_fields_types() -> HashMap<&'static str, Box<dyn DataType>> {
2021
let mut map: HashMap<&'static str, Box<dyn DataType>> = HashMap::new();
2122
map.insert("name", Box::new(TextType));
2223
map.insert("type", Box::new(TextType));
2324
map.insert("signature", Box::new(TextType));
24-
map.insert("class_name", Box::new(TextType));
25+
map.insert("ast_function", Box::new(FunctionType));
2526

26-
map.insert("access_modifier", Box::new(IntType));
27-
28-
map.insert("is_method", Box::new(BoolType));
29-
map.insert("is_virtual", Box::new(BoolType));
30-
map.insert("is_pure_virtual", Box::new(BoolType));
31-
map.insert("is_static", Box::new(BoolType));
32-
map.insert("is_const", Box::new(BoolType));
33-
map.insert("is_variadic", Box::new(BoolType));
3427
map.insert("is_volatile", Box::new(BoolType));
3528
map.insert("is_struct", Box::new(BoolType));
36-
map.insert("has_template", Box::new(BoolType));
3729

3830
map.insert("return_type", Box::new(TextType));
3931
map.insert("type_literal", Box::new(TextType));
@@ -47,7 +39,6 @@ fn tables_fields_types() -> HashMap<&'static str, Box<dyn DataType>> {
4739
map.insert("size", Box::new(IntType));
4840
map.insert("align", Box::new(IntType));
4941

50-
// Source code location columns
5142
map.insert("source_loc", Box::new(SourceLocType));
5243
map
5344
}
@@ -79,17 +70,8 @@ fn tables_fields_names() -> &'static HashMap<&'static str, Vec<&'static str>> {
7970
vec![
8071
"name",
8172
"signature",
82-
"args_count",
8373
"return_type",
84-
"class_name",
85-
"is_method",
86-
"is_virtual",
87-
"is_pure_virtual",
88-
"is_static",
89-
"is_const",
90-
"has_template",
91-
"access_modifier",
92-
"is_variadic",
74+
"ast_function",
9375
"source_loc",
9476
],
9577
);
@@ -104,8 +86,8 @@ pub fn create_clang_ql_environment() -> Environment {
10486
tables_fields_types: tables_fields_types().to_owned(),
10587
};
10688

107-
let std_signatures = standard_function_signatures();
108-
let std_functions = standard_functions();
89+
let std_signatures = clang_ql_functions_signatures();
90+
let std_functions = clang_ql_functions();
10991

11092
let aggregation_signatures = aggregation_function_signatures();
11193
let aggregation_functions = aggregation_functions();

‎src/clang_ql/types/function.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use std::any::Any;
2+
3+
use gitql_ast::types::base::DataType;
4+
5+
#[derive(Clone)]
6+
pub struct FunctionType;
7+
8+
impl DataType for FunctionType {
9+
fn literal(&self) -> String {
10+
"Function".to_string()
11+
}
12+
13+
#[allow(clippy::borrowed_box)]
14+
fn equals(&self, other: &Box<dyn DataType>) -> bool {
15+
let self_type: Box<dyn DataType> = Box::new(FunctionType);
16+
other.is_any()
17+
|| other.is_variant_contains(&self_type)
18+
|| other.as_any().downcast_ref::<FunctionType>().is_some()
19+
}
20+
21+
fn as_any(&self) -> &dyn Any {
22+
self
23+
}
24+
}

‎src/clang_ql/types/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
mod source_location;
22
pub use source_location::SourceLocType;
3+
4+
mod function;
5+
pub use function::FunctionType;

‎src/clang_ql/values/function.rs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use clang_sys::CXCursor;
2+
use gitql_core::values::base::Value;
3+
4+
use crate::clang_ql::types::FunctionType;
5+
6+
use super::FileLocation;
7+
8+
#[derive(Clone)]
9+
pub struct FunctionNode {
10+
pub name: String,
11+
pub cursor: CXCursor,
12+
pub parent: CXCursor,
13+
pub signature: String,
14+
pub return_type: String,
15+
pub location: FileLocation,
16+
}
17+
18+
#[derive(Clone)]
19+
pub struct FunctionValue {
20+
pub node: FunctionNode,
21+
}
22+
23+
impl FunctionValue {
24+
pub fn new(node: FunctionNode) -> Self {
25+
FunctionValue { node }
26+
}
27+
}
28+
29+
impl Value for FunctionValue {
30+
fn literal(&self) -> String {
31+
self.node.signature.to_string()
32+
}
33+
34+
fn equals(&self, other: &Box<dyn Value>) -> bool {
35+
if let Some(other_fun) = other.as_any().downcast_ref::<FunctionValue>() {
36+
return self.node.name.eq(&other_fun.node.name)
37+
&& self.node.signature.eq(&other_fun.node.signature)
38+
&& self.node.return_type.eq(&other_fun.node.return_type)
39+
&& self.node.location.eq(&other_fun.node.location);
40+
}
41+
false
42+
}
43+
44+
fn compare(&self, _other: &Box<dyn Value>) -> Option<std::cmp::Ordering> {
45+
None
46+
}
47+
48+
fn data_type(&self) -> Box<dyn gitql_ast::types::base::DataType> {
49+
Box::new(FunctionType)
50+
}
51+
52+
fn as_any(&self) -> &dyn std::any::Any {
53+
self
54+
}
55+
}

‎src/clang_ql/values/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
mod source_location;
22
pub use source_location::FileLocation;
33
pub use source_location::SourceLocValue;
4+
5+
mod function;
6+
pub use function::FunctionNode;
7+
pub use function::FunctionValue;

‎src/clang_ql/visitors/function.rs

+3-55
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,9 @@ use std::ffi::c_void;
55
use std::ffi::CStr;
66

77
use crate::clang_ql::clang_parser::CompilationUnit;
8-
use crate::clang_ql::values::FileLocation;
8+
use crate::clang_ql::values::FunctionNode;
99
use crate::clang_ql::visitors::location;
1010

11-
pub struct FunctionNode {
12-
pub name: String,
13-
pub signature: String,
14-
pub return_type: String,
15-
pub arguments_count: i32,
16-
pub class_name: String,
17-
pub is_method: bool,
18-
pub is_virtual: bool,
19-
pub is_pure_virtual: bool,
20-
pub is_static: bool,
21-
pub is_const: bool,
22-
pub has_template: bool,
23-
pub access_modifier: i32,
24-
pub is_variadic: bool,
25-
pub location: FileLocation,
26-
}
27-
2811
pub fn select_clang_functions(compilation_unit: &CompilationUnit) -> Vec<FunctionNode> {
2912
let mut functions: Vec<FunctionNode> = Vec::new();
3013
let data = &mut functions as *mut Vec<FunctionNode> as *mut c_void;
@@ -67,49 +50,14 @@ extern "C" fn visit_children(
6750
let return_type =
6851
CStr::from_ptr(clang_getCString(result_type_spelling)).to_string_lossy();
6952

70-
let arguments_count = clang_getNumArgTypes(function_type);
71-
72-
let mut is_method = false;
73-
let mut has_template = false;
74-
let mut class_name = String::from("None");
75-
let mut is_virtual = false;
76-
let mut is_pure_virtual = false;
77-
let mut is_static = false;
78-
let mut is_const = false;
79-
80-
if cursor_kind == CXCursor_CXXMethod {
81-
is_method = true;
82-
has_template = cursor_kind == CXCursor_FunctionTemplate;
83-
84-
let parent_spelling = clang_getCursorSpelling(parent);
85-
let parent_name =
86-
CStr::from_ptr(clang_getCString(parent_spelling)).to_string_lossy();
87-
class_name = parent_name.to_string();
88-
89-
is_virtual = clang_CXXMethod_isVirtual(cursor) != 0;
90-
is_pure_virtual = clang_CXXMethod_isPureVirtual(cursor) != 0;
91-
is_static = clang_CXXMethod_isStatic(cursor) != 0;
92-
is_const = clang_CXXMethod_isConst(cursor) != 0;
93-
}
94-
95-
let access_modifier = clang_getCXXAccessSpecifier(cursor);
96-
let is_variadic = clang_isFunctionTypeVariadic(function_type) != 0;
9753
let location = location::visit_source_location(cursor);
9854

9955
functions.push(FunctionNode {
10056
name: name.to_string(),
57+
cursor,
58+
parent,
10159
signature: signature.to_string(),
10260
return_type: return_type.to_string(),
103-
arguments_count,
104-
class_name,
105-
is_method,
106-
is_virtual,
107-
is_pure_virtual,
108-
is_static,
109-
is_const,
110-
has_template,
111-
access_modifier,
112-
is_variadic,
11361
location,
11462
});
11563

0 commit comments

Comments
 (0)
Please sign in to comment.