Skip to content

Commit

Permalink
feat: Support query enum name and number of constants
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrDeveloper committed May 5, 2024
1 parent b2c58d2 commit 8e16b87
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
73 changes: 73 additions & 0 deletions src/data_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use gitql_engine::data_provider::DataProvider;
use gitql_engine::engine_evaluator::evaluate_expression;

use crate::visitor::class;
use crate::visitor::enumeration;
use crate::visitor::function;
use crate::visitor::global;
pub struct ClangAstDataProvider {
Expand Down Expand Up @@ -69,6 +70,7 @@ fn select_clang_ast_objects(
) -> Result<Group, String> {
match table.as_str() {
"classes" => select_classes(env, path, fields_names, titles, fields_values),
"enums" => select_enumss(env, path, fields_names, titles, fields_values),
"functions" => select_functions(env, path, fields_names, titles, fields_values),
"globals" => select_variables(env, path, fields_names, titles, fields_values),
_ => select_values(env, titles, fields_values),
Expand Down Expand Up @@ -159,6 +161,77 @@ fn select_classes(
Ok(Group { rows })
}

fn select_enumss(
env: &mut Environment,
path: &str,
fields_names: &[String],
titles: &[String],
fields_values: &[Box<dyn Expression>],
) -> Result<Group, String> {
let mut rows: Vec<Row> = vec![];

let names_len = fields_names.len() as i64;
let values_len = fields_values.len() as i64;
let padding = names_len - values_len;

let ast_enums = enumeration::select_clang_enums(path);
for enumeration in ast_enums.iter() {
let mut values: Vec<Value> = Vec::with_capacity(fields_names.len());

for index in 0..names_len {
let field_name = &fields_names[index as usize];

if (index - padding) >= 0 {
let value = &fields_values[(index - padding) as usize];
if value.as_any().downcast_ref::<SymbolExpression>().is_none() {
let evaluated = evaluate_expression(env, value, titles, &values)?;
values.push(evaluated);
continue;
}
}

if field_name == "name" {
values.push(Value::Text(enumeration.name.to_owned()));
continue;
}

if field_name == "constants_count" {
values.push(Value::Integer(
enumeration.attributes.constants_count.into(),
));
continue;
}

if field_name == "file" {
values.push(Value::Text(enumeration.location.file.to_string()));
continue;
}

if field_name == "line" {
values.push(Value::Integer(enumeration.location.line.into()));
continue;
}

if field_name == "column" {
values.push(Value::Integer(enumeration.location.column.into()));
continue;
}

if field_name == "offset" {
values.push(Value::Integer(enumeration.location.offset.into()));
continue;
}

values.push(Value::Null);
}

let row = Row { values };
rows.push(row);
}

Ok(Group { rows })
}

fn select_functions(
env: &mut Environment,
path: &str,
Expand Down
5 changes: 5 additions & 0 deletions src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ lazy_static! {
map.insert("bases_count", DataType::Integer);
map.insert("methods_count", DataType::Integer);
map.insert("fields_count", DataType::Integer);
map.insert("constants_count", DataType::Integer);

// Source code location columns
map.insert("file", DataType::Text);
Expand All @@ -51,6 +52,10 @@ lazy_static! {
"offset",
],
);
map.insert(
"enums",
vec!["name", "constants_count", "line", "column", "offset"],
);
map.insert(
"functions",
vec![
Expand Down
106 changes: 106 additions & 0 deletions src/visitor/enumeration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
extern crate clang_sys;

use clang_sys::*;
use std::ffi::c_char;
use std::ffi::c_void;
use std::ffi::CStr;
use std::ptr;

use crate::visitor::location;

pub struct EnumNode {
pub name: String,
pub attributes: EnumAttributes,
pub location: location::SourceLocation,
}

#[derive(Default)]
pub struct EnumAttributes {
pub constants_count: u32,
}

pub fn select_clang_enums(path: &str) -> Vec<EnumNode> {
let mut enums: Vec<EnumNode> = Vec::new();
let data = &mut enums as *mut Vec<EnumNode> as *mut c_void;

unsafe {
let index = clang_createIndex(0, 0);
let translation_unit: CXTranslationUnit = clang_parseTranslationUnit(
index,
path.as_ptr() as *const c_char,
ptr::null_mut(),
0,
ptr::null_mut(),
0,
0,
);

let cursor = clang_getTranslationUnitCursor(translation_unit);
clang_visitChildren(cursor, visit_enum_declaration, data);

// Dispose the translation unit
clang_disposeTranslationUnit(translation_unit);

// Dispose the index
clang_disposeIndex(index);
}

enums
}

extern "C" fn visit_enum_declaration(
cursor: CXCursor,
_parent: CXCursor,
data: *mut c_void,
) -> CXChildVisitResult {
unsafe {
if clang_Location_isFromMainFile(clang_getCursorLocation(cursor)) == 0 {
return CXChildVisit_Continue;
}

let cursor_kind = clang_getCursorKind(cursor);
if cursor_kind == CXCursor_EnumDecl {
let cursor_name = clang_getCursorSpelling(cursor);
let enum_name = CStr::from_ptr(clang_getCString(cursor_name)).to_string_lossy();

let location = location::visit_source_location(cursor);

let enums = &mut *(data as *mut Vec<EnumNode>);

let mut attributes = EnumAttributes::default();
let attributes_pointer = &mut attributes as *mut EnumAttributes as *mut c_void;
clang_visitChildren(cursor, visit_enum_attributes, attributes_pointer);

enums.push(EnumNode {
name: enum_name.to_string(),
attributes,
location,
});

clang_disposeString(cursor_name);
return CXChildVisit_Continue;
}
}
CXChildVisit_Recurse
}

extern "C" fn visit_enum_attributes(
cursor: CXCursor,
_parent: CXCursor,
data: *mut c_void,
) -> CXChildVisitResult {
unsafe {
if clang_Location_isFromMainFile(clang_getCursorLocation(cursor)) == 0 {
return CXChildVisit_Continue;
}

let cursor_kind = clang_getCursorKind(cursor);

if cursor_kind == CXCursor_EnumConstantDecl {
let attributes = &mut *(data as *mut EnumAttributes);
attributes.constants_count += 1;
return CXChildVisit_Continue;
}
}
CXChildVisit_Recurse
}
1 change: 1 addition & 0 deletions src/visitor/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod class;
pub mod enumeration;
pub mod function;
pub mod global;
pub mod location;

0 comments on commit 8e16b87

Please sign in to comment.