diff --git a/README.md b/README.md index 81d3568..e3983ff 100644 --- a/README.md +++ b/README.md @@ -43,13 +43,16 @@ SELECT * FROM globals WHERE is_volatile ### Classes and Structs table structure -| Name | Type | Description | -| ------ | ------- | ----------------------- | -| name | Text | Class variable name | -| file | Text | File path | -| line | Integer | Line at the file path | -| column | Integer | Column at the file path | -| offset | Integer | Offset at the file path | +| Name | Type | Description | +| ------------- | ------- | ------------------------------- | +| name | Text | Class variable name | +| is_struct | Boolean | True if it a struct declaration | +| methods_count | Integer | Number of methods declarations | +| fields_count | Integer | Number of fields declarations | +| file | Text | File path | +| line | Integer | Line at the file path | +| column | Integer | Column at the file path | +| offset | Integer | Offset at the file path | --- diff --git a/src/data_provider.rs b/src/data_provider.rs index e571811..d590125 100644 --- a/src/data_provider.rs +++ b/src/data_provider.rs @@ -109,6 +109,16 @@ fn select_classes( continue; } + if field_name == "methods_count" { + values.push(Value::Integer(class.attributes.methods_count as i64)); + continue; + } + + if field_name == "fields_count" { + values.push(Value::Integer(class.attributes.fields_count as i64)); + continue; + } + if field_name == "is_struct" { values.push(Value::Boolean(class.is_struct)); continue; diff --git a/src/schema.rs b/src/schema.rs index 1ca4d0d..ff52d14 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -22,6 +22,9 @@ lazy_static! { map.insert("is_volatile", DataType::Boolean); map.insert("is_struct", DataType::Boolean); + map.insert("methods_count", DataType::Integer); + map.insert("fields_count", DataType::Integer); + // Source code location columns map.insert("file", DataType::Text); map.insert("line", DataType::Integer); @@ -36,7 +39,15 @@ lazy_static! { let mut map = HashMap::new(); map.insert( "classes", - vec!["name", "is_struct", "line", "column", "offset"], + vec![ + "name", + "is_struct", + "methods_count", + "fields_count", + "line", + "column", + "offset", + ], ); map.insert( "functions", diff --git a/src/visitor/class.rs b/src/visitor/class.rs index 9abcdee..cfe6544 100644 --- a/src/visitor/class.rs +++ b/src/visitor/class.rs @@ -10,10 +10,17 @@ use crate::visitor::location; pub struct ClassNode { pub name: String, + pub attributes: ClassAttributes, pub is_struct: bool, pub location: location::SourceLocation, } +#[derive(Default)] +pub struct ClassAttributes { + pub methods_count: u32, + pub fields_count: u32, +} + pub fn select_clang_classes(path: &str) -> Vec { let mut classes: Vec = Vec::new(); let data = &mut classes as *mut Vec as *mut c_void; @@ -31,7 +38,7 @@ pub fn select_clang_classes(path: &str) -> Vec { ); let cursor = clang_getTranslationUnitCursor(translation_unit); - clang_visitChildren(cursor, visit_children, data); + clang_visitChildren(cursor, visit_class_or_struct_declaration, data); // Dispose the translation unit clang_disposeTranslationUnit(translation_unit); @@ -43,7 +50,7 @@ pub fn select_clang_classes(path: &str) -> Vec { classes } -extern "C" fn visit_children( +extern "C" fn visit_class_or_struct_declaration( cursor: CXCursor, _parent: CXCursor, data: *mut c_void, @@ -63,8 +70,13 @@ extern "C" fn visit_children( let classes = &mut *(data as *mut Vec); let is_struct = cursor_kind == CXCursor_StructDecl; + let mut attributes = ClassAttributes::default(); + let attributes_pointer = &mut attributes as *mut ClassAttributes as *mut c_void; + clang_visitChildren(cursor, visit_class_attributes, attributes_pointer); + classes.push(ClassNode { name: class_name.to_string(), + attributes, is_struct, location, }); @@ -75,3 +87,29 @@ extern "C" fn visit_children( } CXChildVisit_Recurse } + +extern "C" fn visit_class_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_CXXMethod || cursor_kind == CXCursor_FunctionTemplate { + let attributes = &mut *(data as *mut ClassAttributes); + attributes.methods_count += 1; + return CXChildVisit_Continue; + } + + if cursor_kind == CXCursor_FieldDecl { + let attributes = &mut *(data as *mut ClassAttributes); + attributes.fields_count += 1; + return CXChildVisit_Continue; + } + } + CXChildVisit_Recurse +}