Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions ext/rubydex/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,24 @@ static VALUE rdxr_graph_set_encoding(VALUE self, VALUE encoding) {
return Qnil;
}

// Graph#without_resolution=: (Boolean) -> void
// Configures the graph to skip accumulating resolution work items
static VALUE rdxr_graph_set_without_resolution(VALUE self, VALUE without_resolution) {
void *graph;
TypedData_Get_Struct(self, void *, &graph_type, graph);
rdx_graph_set_without_resolution(graph, RTEST(without_resolution));
return Qnil;
}

// Graph#without_resolution?: () -> Boolean
// Returns whether the graph is configured to skip accumulating resolution work items
static VALUE rdxr_graph_without_resolution(VALUE self) {
void *graph;
TypedData_Get_Struct(self, void *, &graph_type, graph);

return rdx_graph_without_resolution(graph) ? Qtrue : Qfalse;
}

// Graph#resolve_constant: (String, Array[String]) -> Declaration?
// Runs the resolver on a single constant reference to determine what it points to
static VALUE rdxr_graph_resolve_constant(VALUE self, VALUE const_name, VALUE nesting) {
Expand Down Expand Up @@ -498,6 +516,8 @@ void rdxi_initialize_graph(VALUE mRubydex) {
rb_define_method(cGraph, "[]", rdxr_graph_aref, 1);
rb_define_method(cGraph, "search", rdxr_graph_search, 1);
rb_define_method(cGraph, "encoding=", rdxr_graph_set_encoding, 1);
rb_define_method(cGraph, "without_resolution=", rdxr_graph_set_without_resolution, 1);
rb_define_method(cGraph, "without_resolution?", rdxr_graph_without_resolution, 0);
rb_define_method(cGraph, "resolve_require_path", rdxr_graph_resolve_require_path, 2);
rb_define_method(cGraph, "require_paths", rdxr_graph_require_paths, 1);
}
5 changes: 3 additions & 2 deletions lib/rubydex/graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ class Graph
#: String
attr_accessor :workspace_path

#: (?workspace_path: String) -> void
def initialize(workspace_path: Dir.pwd)
#: (?workspace_path: String, ?without_resolution: bool) -> void
def initialize(workspace_path: Dir.pwd, without_resolution: false)
@workspace_path = workspace_path
self.without_resolution = without_resolution
end

# Index all files and dependencies of the workspace that exists in `@workspace_path`
Expand Down
2 changes: 1 addition & 1 deletion rust/rubydex-mcp/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl RubydexServer {
}

let mut resolver = rubydex::resolution::Resolver::new(&mut graph);
resolver.resolve_all();
resolver.resolve();

eprintln!(
"Rubydex indexed {} files, {} declarations",
Expand Down
26 changes: 24 additions & 2 deletions rust/rubydex-sys/src/graph_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ pub unsafe extern "C" fn rdx_graph_delete_document(pointer: GraphPointer, uri: *
pub extern "C" fn rdx_graph_resolve(pointer: GraphPointer) {
with_mut_graph(pointer, |graph| {
let mut resolver = Resolver::new(graph);
resolver.resolve_all();
resolver.resolve();
});
}

Expand Down Expand Up @@ -221,6 +221,28 @@ pub unsafe extern "C" fn rdx_graph_set_encoding(pointer: GraphPointer, encoding_
true
}

/// Configures the graph to skip accumulating resolution work items.
///
/// # Safety
///
/// Expects the graph pointer to be valid
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rdx_graph_set_without_resolution(pointer: GraphPointer, without_resolution: bool) {
with_mut_graph(pointer, |graph| {
graph.set_without_resolution(without_resolution);
});
}

/// Returns whether the graph is configured to skip accumulating resolution work items.
///
/// # Safety
///
/// Expects the graph pointer to be valid
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rdx_graph_without_resolution(pointer: GraphPointer) -> bool {
with_graph(pointer, |graph| graph.without_resolution())
}

/// Creates a new iterator over declaration IDs by snapshotting the current set of IDs.
///
/// # Safety
Expand Down Expand Up @@ -577,7 +599,7 @@ mod tests {
let mut graph = Graph::new();
graph.update(indexer.local_graph());
let mut resolver = Resolver::new(&mut graph);
resolver.resolve_all();
resolver.resolve();

assert_eq!(
1,
Expand Down
1 change: 1 addition & 0 deletions rust/rubydex/src/indexing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub fn index_source(graph: &mut Graph, uri: &str, source: &str, language_id: &La
}

/// Indexes the given paths, reading the content from disk and populating the given `Graph` instance.
/// Pending work is accumulated on the graph; drained by the resolver.
///
/// # Panics
///
Expand Down
28 changes: 28 additions & 0 deletions rust/rubydex/src/indexing/local_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::collections::hash_map::Entry;
use crate::diagnostic::{Diagnostic, Rule};
use crate::model::definitions::Definition;
use crate::model::document::Document;
use crate::model::graph::NameDependent;
use crate::model::identity_maps::IdentityHashMap;
use crate::model::ids::{DefinitionId, NameId, ReferenceId, StringId, UriId};
use crate::model::name::{Name, NameRef};
Expand All @@ -18,6 +19,7 @@ type LocalGraphParts = (
IdentityHashMap<NameId, NameRef>,
IdentityHashMap<ReferenceId, ConstantReference>,
IdentityHashMap<ReferenceId, MethodRef>,
IdentityHashMap<NameId, Vec<NameDependent>>,
);

#[derive(Debug)]
Expand All @@ -29,6 +31,7 @@ pub struct LocalGraph {
names: IdentityHashMap<NameId, NameRef>,
constant_references: IdentityHashMap<ReferenceId, ConstantReference>,
method_references: IdentityHashMap<ReferenceId, MethodRef>,
name_dependents: IdentityHashMap<NameId, Vec<NameDependent>>,
}

impl LocalGraph {
Expand All @@ -42,6 +45,7 @@ impl LocalGraph {
names: IdentityHashMap::default(),
constant_references: IdentityHashMap::default(),
method_references: IdentityHashMap::default(),
name_dependents: IdentityHashMap::default(),
}
}

Expand Down Expand Up @@ -70,6 +74,13 @@ impl LocalGraph {
pub fn add_definition(&mut self, definition: Definition) -> DefinitionId {
let definition_id = definition.id();

if let Some(name_id) = definition.name_id() {
self.name_dependents
.entry(*name_id)
.or_default()
.push(NameDependent::Definition(definition_id));
}

if self.definitions.insert(definition_id, definition).is_some() {
debug_assert!(false, "DefinitionId collision in local graph");
}
Expand Down Expand Up @@ -110,6 +121,8 @@ impl LocalGraph {

pub fn add_name(&mut self, name: Name) -> NameId {
let name_id = name.id();
let nesting_id = name.nesting().as_ref().copied();
let parent_scope_id = name.parent_scope().as_ref().copied();

match self.names.entry(name_id) {
Entry::Occupied(mut entry) => {
Expand All @@ -118,6 +131,15 @@ impl LocalGraph {
}
Entry::Vacant(entry) => {
entry.insert(NameRef::Unresolved(Box::new(name)));

// Track nesting and parent_scope dependents for new names
let dep = NameDependent::Name(name_id);
for dep_owner_id in [nesting_id, parent_scope_id].into_iter().flatten() {
let deps = self.name_dependents.entry(dep_owner_id).or_default();
if !deps.contains(&dep) {
deps.push(dep);
}
}
}
}

Expand All @@ -134,6 +156,11 @@ impl LocalGraph {
pub fn add_constant_reference(&mut self, reference: ConstantReference) -> ReferenceId {
let reference_id = reference.id();

self.name_dependents
.entry(*reference.name_id())
.or_default()
.push(NameDependent::Reference(reference_id));

if self.constant_references.insert(reference_id, reference).is_some() {
debug_assert!(false, "ReferenceId collision in local graph");
}
Expand Down Expand Up @@ -184,6 +211,7 @@ impl LocalGraph {
self.names,
self.constant_references,
self.method_references,
self.name_dependents,
)
}
}
2 changes: 1 addition & 1 deletion rust/rubydex/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ fn main() {

time_it!(resolution, {
let mut resolver = Resolver::new(&mut graph);
resolver.resolve_all();
resolver.resolve();
});

if let Some(StopAfter::Resolution) = args.stop_after {
Expand Down
4 changes: 4 additions & 0 deletions rust/rubydex/src/model/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,10 @@ impl Namespace {
all_namespaces!(self, it => it.member(str_id))
}

pub fn remove_member(&mut self, str_id: &StringId) -> Option<DeclarationId> {
all_namespaces!(self, it => it.remove_member(str_id))
}

#[must_use]
pub fn singleton_class(&self) -> Option<&DeclarationId> {
all_namespaces!(self, it => it.singleton_class_id())
Expand Down
Loading
Loading