rubydex 0.2.4-aarch64-linux → 0.2.6-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -16
- data/THIRD_PARTY_LICENSES.html +6 -6
- data/exe/rubydex_mcp +17 -0
- data/ext/rubydex/definition.c +89 -2
- data/ext/rubydex/document.c +36 -0
- data/ext/rubydex/extconf.rb +8 -0
- data/ext/rubydex/graph.c +32 -18
- data/ext/rubydex/handle.h +21 -5
- data/lib/rubydex/3.2/rubydex.so +0 -0
- data/lib/rubydex/3.3/rubydex.so +0 -0
- data/lib/rubydex/3.4/rubydex.so +0 -0
- data/lib/rubydex/4.0/rubydex.so +0 -0
- data/lib/rubydex/bin/rubydex_mcp +0 -0
- data/lib/rubydex/declaration.rb +3 -3
- data/lib/rubydex/errors.rb +8 -0
- data/lib/rubydex/graph.rb +3 -1
- data/lib/rubydex/librubydex_sys.so +0 -0
- data/lib/rubydex/location.rb +24 -0
- data/lib/rubydex/version.rb +1 -1
- data/lib/rubydex.rb +1 -0
- data/rbi/rubydex.rbi +37 -14
- data/rust/Cargo.lock +3 -3
- data/rust/rubydex/Cargo.toml +7 -1
- data/rust/rubydex/src/dot.rs +609 -0
- data/rust/rubydex/src/indexing/local_graph.rs +38 -0
- data/rust/rubydex/src/indexing/rbs_indexer.rs +19 -1
- data/rust/rubydex/src/indexing/ruby_indexer.rs +10 -0
- data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +5 -1
- data/rust/rubydex/src/indexing.rs +38 -12
- data/rust/rubydex/src/lib.rs +2 -1
- data/rust/rubydex/src/listing.rs +14 -3
- data/rust/rubydex/src/main.rs +35 -7
- data/rust/rubydex/src/model/built_in.rs +5 -2
- data/rust/rubydex/src/model/comment.rs +2 -0
- data/rust/rubydex/src/model/declaration.rs +1 -0
- data/rust/rubydex/src/model/definitions.rs +20 -19
- data/rust/rubydex/src/model/document.rs +2 -0
- data/rust/rubydex/src/model/encoding.rs +2 -0
- data/rust/rubydex/src/model/graph.rs +51 -13
- data/rust/rubydex/src/model/identity_maps.rs +3 -0
- data/rust/rubydex/src/model/ids.rs +27 -1
- data/rust/rubydex/src/model/keywords.rs +3 -0
- data/rust/rubydex/src/model/name.rs +2 -0
- data/rust/rubydex/src/model/string_ref.rs +2 -0
- data/rust/rubydex/src/model/visibility.rs +3 -0
- data/rust/rubydex/src/operation/applier.rs +520 -0
- data/rust/rubydex/src/operation/mod.rs +285 -0
- data/rust/rubydex/src/operation/printer.rs +260 -0
- data/rust/rubydex/src/operation/ruby_builder.rs +2919 -0
- data/rust/rubydex/src/query.rs +114 -33
- data/rust/rubydex/src/resolution.rs +22 -9
- data/rust/rubydex/src/resolution_tests.rs +349 -209
- data/rust/rubydex/src/test_utils/graph_test.rs +19 -4
- data/rust/rubydex/src/test_utils/local_graph_test.rs +7 -6
- data/rust/rubydex/tests/cli.rs +17 -61
- data/rust/rubydex-mcp/Cargo.toml +9 -3
- data/rust/rubydex-mcp/src/server.rs +5 -1
- data/rust/rubydex-sys/Cargo.toml +9 -2
- data/rust/rubydex-sys/src/definition_api.rs +96 -2
- data/rust/rubydex-sys/src/document_api.rs +28 -0
- data/rust/rubydex-sys/src/graph_api.rs +2 -4
- metadata +11 -4
- data/rust/rubydex/src/visualization/dot.rs +0 -192
- data/rust/rubydex/src/visualization.rs +0 -6
|
@@ -1,20 +1,34 @@
|
|
|
1
1
|
use super::normalize_indentation;
|
|
2
2
|
#[cfg(test)]
|
|
3
3
|
use crate::diagnostic::Rule;
|
|
4
|
-
use crate::indexing::{self, LanguageId};
|
|
4
|
+
use crate::indexing::{self, IndexerBackend, LanguageId};
|
|
5
5
|
use crate::model::graph::{Graph, NameDependent};
|
|
6
6
|
use crate::model::ids::{NameId, StringId};
|
|
7
7
|
use crate::resolution::Resolver;
|
|
8
8
|
|
|
9
|
-
#[derive(Default)]
|
|
10
9
|
pub struct GraphTest {
|
|
11
10
|
graph: Graph,
|
|
11
|
+
backend: IndexerBackend,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl Default for GraphTest {
|
|
15
|
+
fn default() -> Self {
|
|
16
|
+
Self::new()
|
|
17
|
+
}
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
impl GraphTest {
|
|
15
21
|
#[must_use]
|
|
16
22
|
pub fn new() -> Self {
|
|
17
|
-
Self
|
|
23
|
+
Self::new_with_backend(IndexerBackend::RubyIndexer)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#[must_use]
|
|
27
|
+
pub fn new_with_backend(backend: IndexerBackend) -> Self {
|
|
28
|
+
Self {
|
|
29
|
+
graph: Graph::new(),
|
|
30
|
+
backend,
|
|
31
|
+
}
|
|
18
32
|
}
|
|
19
33
|
|
|
20
34
|
#[must_use]
|
|
@@ -30,7 +44,8 @@ impl GraphTest {
|
|
|
30
44
|
/// Indexes a Ruby source
|
|
31
45
|
pub fn index_uri(&mut self, uri: &str, source: &str) {
|
|
32
46
|
let source = normalize_indentation(source);
|
|
33
|
-
indexing::
|
|
47
|
+
let local_graph = indexing::build_local_graph(uri.to_string(), &source, &LanguageId::Ruby, self.backend);
|
|
48
|
+
self.graph.consume_document_changes(local_graph);
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
/// Indexes an RBS source
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use super::normalize_indentation;
|
|
2
2
|
use crate::indexing::local_graph::LocalGraph;
|
|
3
3
|
use crate::indexing::rbs_indexer::RBSIndexer;
|
|
4
|
-
use crate::indexing::
|
|
4
|
+
use crate::indexing::{IndexerBackend, LanguageId, build_local_graph};
|
|
5
5
|
use crate::model::definitions::Definition;
|
|
6
6
|
use crate::model::graph::NameDependent;
|
|
7
7
|
use crate::model::ids::{NameId, StringId, UriId};
|
|
@@ -19,13 +19,14 @@ pub struct LocalGraphTest {
|
|
|
19
19
|
impl LocalGraphTest {
|
|
20
20
|
#[must_use]
|
|
21
21
|
pub fn new(uri: &str, source: &str) -> Self {
|
|
22
|
+
Self::new_with_backend(uri, source, IndexerBackend::RubyIndexer)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#[must_use]
|
|
26
|
+
pub fn new_with_backend(uri: &str, source: &str, backend: IndexerBackend) -> Self {
|
|
22
27
|
let uri = uri.to_string();
|
|
23
28
|
let source = normalize_indentation(source);
|
|
24
|
-
|
|
25
|
-
let mut indexer = RubyIndexer::new(uri.clone(), &source);
|
|
26
|
-
indexer.index();
|
|
27
|
-
let graph = indexer.local_graph();
|
|
28
|
-
|
|
29
|
+
let graph = build_local_graph(uri.clone(), &source, &LanguageId::Ruby, backend);
|
|
29
30
|
Self { uri, source, graph }
|
|
30
31
|
}
|
|
31
32
|
|
data/rust/rubydex/tests/cli.rs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
use assert_cmd::{assert::Assert, prelude::*};
|
|
2
2
|
use predicates::prelude::*;
|
|
3
|
-
use
|
|
4
|
-
use rubydex::test_utils::{normalize_indentation, with_context};
|
|
3
|
+
use rubydex::test_utils::with_context;
|
|
5
4
|
use std::process::Command;
|
|
6
5
|
|
|
7
6
|
fn rdx_cmd(args: &[&str]) -> Command {
|
|
@@ -21,7 +20,7 @@ fn prints_help() {
|
|
|
21
20
|
.stdout(predicate::str::contains("A Static Analysis Toolkit for Ruby"))
|
|
22
21
|
.stdout(predicate::str::contains("Usage:"))
|
|
23
22
|
.stdout(predicate::str::contains("--stats"))
|
|
24
|
-
.stdout(predicate::str::contains("--
|
|
23
|
+
.stdout(predicate::str::contains("--dot"))
|
|
25
24
|
.stdout(predicate::str::contains("--stop-after"));
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -68,68 +67,25 @@ fn prints_index_metrics() {
|
|
|
68
67
|
});
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
fn normalize_visualization_output(output: &str) -> String {
|
|
72
|
-
let def_re = Regex::new(r"def_-?[a-f0-9]+").unwrap();
|
|
73
|
-
let uri_re = Regex::new(r#"file://[^"]+/([^/"]+\.rb)"#).unwrap();
|
|
74
|
-
|
|
75
|
-
let normalized = def_re.replace_all(output, "def_<ID>");
|
|
76
|
-
uri_re.replace_all(&normalized, "file://<PATH>/$1").to_string()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
70
|
#[test]
|
|
80
|
-
fn
|
|
71
|
+
fn dot_flag() {
|
|
81
72
|
with_context(|context| {
|
|
82
73
|
context.write("simple.rb", "class SimpleClass\nend\n");
|
|
83
74
|
|
|
84
|
-
|
|
85
|
-
.
|
|
86
|
-
.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"Name:BasicObject" [label="BasicObject",shape=hexagon];
|
|
99
|
-
"Name:BasicObject" -> "def_<ID>" [dir=both];
|
|
100
|
-
"Name:Class" [label="Class",shape=hexagon];
|
|
101
|
-
"Name:Class" -> "def_<ID>" [dir=both];
|
|
102
|
-
"Name:Kernel" [label="Kernel",shape=hexagon];
|
|
103
|
-
"Name:Kernel" -> "def_<ID>" [dir=both];
|
|
104
|
-
"Name:Module" [label="Module",shape=hexagon];
|
|
105
|
-
"Name:Module" -> "def_<ID>" [dir=both];
|
|
106
|
-
"Name:Object" [label="Object",shape=hexagon];
|
|
107
|
-
"Name:Object" -> "def_<ID>" [dir=both];
|
|
108
|
-
"Name:SimpleClass" [label="SimpleClass",shape=hexagon];
|
|
109
|
-
"Name:SimpleClass" -> "def_<ID>" [dir=both];
|
|
110
|
-
|
|
111
|
-
"def_<ID>" [label="Class(BasicObject)",shape=ellipse];
|
|
112
|
-
"def_<ID>" [label="Class(Class)",shape=ellipse];
|
|
113
|
-
"def_<ID>" [label="Class(Module)",shape=ellipse];
|
|
114
|
-
"def_<ID>" [label="Class(Object)",shape=ellipse];
|
|
115
|
-
"def_<ID>" [label="Class(SimpleClass)",shape=ellipse];
|
|
116
|
-
"def_<ID>" [label="Module(Kernel)",shape=ellipse];
|
|
117
|
-
|
|
118
|
-
"file://<PATH>/simple.rb" [label="simple.rb",shape=box];
|
|
119
|
-
"def_<ID>" -> "file://<PATH>/simple.rb";
|
|
120
|
-
"rubydex:built-in" [label="rubydex:built-in",shape=box];
|
|
121
|
-
"def_<ID>" -> "rubydex:built-in";
|
|
122
|
-
"def_<ID>" -> "rubydex:built-in";
|
|
123
|
-
"def_<ID>" -> "rubydex:built-in";
|
|
124
|
-
"def_<ID>" -> "rubydex:built-in";
|
|
125
|
-
"def_<ID>" -> "rubydex:built-in";
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
"#
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
assert_eq!(normalized, expected);
|
|
75
|
+
rdx(&[context.absolute_path().to_str().unwrap(), "--dot"])
|
|
76
|
+
.success()
|
|
77
|
+
.stdout(predicate::str::contains("digraph rubydex"))
|
|
78
|
+
// Document node
|
|
79
|
+
.stdout(predicate::str::contains("Document"))
|
|
80
|
+
.stdout(predicate::str::contains("simple.rb"))
|
|
81
|
+
// Definition node
|
|
82
|
+
.stdout(predicate::str::contains("ClassDef"))
|
|
83
|
+
.stdout(predicate::str::contains("SimpleClass"))
|
|
84
|
+
// Declaration node
|
|
85
|
+
.stdout(predicate::str::contains("ClassDecl"))
|
|
86
|
+
// Edges
|
|
87
|
+
.stdout(predicate::str::contains("defines"))
|
|
88
|
+
.stdout(predicate::str::contains("declares"));
|
|
133
89
|
});
|
|
134
90
|
}
|
|
135
91
|
|
data/rust/rubydex-mcp/Cargo.toml
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "rubydex-mcp"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.6"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
rust-version = "1.89.0"
|
|
6
6
|
license = "MIT"
|
|
7
|
+
description = "MCP server exposing Rubydex semantic Ruby code intelligence tools."
|
|
8
|
+
homepage = "https://github.com/Shopify/rubydex"
|
|
9
|
+
repository = "https://github.com/Shopify/rubydex"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
keywords = ["ruby", "mcp", "static-analysis"]
|
|
12
|
+
categories = ["development-tools"]
|
|
7
13
|
|
|
8
14
|
[[bin]]
|
|
9
15
|
name = "rubydex_mcp"
|
|
10
16
|
path = "src/main.rs"
|
|
11
17
|
|
|
12
18
|
[dependencies]
|
|
13
|
-
rubydex = { path = "../rubydex" }
|
|
19
|
+
rubydex = { version = "0.2.6", path = "../rubydex" }
|
|
14
20
|
clap = { version = "4.5.16", features = ["derive"] }
|
|
15
21
|
rmcp = { version = "1.4", features = ["server", "macros", "transport-io", "schemars"] }
|
|
16
22
|
tokio = { version = "1", features = ["macros", "rt", "io-std"] }
|
|
@@ -20,7 +26,7 @@ schemars = "1"
|
|
|
20
26
|
url = "2"
|
|
21
27
|
|
|
22
28
|
[dev-dependencies]
|
|
23
|
-
rubydex = { path = "../rubydex", features = ["test_utils"] }
|
|
29
|
+
rubydex = { version = "0.2.6", path = "../rubydex", features = ["test_utils"] }
|
|
24
30
|
assert_cmd = "2.0"
|
|
25
31
|
serde_json = "1"
|
|
26
32
|
|
|
@@ -54,7 +54,11 @@ impl RubydexServer {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
let mut graph = Graph::new();
|
|
57
|
-
let errors = rubydex::indexing::index_files(
|
|
57
|
+
let errors = rubydex::indexing::index_files(
|
|
58
|
+
&mut graph,
|
|
59
|
+
file_paths,
|
|
60
|
+
rubydex::indexing::IndexerBackend::RubyIndexer,
|
|
61
|
+
);
|
|
58
62
|
for error in &errors {
|
|
59
63
|
eprintln!("Indexing error: {error}");
|
|
60
64
|
}
|
data/rust/rubydex-sys/Cargo.toml
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "rubydex-sys"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.6"
|
|
4
4
|
edition = "2024"
|
|
5
|
+
rust-version = "1.89.0"
|
|
5
6
|
license = "MIT"
|
|
7
|
+
description = "C FFI bindings for the Rubydex Ruby code indexing engine."
|
|
8
|
+
homepage = "https://github.com/Shopify/rubydex"
|
|
9
|
+
repository = "https://github.com/Shopify/rubydex"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
keywords = ["ruby", "ffi", "static-analysis"]
|
|
12
|
+
categories = ["development-tools", "external-ffi-bindings"]
|
|
6
13
|
|
|
7
14
|
[lib]
|
|
8
15
|
crate-type = ["cdylib", "staticlib"]
|
|
9
16
|
|
|
10
17
|
[dependencies]
|
|
11
|
-
rubydex = { path = "../rubydex" }
|
|
18
|
+
rubydex = { version = "0.2.6", path = "../rubydex" }
|
|
12
19
|
libc = "0.2.174"
|
|
13
20
|
url = "2.5.4"
|
|
14
21
|
line-index = "0.1.2"
|
|
@@ -7,6 +7,7 @@ use crate::reference_api::CConstantReference;
|
|
|
7
7
|
use libc::c_char;
|
|
8
8
|
use rubydex::model::definitions::{Definition, Mixin};
|
|
9
9
|
use rubydex::model::ids::DefinitionId;
|
|
10
|
+
use rubydex::query::AliasResolutionError;
|
|
10
11
|
use std::ffi::CString;
|
|
11
12
|
use std::ptr;
|
|
12
13
|
|
|
@@ -276,6 +277,30 @@ pub unsafe extern "C" fn rdx_definition_declaration(pointer: GraphPointer, defin
|
|
|
276
277
|
})
|
|
277
278
|
}
|
|
278
279
|
|
|
280
|
+
/// Returns the lexical nesting definition id for the given definition, or NULL if there is no lexical nesting.
|
|
281
|
+
/// Caller must free the returned pointer with `free_u64`.
|
|
282
|
+
///
|
|
283
|
+
/// # Safety
|
|
284
|
+
/// - `pointer` must be a valid pointer previously returned by `rdx_graph_new`.
|
|
285
|
+
/// - `definition_id` must be a valid definition id.
|
|
286
|
+
///
|
|
287
|
+
/// # Panics
|
|
288
|
+
/// This function will panic if the definition cannot be found.
|
|
289
|
+
#[unsafe(no_mangle)]
|
|
290
|
+
pub unsafe extern "C" fn rdx_definition_lexical_nesting_id(pointer: GraphPointer, definition_id: u64) -> *const u64 {
|
|
291
|
+
with_graph(pointer, |graph| {
|
|
292
|
+
let def_id = DefinitionId::new(definition_id);
|
|
293
|
+
let Some(defn) = graph.definitions().get(&def_id) else {
|
|
294
|
+
panic!("Definition not found: {definition_id:?}");
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
match defn.lexical_nesting_id() {
|
|
298
|
+
Some(lexical_nesting_id) => Box::into_raw(Box::new(**lexical_nesting_id)).cast_const(),
|
|
299
|
+
None => ptr::null(),
|
|
300
|
+
}
|
|
301
|
+
})
|
|
302
|
+
}
|
|
303
|
+
|
|
279
304
|
/// Creates a new iterator over definition IDs for a given declaration by snapshotting the current set of IDs.
|
|
280
305
|
///
|
|
281
306
|
/// # Panics
|
|
@@ -322,8 +347,8 @@ pub unsafe extern "C" fn rdx_definition_is_deprecated(pointer: GraphPointer, def
|
|
|
322
347
|
}
|
|
323
348
|
|
|
324
349
|
/// Returns a newly allocated `Location` for the name portion of a definition id.
|
|
325
|
-
/// For class, module,
|
|
326
|
-
/// the name (e.g., "Bar" in `class Foo::Bar`).
|
|
350
|
+
/// For class, module, singleton class, and method definitions, this returns the location of just
|
|
351
|
+
/// the name (e.g., "Bar" in `class Foo::Bar`, or "foo" in `def foo`).
|
|
327
352
|
/// For other definition types, returns NULL.
|
|
328
353
|
/// Caller must free the returned pointer with `rdx_location_free`.
|
|
329
354
|
///
|
|
@@ -467,3 +492,72 @@ pub unsafe extern "C" fn rdx_definition_mixins(pointer: GraphPointer, definition
|
|
|
467
492
|
MixinsIter::new(entries.into_boxed_slice())
|
|
468
493
|
})
|
|
469
494
|
}
|
|
495
|
+
|
|
496
|
+
/// Status of a `MethodAliasDefinition#target` resolution.
|
|
497
|
+
#[repr(u8)]
|
|
498
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
499
|
+
pub enum CMethodAliasResolution {
|
|
500
|
+
/// The alias chain resolved successfully; `declaration` is valid.
|
|
501
|
+
Resolved = 0,
|
|
502
|
+
/// The chain could not be resolved because the target name does not exist on the owner, or the owner itself was
|
|
503
|
+
/// never resolved. Treated as `nil` on the Ruby side.
|
|
504
|
+
NotFound = 1,
|
|
505
|
+
/// The alias chain forms a cycle. Surfaced as a `Rubydex::AliasCycleError` on the Ruby side.
|
|
506
|
+
Cycle = 2,
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
#[repr(C)]
|
|
510
|
+
#[derive(Debug)]
|
|
511
|
+
pub struct CMethodAliasTargetResult {
|
|
512
|
+
pub status: CMethodAliasResolution,
|
|
513
|
+
pub declaration: *const CDeclaration,
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/// Resolves a `MethodAliasDefinition` to its target method declaration via `query::follow_method_alias` and reports the
|
|
517
|
+
/// outcome as a tagged status. The `declaration` pointer is non-null only when `status == Resolved`; the caller is
|
|
518
|
+
/// responsible for freeing it with `free_c_declaration`.
|
|
519
|
+
///
|
|
520
|
+
/// # Safety
|
|
521
|
+
/// - `pointer` must be a valid pointer previously returned by `rdx_graph_new`.
|
|
522
|
+
/// - `definition_id` must be a valid definition id for a `MethodAliasDefinition`.
|
|
523
|
+
///
|
|
524
|
+
/// # Panics
|
|
525
|
+
/// Panics on graph inconsistencies (the definition is not a method alias, or the alias resolved to a non-method
|
|
526
|
+
/// declaration).
|
|
527
|
+
#[unsafe(no_mangle)]
|
|
528
|
+
pub unsafe extern "C" fn rdx_method_alias_definition_target(
|
|
529
|
+
pointer: GraphPointer,
|
|
530
|
+
definition_id: u64,
|
|
531
|
+
) -> CMethodAliasTargetResult {
|
|
532
|
+
with_graph(pointer, |graph| {
|
|
533
|
+
let def_id = DefinitionId::new(definition_id);
|
|
534
|
+
|
|
535
|
+
match rubydex::query::follow_method_alias(graph, def_id) {
|
|
536
|
+
Ok(target_id) => {
|
|
537
|
+
let target_decl = graph
|
|
538
|
+
.declarations()
|
|
539
|
+
.get(&target_id)
|
|
540
|
+
.expect("target declaration must exist");
|
|
541
|
+
let boxed = Box::new(CDeclaration::from_declaration(target_id, target_decl));
|
|
542
|
+
|
|
543
|
+
CMethodAliasTargetResult {
|
|
544
|
+
status: CMethodAliasResolution::Resolved,
|
|
545
|
+
declaration: Box::into_raw(boxed).cast_const(),
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
Err(AliasResolutionError::TargetNotFound | AliasResolutionError::UnresolvedOwner) => {
|
|
549
|
+
CMethodAliasTargetResult {
|
|
550
|
+
status: CMethodAliasResolution::NotFound,
|
|
551
|
+
declaration: ptr::null(),
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
Err(AliasResolutionError::Cycle) => CMethodAliasTargetResult {
|
|
555
|
+
status: CMethodAliasResolution::Cycle,
|
|
556
|
+
declaration: ptr::null(),
|
|
557
|
+
},
|
|
558
|
+
Err(err @ (AliasResolutionError::NotAnAlias | AliasResolutionError::TargetNotMethod)) => {
|
|
559
|
+
panic!("graph inconsistency in method alias resolution: {err:?}")
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
})
|
|
563
|
+
}
|
|
@@ -6,6 +6,7 @@ use std::ptr;
|
|
|
6
6
|
|
|
7
7
|
use crate::definition_api::{DefinitionsIter, rdx_definitions_iter_new_from_ids};
|
|
8
8
|
use crate::graph_api::{GraphPointer, with_graph};
|
|
9
|
+
use crate::reference_api::{CMethodReference, MethodReferencesIter};
|
|
9
10
|
use rubydex::model::ids::UriId;
|
|
10
11
|
|
|
11
12
|
#[derive(Debug)]
|
|
@@ -83,3 +84,30 @@ pub unsafe extern "C" fn rdx_document_definitions_iter_new(pointer: GraphPointer
|
|
|
83
84
|
}
|
|
84
85
|
})
|
|
85
86
|
}
|
|
87
|
+
|
|
88
|
+
/// Creates a new iterator over method reference IDs for a given document by snapshotting the current set of IDs.
|
|
89
|
+
///
|
|
90
|
+
/// # Safety
|
|
91
|
+
///
|
|
92
|
+
/// - `pointer` must be a valid `GraphPointer` previously returned by this crate.
|
|
93
|
+
/// - The returned pointer must be freed with `rdx_method_references_iter_free`.
|
|
94
|
+
#[unsafe(no_mangle)]
|
|
95
|
+
pub unsafe extern "C" fn rdx_document_method_references_iter_new(
|
|
96
|
+
pointer: GraphPointer,
|
|
97
|
+
uri_id: u64,
|
|
98
|
+
) -> *mut MethodReferencesIter {
|
|
99
|
+
with_graph(pointer, |graph| {
|
|
100
|
+
let uri_id = UriId::new(uri_id);
|
|
101
|
+
if let Some(doc) = graph.documents().get(&uri_id) {
|
|
102
|
+
let entries: Vec<_> = doc
|
|
103
|
+
.method_references()
|
|
104
|
+
.iter()
|
|
105
|
+
.map(|ref_id| CMethodReference { id: **ref_id })
|
|
106
|
+
.collect();
|
|
107
|
+
|
|
108
|
+
MethodReferencesIter::new(entries.into_boxed_slice())
|
|
109
|
+
} else {
|
|
110
|
+
MethodReferencesIter::new(Vec::<_>::new().into_boxed_slice())
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
}
|
|
@@ -233,7 +233,7 @@ pub unsafe extern "C" fn rdx_index_all(
|
|
|
233
233
|
|
|
234
234
|
with_mut_graph(pointer, |graph| {
|
|
235
235
|
let (file_paths, listing_errors) = listing::collect_file_paths(file_paths, graph.excluded_paths());
|
|
236
|
-
let indexing_errors = indexing::index_files(graph, file_paths);
|
|
236
|
+
let indexing_errors = indexing::index_files(graph, file_paths, indexing::IndexerBackend::RubyIndexer);
|
|
237
237
|
|
|
238
238
|
let all_errors: Vec<String> = listing_errors
|
|
239
239
|
.into_iter()
|
|
@@ -793,9 +793,7 @@ fn run_and_finalize_completion(
|
|
|
793
793
|
///
|
|
794
794
|
/// - `pointer` must be a valid `GraphPointer` previously returned by this crate.
|
|
795
795
|
/// - `nesting` must point to `nesting_count` valid, null-terminated UTF-8 strings.
|
|
796
|
-
/// - `self_receiver`
|
|
797
|
-
/// overrides the self-type (e.g., `"Foo::<Foo>"` for completion inside `def Foo.bar`), while
|
|
798
|
-
/// the lexical nesting still comes from `nesting`.
|
|
796
|
+
/// - `self_receiver` is the fully qualified name of the **type of `self`**
|
|
799
797
|
#[unsafe(no_mangle)]
|
|
800
798
|
pub unsafe extern "C" fn rdx_graph_complete_expression(
|
|
801
799
|
pointer: GraphPointer,
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubydex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.6
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Shopify
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A high-performance static analysis suite for Ruby, built in Rust with
|
|
14
14
|
Ruby APIs
|
|
@@ -16,6 +16,7 @@ email:
|
|
|
16
16
|
- ruby@shopify.com
|
|
17
17
|
executables:
|
|
18
18
|
- rdx
|
|
19
|
+
- rubydex_mcp
|
|
19
20
|
extensions: []
|
|
20
21
|
extra_rdoc_files: []
|
|
21
22
|
files:
|
|
@@ -23,6 +24,7 @@ files:
|
|
|
23
24
|
- README.md
|
|
24
25
|
- THIRD_PARTY_LICENSES.html
|
|
25
26
|
- exe/rdx
|
|
27
|
+
- exe/rubydex_mcp
|
|
26
28
|
- ext/rubydex/declaration.c
|
|
27
29
|
- ext/rubydex/declaration.h
|
|
28
30
|
- ext/rubydex/definition.c
|
|
@@ -49,9 +51,11 @@ files:
|
|
|
49
51
|
- lib/rubydex/3.3/rubydex.so
|
|
50
52
|
- lib/rubydex/3.4/rubydex.so
|
|
51
53
|
- lib/rubydex/4.0/rubydex.so
|
|
54
|
+
- lib/rubydex/bin/rubydex_mcp
|
|
52
55
|
- lib/rubydex/comment.rb
|
|
53
56
|
- lib/rubydex/declaration.rb
|
|
54
57
|
- lib/rubydex/diagnostic.rb
|
|
58
|
+
- lib/rubydex/errors.rb
|
|
55
59
|
- lib/rubydex/failures.rb
|
|
56
60
|
- lib/rubydex/graph.rb
|
|
57
61
|
- lib/rubydex/keyword.rb
|
|
@@ -90,6 +94,7 @@ files:
|
|
|
90
94
|
- rust/rubydex/Cargo.toml
|
|
91
95
|
- rust/rubydex/src/compile_assertions.rs
|
|
92
96
|
- rust/rubydex/src/diagnostic.rs
|
|
97
|
+
- rust/rubydex/src/dot.rs
|
|
93
98
|
- rust/rubydex/src/errors.rs
|
|
94
99
|
- rust/rubydex/src/indexing.rs
|
|
95
100
|
- rust/rubydex/src/indexing/local_graph.rs
|
|
@@ -118,6 +123,10 @@ files:
|
|
|
118
123
|
- rust/rubydex/src/model/string_ref.rs
|
|
119
124
|
- rust/rubydex/src/model/visibility.rs
|
|
120
125
|
- rust/rubydex/src/offset.rs
|
|
126
|
+
- rust/rubydex/src/operation/applier.rs
|
|
127
|
+
- rust/rubydex/src/operation/mod.rs
|
|
128
|
+
- rust/rubydex/src/operation/printer.rs
|
|
129
|
+
- rust/rubydex/src/operation/ruby_builder.rs
|
|
121
130
|
- rust/rubydex/src/position.rs
|
|
122
131
|
- rust/rubydex/src/query.rs
|
|
123
132
|
- rust/rubydex/src/resolution.rs
|
|
@@ -130,8 +139,6 @@ files:
|
|
|
130
139
|
- rust/rubydex/src/test_utils/context.rs
|
|
131
140
|
- rust/rubydex/src/test_utils/graph_test.rs
|
|
132
141
|
- rust/rubydex/src/test_utils/local_graph_test.rs
|
|
133
|
-
- rust/rubydex/src/visualization.rs
|
|
134
|
-
- rust/rubydex/src/visualization/dot.rs
|
|
135
142
|
- rust/rubydex/tests/cli.rs
|
|
136
143
|
- rust/rustfmt.toml
|
|
137
144
|
homepage: https://github.com/Shopify/rubydex
|