Skip to content

Commit bad2faa

Browse files
committed
feat: Support query union name and location in source code
1 parent 4c939d4 commit bad2faa

File tree

5 files changed

+156
-0
lines changed

5 files changed

+156
-0
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,22 @@ SELECT * FROM globals WHERE is_volatile
8383

8484
---
8585

86+
<details>
87+
88+
<summary>Unions table</summary>
89+
90+
| Name | Type | Description |
91+
| ------ | ------- | ----------------------- |
92+
| name | Text | Union name |
93+
| file | Text | File path |
94+
| line | Integer | Line at the file path |
95+
| column | Integer | Column at the file path |
96+
| offset | Integer | Offset at the file path |
97+
98+
</details>
99+
100+
---
101+
86102
<details>
87103

88104
<summary>Functions table</summary>

src/data_provider.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::visitor::class;
1313
use crate::visitor::enumeration;
1414
use crate::visitor::function;
1515
use crate::visitor::global;
16+
use crate::visitor::unions;
1617
pub struct ClangAstDataProvider {
1718
pub paths: Vec<String>,
1819
}
@@ -69,6 +70,7 @@ fn select_clang_ast_objects(
6970
match table.as_str() {
7071
"classes" => select_classes(env, path, fields_names, titles, fields_values),
7172
"enums" => select_enumss(env, path, fields_names, titles, fields_values),
73+
"unions" => select_unions(env, path, fields_names, titles, fields_values),
7274
"functions" => select_functions(env, path, fields_names, titles, fields_values),
7375
"globals" => select_variables(env, path, fields_names, titles, fields_values),
7476
_ => select_values(env, titles, fields_values),
@@ -245,6 +247,70 @@ fn select_enumss(
245247
Ok(Group { rows })
246248
}
247249

250+
fn select_unions(
251+
env: &mut Environment,
252+
path: &str,
253+
fields_names: &[String],
254+
titles: &[String],
255+
fields_values: &[Box<dyn Expression>],
256+
) -> Result<Group, String> {
257+
let mut rows: Vec<Row> = vec![];
258+
259+
let names_len = fields_names.len() as i64;
260+
let values_len = fields_values.len() as i64;
261+
let padding = names_len - values_len;
262+
263+
let ast_unions = unions::select_clang_unions(path);
264+
for union_node in ast_unions.iter() {
265+
let mut values: Vec<Value> = Vec::with_capacity(fields_names.len());
266+
267+
for index in 0..names_len {
268+
let field_name = &fields_names[index as usize];
269+
270+
if (index - padding) >= 0 {
271+
let value = &fields_values[(index - padding) as usize];
272+
if value.as_any().downcast_ref::<SymbolExpression>().is_none() {
273+
let evaluated = evaluate_expression(env, value, titles, &values)?;
274+
values.push(evaluated);
275+
continue;
276+
}
277+
}
278+
279+
if field_name == "name" {
280+
values.push(Value::Text(union_node.name.to_owned()));
281+
continue;
282+
}
283+
284+
if field_name == "file" {
285+
values.push(Value::Text(union_node.location.file.to_string()));
286+
continue;
287+
}
288+
289+
if field_name == "line" {
290+
values.push(Value::Integer(union_node.location.line.into()));
291+
continue;
292+
}
293+
294+
if field_name == "column" {
295+
values.push(Value::Integer(union_node.location.column.into()));
296+
continue;
297+
}
298+
299+
if field_name == "offset" {
300+
values.push(Value::Integer(union_node.location.offset.into()));
301+
continue;
302+
}
303+
304+
values.push(Value::Null);
305+
}
306+
307+
let row = Row { values };
308+
rows.push(row);
309+
}
310+
311+
Ok(Group { rows })
312+
}
313+
248314
fn select_functions(
249315
env: &mut Environment,
250316
path: &str,

src/schema.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ pub fn tables_fields_names() -> &'static HashMap<&'static str, Vec<&'static str>
6969
"name",
7070
"constants_count",
7171
"type_literal",
72+
"file",
7273
"line",
7374
"column",
7475
"offset",
7576
],
7677
);
78+
map.insert("unions", vec!["name", "file", "line", "column", "offset"]);
7779
map.insert(
7880
"functions",
7981
vec![

src/visitor/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pub mod enumeration;
33
pub mod function;
44
pub mod global;
55
pub mod location;
6+
pub mod unions;

src/visitor/unions.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
extern crate clang_sys;
2+
3+
use clang_sys::*;
4+
use std::ffi::c_char;
5+
use std::ffi::c_void;
6+
use std::ffi::CStr;
7+
use std::ptr;
8+
9+
use crate::visitor::location;
10+
pub struct UnionNode {
11+
pub name: String,
12+
pub location: location::SourceLocation,
13+
}
14+
15+
pub fn select_clang_unions(path: &str) -> Vec<UnionNode> {
16+
let mut unions: Vec<UnionNode> = Vec::new();
17+
let data = &mut unions as *mut Vec<UnionNode> as *mut c_void;
18+
19+
unsafe {
20+
let index = clang_createIndex(0, 0);
21+
let translation_unit: CXTranslationUnit = clang_parseTranslationUnit(
22+
index,
23+
path.as_ptr() as *const c_char,
24+
ptr::null_mut(),
25+
0,
26+
ptr::null_mut(),
27+
0,
28+
0,
29+
);
30+
31+
let cursor = clang_getTranslationUnitCursor(translation_unit);
32+
clang_visitChildren(cursor, visit_union_declaration, data);
33+
34+
// Dispose the translation unit
35+
clang_disposeTranslationUnit(translation_unit);
36+
37+
// Dispose the index
38+
clang_disposeIndex(index);
39+
}
40+
41+
unions
42+
}
43+
44+
extern "C" fn visit_union_declaration(
45+
cursor: CXCursor,
46+
_parent: CXCursor,
47+
data: *mut c_void,
48+
) -> CXChildVisitResult {
49+
unsafe {
50+
if clang_Location_isFromMainFile(clang_getCursorLocation(cursor)) == 0 {
51+
return CXChildVisit_Continue;
52+
}
53+
54+
let cursor_kind = clang_getCursorKind(cursor);
55+
if cursor_kind == CXCursor_UnionDecl {
56+
let cursor_name = clang_getCursorSpelling(cursor);
57+
let union_name = CStr::from_ptr(clang_getCString(cursor_name)).to_string_lossy();
58+
let location = location::visit_source_location(cursor);
59+
60+
let unions: &mut Vec<UnionNode> = &mut *(data as *mut Vec<UnionNode>);
61+
unions.push(UnionNode {
62+
name: union_name.to_string(),
63+
location,
64+
});
65+
66+
clang_disposeString(cursor_name);
67+
return CXChildVisit_Continue;
68+
}
69+
}
70+
CXChildVisit_Recurse
71+
}

0 commit comments

Comments
 (0)