Skip to content

Commit 2abe9e1

Browse files
committed
Make index_source language_id optional
1 parent 33e510e commit 2abe9e1

4 files changed

Lines changed: 106 additions & 22 deletions

File tree

ext/rubydex/graph.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,28 @@ static VALUE rdxr_graph_index_all(VALUE self, VALUE file_paths) {
8585
return array;
8686
}
8787

88-
// Indexes a single source string in memory, dispatching to the appropriate indexer based on language_id
88+
// Indexes a single source string in memory, dispatching to the appropriate indexer based on language_id.
8989
//
90-
// Graph#index_source: (String uri, String source, String language_id) -> void
91-
static VALUE rdxr_graph_index_source(VALUE self, VALUE uri, VALUE source, VALUE language_id) {
90+
// Graph#index_source: (String uri, String source, ?String language_id) -> void
91+
static VALUE rdxr_graph_index_source(int argc, VALUE *argv, VALUE self) {
92+
VALUE uri, source, language_id;
93+
rb_scan_args(argc, argv, "21", &uri, &source, &language_id);
94+
9295
Check_Type(uri, T_STRING);
9396
Check_Type(source, T_STRING);
94-
Check_Type(language_id, T_STRING);
9597

9698
void *graph;
9799
TypedData_Get_Struct(self, void *, &graph_type, graph);
98100

99101
const char *uri_str = StringValueCStr(uri);
100-
const char *language_id_str = StringValueCStr(language_id);
102+
const char *language_id_str = NULL;
103+
if (NIL_P(language_id)) {
104+
language_id_str = NULL;
105+
} else {
106+
Check_Type(language_id, T_STRING);
107+
language_id_str = StringValueCStr(language_id);
108+
}
109+
101110
const char *source_str = RSTRING_PTR(source);
102111
size_t source_len = RSTRING_LEN(source);
103112

@@ -746,7 +755,7 @@ void rdxi_initialize_graph(VALUE moduleRubydex) {
746755

747756
rb_define_alloc_func(cGraph, rdxr_graph_alloc);
748757
rb_define_method(cGraph, "index_all", rdxr_graph_index_all, 1);
749-
rb_define_method(cGraph, "index_source", rdxr_graph_index_source, 3);
758+
rb_define_method(cGraph, "index_source", rdxr_graph_index_source, -1);
750759
rb_define_method(cGraph, "document", rdxr_graph_document, 1);
751760
rb_define_method(cGraph, "delete_document", rdxr_graph_delete_document, 1);
752761
rb_define_method(cGraph, "resolve", rdxr_graph_resolve, 0);

rbi/rubydex.rbi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,8 @@ class Rubydex::Graph
298298
sig { params(file_paths: T::Array[String]).returns(T::Array[String]) }
299299
def index_all(file_paths); end
300300

301-
sig { params(uri: String, source: String, language_id: String).void }
302-
def index_source(uri, source, language_id); end
301+
sig { params(uri: String, source: String, language_id: T.nilable(String)).void }
302+
def index_source(uri, source, language_id = nil); end
303303

304304
# Index all files and dependencies of the workspace that exists in `@workspace_path`
305305
sig { returns(T::Array[String]) }

rust/rubydex-sys/src/graph_api.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rubydex::query::{CompletionCandidate, CompletionContext, CompletionReceiver}
1818
use rubydex::resolution::Resolver;
1919
use rubydex::{indexing, integrity, listing, query};
2020
use std::ffi::CString;
21-
use std::path::PathBuf;
21+
use std::path::{Path, PathBuf};
2222
use std::{mem, ptr};
2323

2424
pub type GraphPointer = *mut c_void;
@@ -562,13 +562,20 @@ pub enum IndexSourceResult {
562562
UnsupportedLanguageId = 4,
563563
}
564564

565-
/// Indexes source code from memory using the specified language. Returns `IndexSourceResult::Success` on success
566-
/// or a specific error variant if string conversion or language lookup fails.
565+
fn language_from_uri(uri: &str) -> LanguageId {
566+
let extension = Path::new(uri).extension();
567+
extension.map_or(LanguageId::Ruby, LanguageId::from)
568+
}
569+
570+
/// Indexes source code from memory using the specified language. If `language_id` is null, infers the language from
571+
/// the URI using the same default as file indexing. Returns `IndexSourceResult::Success` on success or a specific error
572+
/// variant if string conversion or language lookup fails.
567573
///
568574
/// # Safety
569575
///
570576
/// - `pointer` must be a valid `GraphPointer` previously returned by this crate.
571-
/// - `uri` and `language_id` must be valid, null-terminated UTF-8 strings.
577+
/// - `uri` must be a valid, null-terminated UTF-8 string.
578+
/// - `language_id` must be either null or a valid, null-terminated UTF-8 string.
572579
/// - `source` must point to a valid UTF-8 byte buffer of at least `source_len` bytes.
573580
/// It may contain null bytes.
574581
#[unsafe(no_mangle)]
@@ -588,12 +595,18 @@ pub unsafe extern "C" fn rdx_index_source(
588595
return IndexSourceResult::InvalidSource;
589596
};
590597

591-
let Ok(language_id_str) = (unsafe { utils::convert_char_ptr_to_string(language_id) }) else {
592-
return IndexSourceResult::InvalidLanguageId;
593-
};
598+
let language = if language_id.is_null() {
599+
language_from_uri(&uri_str)
600+
} else {
601+
let Ok(language_id_str) = (unsafe { utils::convert_char_ptr_to_string(language_id) }) else {
602+
return IndexSourceResult::InvalidLanguageId;
603+
};
604+
605+
let Ok(language) = LanguageId::from_language_id(&language_id_str) else {
606+
return IndexSourceResult::UnsupportedLanguageId;
607+
};
594608

595-
let Ok(language) = LanguageId::from_language_id(&language_id_str) else {
596-
return IndexSourceResult::UnsupportedLanguageId;
609+
language
597610
};
598611

599612
with_mut_graph(pointer, |graph| {

test/graph_test.rb

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -529,18 +529,80 @@ def test_delete_uri_with_invalid_argument
529529

530530
def test_index_source_with_ruby
531531
graph = Rubydex::Graph.new
532-
graph.index_source("file:///foo.rb", "class Foo; end", "ruby")
532+
graph.index_source("file:///foo.rb", <<~RUBY, "ruby")
533+
class Foo
534+
def bar; end
535+
end
536+
RUBY
533537
graph.resolve
534538

535-
assert_equal(2, graph.documents.count)
536-
refute_nil(graph["Foo"])
539+
assert_empty(graph.diagnostics)
540+
assert_equal("Foo#bar()", graph["Foo#bar()"].name)
541+
end
542+
543+
def test_index_source_infers_ruby_language_id_when_omitted
544+
graph = Rubydex::Graph.new
545+
graph.index_source("file:///foo.rake", <<~RUBY)
546+
class Foo
547+
def bar; end
548+
end
549+
RUBY
550+
graph.resolve
551+
552+
assert_empty(graph.diagnostics)
553+
assert_equal("Foo#bar()", graph["Foo#bar()"].name)
554+
end
555+
556+
def test_index_source_infers_ruby_language_id_when_nil
557+
graph = Rubydex::Graph.new
558+
graph.index_source("untitled:Untitled-1", <<~RUBY, nil)
559+
class Foo
560+
def bar; end
561+
end
562+
RUBY
563+
graph.resolve
564+
565+
assert_empty(graph.diagnostics)
566+
assert_equal("Foo#bar()", graph["Foo#bar()"].name)
537567
end
538568

539569
def test_index_source_with_rbs
540570
graph = Rubydex::Graph.new
541-
graph.index_source("file:///foo.rbs", "class Foo\nend", "rbs")
571+
graph.index_source("file:///foo.rbs", <<~RBS, "rbs")
572+
class Foo
573+
def bar: () -> void
574+
end
575+
RBS
576+
graph.resolve
542577

543-
assert_equal(2, graph.documents.count)
578+
assert_empty(graph.diagnostics)
579+
assert_equal("Foo#bar()", graph["Foo#bar()"].name)
580+
end
581+
582+
def test_index_source_keeps_explicit_rbs_language_id_override
583+
graph = Rubydex::Graph.new
584+
graph.index_source("file:///foo.rb", <<~RBS, "rbs")
585+
class Foo
586+
def bar: () -> void
587+
end
588+
RBS
589+
graph.resolve
590+
591+
assert_empty(graph.diagnostics)
592+
assert_equal("Foo#bar()", graph["Foo#bar()"].name)
593+
end
594+
595+
def test_index_source_infers_rbs_language_id_when_omitted
596+
graph = Rubydex::Graph.new
597+
graph.index_source("file:///foo.rbs", <<~RBS)
598+
class Foo
599+
def bar: () -> void
600+
end
601+
RBS
602+
graph.resolve
603+
604+
assert_empty(graph.diagnostics)
605+
assert_equal("Foo#bar()", graph["Foo#bar()"].name)
544606
end
545607

546608
def test_index_source_with_unknown_language_id

0 commit comments

Comments
 (0)