Skip to content
Draft
26 changes: 19 additions & 7 deletions ext/rubydex/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "reference.h"
#include "ruby/internal/globals.h"
#include "rustbindings.h"
#include "index_result.h"
#include "utils.h"

static VALUE cGraph;
Expand All @@ -27,7 +28,7 @@ static VALUE rdxr_graph_alloc(VALUE klass) {
return TypedData_Wrap_Struct(klass, &graph_type, graph);
}

// Graph#index_all: (Array[String] file_paths) -> nil
// Graph#index_all: (Array[String] file_paths) -> IndexResult
// Raises IndexingError if anything failed during indexing
static VALUE rdxr_graph_index_all(VALUE self, VALUE file_paths) {
rdxi_check_array_of_strings(file_paths);
Expand All @@ -39,7 +40,9 @@ static VALUE rdxr_graph_index_all(VALUE self, VALUE file_paths) {
// Get the underying graph pointer and then invoke the Rust index all implementation
void *graph;
TypedData_Get_Struct(self, void *, &graph_type, graph);
const char *error_messages = rdx_index_all(graph, (const char **)converted_file_paths, length);

IndexResultPointer index_result = NULL;
const char *error_messages = rdx_index_all(graph, (const char **)converted_file_paths, length, &index_result);

// Free the converted file paths and allow the GC to collect them
for (size_t i = 0; i < length; i++) {
Expand All @@ -55,7 +58,7 @@ static VALUE rdxr_graph_index_all(VALUE self, VALUE file_paths) {
rb_raise(eIndexingError, "%s", StringValueCStr(error_string));
}

return Qnil;
return TypedData_Wrap_Struct(cIndexResult, &index_result_type, index_result);
}

// Size function for the declarations enumerator
Expand Down Expand Up @@ -272,12 +275,21 @@ static VALUE rdxr_graph_method_references(VALUE self) {
return self;
}

// Graph#resolve: () -> self
// Graph#resolve: (IndexResult?) -> self
// Runs the resolver to compute declarations and ownership
static VALUE rdxr_graph_resolve(VALUE self) {
static VALUE rdxr_graph_resolve(int argc, VALUE *argv, VALUE self) {
VALUE units_obj;
rb_scan_args(argc, argv, "01", &units_obj);

void *graph;
TypedData_Get_Struct(self, void *, &graph_type, graph);
rdx_graph_resolve(graph);

IndexResultPointer index_result = NULL;
if (!NIL_P(units_obj)) {
TypedData_Get_Struct(units_obj, void *, &index_result_type, index_result);
}

rdx_graph_resolve(graph, index_result);
return self;
}

Expand Down Expand Up @@ -398,7 +410,7 @@ void rdxi_initialize_graph(VALUE mRubydex) {
cGraph = rb_define_class_under(mRubydex, "Graph", rb_cObject);
rb_define_alloc_func(cGraph, rdxr_graph_alloc);
rb_define_method(cGraph, "index_all", rdxr_graph_index_all, 1);
rb_define_method(cGraph, "resolve", rdxr_graph_resolve, 0);
rb_define_method(cGraph, "resolve", rdxr_graph_resolve, -1);
rb_define_method(cGraph, "resolve_constant", rdxr_graph_resolve_constant, 2);
rb_define_method(cGraph, "declarations", rdxr_graph_declarations, 0);
rb_define_method(cGraph, "documents", rdxr_graph_documents, 0);
Expand Down
33 changes: 33 additions & 0 deletions ext/rubydex/index_result.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "index_result.h"
#include "rustbindings.h"

VALUE cIndexResult;

static void index_result_free(void *ptr) {
if (ptr) {
rdx_index_result_free(ptr);
}
}

const rb_data_type_t index_result_type = {"IndexResult", {0, index_result_free, 0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY};

// IndexResult#definition_ids_length -> Integer
static VALUE rdxr_index_result_definition_ids_length(VALUE self) {
void *index_result;
TypedData_Get_Struct(self, void *, &index_result_type, index_result);
return SIZET2NUM(rdx_index_result_definition_ids_len(index_result));
}

// IndexResult#reference_ids_length -> Integer
static VALUE rdxr_index_result_reference_ids_length(VALUE self) {
void *index_result;
TypedData_Get_Struct(self, void *, &index_result_type, index_result);
return SIZET2NUM(rdx_index_result_reference_ids_len(index_result));
}

void rdxi_initialize_index_result(VALUE mRubydex) {
cIndexResult = rb_define_class_under(mRubydex, "IndexResult", rb_cObject);
rb_undef_alloc_func(cIndexResult);
rb_define_method(cIndexResult, "definition_ids_length", rdxr_index_result_definition_ids_length, 0);
rb_define_method(cIndexResult, "reference_ids_length", rdxr_index_result_reference_ids_length, 0);
}
13 changes: 13 additions & 0 deletions ext/rubydex/index_result.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef INDEX_RESULT_H
#define INDEX_RESULT_H

#include "ruby.h"

typedef void *IndexResultPointer;

extern VALUE cIndexResult;
extern const rb_data_type_t index_result_type;

void rdxi_initialize_index_result(VALUE mRubydex);

#endif
2 changes: 2 additions & 0 deletions ext/rubydex/rubydex.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
#include "graph.h"
#include "location.h"
#include "reference.h"
#include "index_result.h"

VALUE mRubydex;

void Init_rubydex(void) {
rb_ext_ractor_safe(true);

mRubydex = rb_define_module("Rubydex");
rdxi_initialize_index_result(mRubydex);
rdxi_initialize_graph(mRubydex);
rdxi_initialize_declaration(mRubydex);
rdxi_initialize_document(mRubydex);
Expand Down
24 changes: 19 additions & 5 deletions rust/rubydex-sys/src/graph_api.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
//! This file provides the C API for the Graph object

use crate::declaration_api::CDeclaration;
use crate::declaration_api::DeclarationsIter;
use crate::declaration_api::{CDeclaration, DeclarationsIter};
use crate::index_result_api::IndexResultPointer;
use crate::reference_api::{ReferenceKind, ReferencesIter};
use crate::{name_api, utils};
use libc::{c_char, c_void};
use rubydex::indexing::IndexResult;
use rubydex::model::encoding::Encoding;
use rubydex::model::graph::Graph;
use rubydex::model::ids::DeclarationId;
Expand Down Expand Up @@ -130,6 +131,7 @@ pub unsafe extern "C" fn rdx_index_all(
pointer: GraphPointer,
file_paths: *const *const c_char,
count: usize,
out_result: *mut IndexResultPointer,
) -> *const c_char {
let file_paths: Vec<String> = unsafe { utils::convert_double_pointer_to_vec(file_paths, count).unwrap() };
let (file_paths, errors) = listing::collect_file_paths(file_paths);
Expand All @@ -145,7 +147,7 @@ pub unsafe extern "C" fn rdx_index_all(
}

with_mut_graph(pointer, |graph| {
let errors = indexing::index_files(graph, file_paths);
let (result, errors) = indexing::index_files(graph, file_paths);

if !errors.is_empty() {
let error_messages = errors
Expand All @@ -157,16 +159,28 @@ pub unsafe extern "C" fn rdx_index_all(
return CString::new(error_messages).unwrap().into_raw().cast_const();
}

if !out_result.is_null() {
unsafe {
*out_result = Box::into_raw(Box::new(result)) as IndexResultPointer;
}
}

ptr::null()
})
}

/// Runs the resolver to compute declarations, ownership and related structures
#[unsafe(no_mangle)]
pub extern "C" fn rdx_graph_resolve(pointer: GraphPointer) {
pub extern "C" fn rdx_graph_resolve(pointer: GraphPointer, index_result: IndexResultPointer) {
with_mut_graph(pointer, |graph| {
let mut resolver = Resolver::new(graph);
resolver.resolve_all();

if index_result.is_null() {
resolver.resolve_all();
} else {
let result = unsafe { &*index_result.cast::<IndexResult>() };
resolver.resolve(&result.definition_ids, &result.reference_ids);
}
});
}

Expand Down
35 changes: 35 additions & 0 deletions rust/rubydex-sys/src/index_result_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use libc::c_void;
use rubydex::indexing::IndexResult;

pub type IndexResultPointer = *mut c_void;

#[unsafe(no_mangle)]
pub extern "C" fn rdx_index_result_free(pointer: IndexResultPointer) {
if pointer.is_null() {
return;
}

unsafe {
let _ = Box::from_raw(pointer.cast::<IndexResult>());
}
}

#[unsafe(no_mangle)]
pub extern "C" fn rdx_index_result_definition_ids_len(pointer: IndexResultPointer) -> usize {
if pointer.is_null() {
return 0;
}

let result = unsafe { &*pointer.cast::<IndexResult>() };
result.definition_ids.len()
}

#[unsafe(no_mangle)]
pub extern "C" fn rdx_index_result_reference_ids_len(pointer: IndexResultPointer) -> usize {
if pointer.is_null() {
return 0;
}

let result = unsafe { &*pointer.cast::<IndexResult>() };
result.reference_ids.len()
}
1 change: 1 addition & 0 deletions rust/rubydex-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod definition_api;
pub mod diagnostic_api;
pub mod document_api;
pub mod graph_api;
pub mod index_result_api;
pub mod location_api;
pub mod name_api;
pub mod reference_api;
Expand Down
Loading
Loading