use crate::graph_api::{GraphPointer, with_graph};
use crate::location_api::{Location, create_location_for_uri_and_offset};
use libc::c_char;
use std::{ffi::CString, mem, ptr};
#[repr(C)]
pub struct DiagnosticEntry {
pub rule: *const c_char,
pub message: *const c_char,
pub location: *mut Location,
}
#[repr(C)]
pub struct DiagnosticArray {
pub items: *mut DiagnosticEntry,
pub len: usize,
}
impl DiagnosticArray {
fn from_vec(mut entries: Vec<DiagnosticEntry>) -> *mut DiagnosticArray {
let len = entries.len();
let ptr = entries.as_mut_ptr();
mem::forget(entries);
Box::into_raw(Box::new(DiagnosticArray { items: ptr, len }))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rdx_graph_diagnostics(pointer: GraphPointer) -> *mut DiagnosticArray {
with_graph(pointer, |graph| {
let entries = graph
.all_diagnostics()
.iter()
.map(|diagnostic| {
let document = graph.documents().get(diagnostic.uri_id()).unwrap();
let location = create_location_for_uri_and_offset(graph, document, diagnostic.offset());
DiagnosticEntry {
rule: CString::new(diagnostic.rule().to_string())
.unwrap()
.into_raw()
.cast_const(),
message: CString::new(diagnostic.message()).unwrap().into_raw().cast_const(),
location,
}
})
.collect::<Vec<DiagnosticEntry>>();
DiagnosticArray::from_vec(entries)
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rdx_diagnostics_free(ptr: *mut DiagnosticArray) {
if ptr.is_null() {
return;
}
let array = unsafe { Box::from_raw(ptr) };
if !array.items.is_null() && array.len > 0 {
let slice_ptr = ptr::slice_from_raw_parts_mut(array.items, array.len);
let mut boxed_slice: Box<[DiagnosticEntry]> = unsafe { Box::from_raw(slice_ptr) };
for entry in &mut *boxed_slice {
if !entry.rule.is_null() {
let _ = unsafe { CString::from_raw(entry.rule.cast_mut()) };
}
if !entry.message.is_null() {
let _ = unsafe { CString::from_raw(entry.message.cast_mut()) };
}
if !entry.location.is_null() {
unsafe { crate::location_api::rdx_location_free(entry.location) };
entry.location = ptr::null_mut();
}
}
}
}