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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -16
  3. data/THIRD_PARTY_LICENSES.html +6 -6
  4. data/exe/rubydex_mcp +17 -0
  5. data/ext/rubydex/definition.c +89 -2
  6. data/ext/rubydex/document.c +36 -0
  7. data/ext/rubydex/extconf.rb +8 -0
  8. data/ext/rubydex/graph.c +32 -18
  9. data/ext/rubydex/handle.h +21 -5
  10. data/lib/rubydex/3.2/rubydex.so +0 -0
  11. data/lib/rubydex/3.3/rubydex.so +0 -0
  12. data/lib/rubydex/3.4/rubydex.so +0 -0
  13. data/lib/rubydex/4.0/rubydex.so +0 -0
  14. data/lib/rubydex/bin/rubydex_mcp +0 -0
  15. data/lib/rubydex/declaration.rb +3 -3
  16. data/lib/rubydex/errors.rb +8 -0
  17. data/lib/rubydex/graph.rb +3 -1
  18. data/lib/rubydex/librubydex_sys.so +0 -0
  19. data/lib/rubydex/location.rb +24 -0
  20. data/lib/rubydex/version.rb +1 -1
  21. data/lib/rubydex.rb +1 -0
  22. data/rbi/rubydex.rbi +37 -14
  23. data/rust/Cargo.lock +3 -3
  24. data/rust/rubydex/Cargo.toml +7 -1
  25. data/rust/rubydex/src/dot.rs +609 -0
  26. data/rust/rubydex/src/indexing/local_graph.rs +38 -0
  27. data/rust/rubydex/src/indexing/rbs_indexer.rs +19 -1
  28. data/rust/rubydex/src/indexing/ruby_indexer.rs +10 -0
  29. data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +5 -1
  30. data/rust/rubydex/src/indexing.rs +38 -12
  31. data/rust/rubydex/src/lib.rs +2 -1
  32. data/rust/rubydex/src/listing.rs +14 -3
  33. data/rust/rubydex/src/main.rs +35 -7
  34. data/rust/rubydex/src/model/built_in.rs +5 -2
  35. data/rust/rubydex/src/model/comment.rs +2 -0
  36. data/rust/rubydex/src/model/declaration.rs +1 -0
  37. data/rust/rubydex/src/model/definitions.rs +20 -19
  38. data/rust/rubydex/src/model/document.rs +2 -0
  39. data/rust/rubydex/src/model/encoding.rs +2 -0
  40. data/rust/rubydex/src/model/graph.rs +51 -13
  41. data/rust/rubydex/src/model/identity_maps.rs +3 -0
  42. data/rust/rubydex/src/model/ids.rs +27 -1
  43. data/rust/rubydex/src/model/keywords.rs +3 -0
  44. data/rust/rubydex/src/model/name.rs +2 -0
  45. data/rust/rubydex/src/model/string_ref.rs +2 -0
  46. data/rust/rubydex/src/model/visibility.rs +3 -0
  47. data/rust/rubydex/src/operation/applier.rs +520 -0
  48. data/rust/rubydex/src/operation/mod.rs +285 -0
  49. data/rust/rubydex/src/operation/printer.rs +260 -0
  50. data/rust/rubydex/src/operation/ruby_builder.rs +2919 -0
  51. data/rust/rubydex/src/query.rs +114 -33
  52. data/rust/rubydex/src/resolution.rs +22 -9
  53. data/rust/rubydex/src/resolution_tests.rs +349 -209
  54. data/rust/rubydex/src/test_utils/graph_test.rs +19 -4
  55. data/rust/rubydex/src/test_utils/local_graph_test.rs +7 -6
  56. data/rust/rubydex/tests/cli.rs +17 -61
  57. data/rust/rubydex-mcp/Cargo.toml +9 -3
  58. data/rust/rubydex-mcp/src/server.rs +5 -1
  59. data/rust/rubydex-sys/Cargo.toml +9 -2
  60. data/rust/rubydex-sys/src/definition_api.rs +96 -2
  61. data/rust/rubydex-sys/src/document_api.rs +28 -0
  62. data/rust/rubydex-sys/src/graph_api.rs +2 -4
  63. metadata +11 -4
  64. data/rust/rubydex/src/visualization/dot.rs +0 -192
  65. data/rust/rubydex/src/visualization.rs +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49147264143f618ef7d2b5bbfa983e511b86123dc01548c2a4176e686a44b57e
4
- data.tar.gz: cbd51f1380330f85dde7861c7df96cbc1db4117458952c561164eef9c511901e
3
+ metadata.gz: f428a340913b09bd93ef62c2c150af6fee8513747d932c58605b0c262e533ad4
4
+ data.tar.gz: 78917993925bf6c11911a869f8ff6cc0ec27097b03244797a1e54422910ab471
5
5
  SHA512:
6
- metadata.gz: 5daa009adaef78d504f2710aac72ec36875a3a7ae169048b36e7220d984ddaf7dd562431a460a44b95530bb030a341887ccf300d14646051f722ba0cc941e9bb
7
- data.tar.gz: adf4c9a9faf405356b64e6de927a7aa4b8499164c9cf48918683b45ab0e7825668f5505d50e0b29305292bae3db511ae6ffb6ab2e96628c1b1ecdc2076fb8b3b
6
+ metadata.gz: 4b47ac60c6a4920bd85b99154545acf82cd57a2036dd748e181159a286474643def1151f13fbdae99d15244ab89576c769d0a713e42a6f1e667da5a26052cc66
7
+ data.tar.gz: e3a5203e261885c70a7240e0ee8a87ce8412525015c330a980c4d715e9cb6d333405cab81c4c83d0ef01112bd68d858c71e9f948fd29404b30972ae661bc8b0a
data/README.md CHANGED
@@ -84,30 +84,31 @@ like Claude to semantically query your Ruby codebase.
84
84
 
85
85
  ### Setup
86
86
 
87
- 1. Install the binary:
87
+ 1. Add Rubydex to the Ruby project you want to index:
88
+ ```ruby
89
+ gem "rubydex"
90
+ ```
91
+
92
+ 2. Install the bundle:
88
93
  ```bash
89
- cargo install --path rust/rubydex-mcp
94
+ bundle install
90
95
  ```
91
96
 
92
- 2. Add rubydex to the Ruby project you want to index:
97
+ 3. Configure your MCP client to run `bundle exec rubydex_mcp`.
98
+
99
+ Using Claude Code as an example:
93
100
  ```bash
94
- claude mcp add --scope project rubydex "\${HOME}/.cargo/bin/rubydex_mcp"
101
+ claude mcp add --scope project rubydex -- bundle exec rubydex_mcp
95
102
  ```
96
103
 
97
- Or manually create a `.mcp.json` in the project root:
98
- ```json
99
- {
100
- "mcpServers": {
101
- "rubydex": {
102
- "command": "${HOME}/.cargo/bin/rubydex_mcp"
103
- }
104
- }
105
- }
104
+ Using Codex as an example:
105
+ ```bash
106
+ codex mcp add rubydex -- bundle exec rubydex_mcp
106
107
  ```
107
108
 
108
- 3. Start Claude Code from that project directory. The MCP server indexes
109
- the project at startup and provides semantic code intelligence tools.
110
- Verify with `/mcp` in the session.
109
+ Start your MCP client from that project directory. The MCP server indexes
110
+ the project at startup and provides semantic code intelligence tools through
111
+ the tools below.
111
112
 
112
113
  ### Available MCP Tools
113
114
 
@@ -3823,14 +3823,14 @@ SOFTWARE.
3823
3823
  <h4>Used by:</h4>
3824
3824
  <ul class="license-used-by">
3825
3825
  <li><a
3826
- href=" https://crates.io/crates/rubydex ">rubydex
3827
- 0.1.0</a></li>
3826
+ href=" https://github.com/Shopify/rubydex ">rubydex
3827
+ 0.2.6</a></li>
3828
3828
  <li><a
3829
- href=" https://crates.io/crates/rubydex-mcp ">rubydex-mcp
3830
- 0.1.0</a></li>
3829
+ href=" https://github.com/Shopify/rubydex ">rubydex-mcp
3830
+ 0.2.6</a></li>
3831
3831
  <li><a
3832
- href=" https://crates.io/crates/rubydex-sys ">rubydex-sys
3833
- 0.1.0</a></li>
3832
+ href=" https://github.com/Shopify/rubydex ">rubydex-sys
3833
+ 0.2.6</a></li>
3834
3834
  <li><a
3835
3835
  href=" https://github.com/DimaKudosh/difflib ">difflib
3836
3836
  0.4.0</a></li>
data/exe/rubydex_mcp ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "rbconfig"
5
+
6
+ host_os = RbConfig::CONFIG.fetch("host_os")
7
+ executable = host_os.match?(/mswin|mingw|cygwin/) ? "rubydex_mcp.exe" : "rubydex_mcp"
8
+ binary = File.expand_path("../lib/rubydex/bin/#{executable}", __dir__)
9
+
10
+ unless File.executable?(binary)
11
+ abort(<<~MESSAGE.chomp)
12
+ rubydex_mcp is not available at #{binary}.
13
+ Install a precompiled rubydex gem, or reinstall rubydex with Cargo available so the MCP executable can be built locally.
14
+ MESSAGE
15
+ end
16
+
17
+ exec(binary, *ARGV)
@@ -154,8 +154,8 @@ static VALUE rdxr_definition_deprecated(VALUE self) {
154
154
  }
155
155
 
156
156
  // Definition#name_location -> Rubydex::Location or nil
157
- // For class, module, and singleton class definitions, returns the location of just the name
158
- // (e.g., "Bar" in "class Foo::Bar"). For other definition types, returns nil.
157
+ // For class, module, singleton class, and method definitions, returns the location of just the name
158
+ // (e.g., "Bar" in "class Foo::Bar", or "foo" in "def foo"). For other definition types, returns nil.
159
159
  static VALUE rdxr_definition_name_location(VALUE self) {
160
160
  HandleData *data;
161
161
  TypedData_Get_Struct(self, HandleData, &handle_type, data);
@@ -195,6 +195,60 @@ static VALUE rdxr_definition_declaration(VALUE self) {
195
195
  return rb_class_new_instance(2, argv, decl_class);
196
196
  }
197
197
 
198
+ static VALUE rdxi_build_definition(VALUE graph_obj, void *graph, uint64_t definition_id) {
199
+ DefinitionKind kind = rdx_definition_kind(graph, definition_id);
200
+ VALUE defn_class = rdxi_definition_class_for_kind(kind);
201
+ VALUE argv[] = {graph_obj, ULL2NUM(definition_id)};
202
+
203
+ return rb_class_new_instance(2, argv, defn_class);
204
+ }
205
+
206
+ // Definition#lexical_owner -> Rubydex::Definition?
207
+ // Returns the lexically enclosing definition, if any.
208
+ static VALUE rdxr_definition_lexical_owner(VALUE self) {
209
+ HandleData *data;
210
+ TypedData_Get_Struct(self, HandleData, &handle_type, data);
211
+
212
+ void *graph;
213
+ TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
214
+
215
+ const uint64_t *owner_id = rdx_definition_lexical_nesting_id(graph, data->id);
216
+ if (owner_id == NULL) {
217
+ return Qnil;
218
+ }
219
+
220
+ VALUE owner = rdxi_build_definition(data->graph_obj, graph, *owner_id);
221
+ free_u64(owner_id);
222
+
223
+ return owner;
224
+ }
225
+
226
+ // Definition#lexical_nesting -> Array<Rubydex::Definition>
227
+ // Returns the lexical nesting from the direct owner up to the root.
228
+ static VALUE rdxr_definition_lexical_nesting(VALUE self) {
229
+ HandleData *data;
230
+ TypedData_Get_Struct(self, HandleData, &handle_type, data);
231
+
232
+ void *graph;
233
+ TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
234
+
235
+ VALUE nesting = rb_ary_new();
236
+ uint64_t definition_id = data->id;
237
+
238
+ while (true) {
239
+ const uint64_t *owner_id = rdx_definition_lexical_nesting_id(graph, definition_id);
240
+ if (owner_id == NULL) {
241
+ break;
242
+ }
243
+
244
+ rb_ary_push(nesting, rdxi_build_definition(data->graph_obj, graph, *owner_id));
245
+ definition_id = *owner_id;
246
+ free_u64(owner_id);
247
+ }
248
+
249
+ return nesting;
250
+ }
251
+
198
252
  static VALUE rdxi_build_constant_reference(VALUE graph_obj, const CConstantReference *cref) {
199
253
  VALUE ref_class = (cref->declaration_id == 0)
200
254
  ? cUnresolvedConstantReference
@@ -287,6 +341,36 @@ static VALUE rdxr_method_alias_definition_signatures(VALUE self) {
287
341
  return rdxi_signatures_to_ruby(arr);
288
342
  }
289
343
 
344
+ // MethodAliasDefinition#target -> Rubydex::Method?
345
+ // Returns the resolved target method declaration by following the alias chain, or nil if the chain could not be
346
+ // resolved (the target name doesn't exist on the owner, or the owner itself never resolved). Raises
347
+ // Rubydex::AliasCycleError when the alias chain forms a cycle.
348
+ static VALUE rdxr_method_alias_definition_target(VALUE self) {
349
+ HandleData *data;
350
+ TypedData_Get_Struct(self, HandleData, &handle_type, data);
351
+
352
+ void *graph;
353
+ TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
354
+
355
+ CMethodAliasTargetResult result = rdx_method_alias_definition_target(graph, data->id);
356
+
357
+ switch (result.status) {
358
+ case CMethodAliasResolution_Resolved: {
359
+ VALUE decl_class = rdxi_declaration_class_for_kind(result.declaration->kind);
360
+ VALUE argv[] = {data->graph_obj, ULL2NUM(result.declaration->id)};
361
+
362
+ free_c_declaration(result.declaration);
363
+ return rb_class_new_instance(2, argv, decl_class);
364
+ }
365
+ case CMethodAliasResolution_NotFound:
366
+ return Qnil;
367
+ case CMethodAliasResolution_Cycle:
368
+ rb_raise(rb_const_get(mRubydex, rb_intern("AliasCycleError")), "method alias chain forms a cycle");
369
+ default:
370
+ rb_raise(rb_eRuntimeError, "Unknown CMethodAliasResolution: %d", result.status);
371
+ }
372
+ }
373
+
290
374
  void rdxi_initialize_definition(VALUE mod) {
291
375
  mRubydex = mod;
292
376
 
@@ -306,6 +390,8 @@ void rdxi_initialize_definition(VALUE mod) {
306
390
  rb_define_method(cDefinition, "deprecated?", rdxr_definition_deprecated, 0);
307
391
  rb_define_method(cDefinition, "name_location", rdxr_definition_name_location, 0);
308
392
  rb_define_method(cDefinition, "declaration", rdxr_definition_declaration, 0);
393
+ rb_define_method(cDefinition, "lexical_owner", rdxr_definition_lexical_owner, 0);
394
+ rb_define_method(cDefinition, "lexical_nesting", rdxr_definition_lexical_nesting, 0);
309
395
 
310
396
  cClassDefinition = rb_define_class_under(mRubydex, "ClassDefinition", cDefinition);
311
397
  rb_define_method(cClassDefinition, "superclass", rdxr_class_definition_superclass, 0);
@@ -331,5 +417,6 @@ void rdxi_initialize_definition(VALUE mod) {
331
417
  cClassVariableDefinition = rb_define_class_under(mRubydex, "ClassVariableDefinition", cDefinition);
332
418
  cMethodAliasDefinition = rb_define_class_under(mRubydex, "MethodAliasDefinition", cDefinition);
333
419
  rb_define_method(cMethodAliasDefinition, "signatures", rdxr_method_alias_definition_signatures, 0);
420
+ rb_define_method(cMethodAliasDefinition, "target", rdxr_method_alias_definition_target, 0);
334
421
  cGlobalVariableAliasDefinition = rb_define_class_under(mRubydex, "GlobalVariableAliasDefinition", cDefinition);
335
422
  }
@@ -3,6 +3,7 @@
3
3
  #include "graph.h"
4
4
  #include "handle.h"
5
5
  #include "rustbindings.h"
6
+ #include "utils.h"
6
7
 
7
8
  VALUE cDocument;
8
9
 
@@ -85,6 +86,40 @@ static VALUE rdxr_document_definitions(VALUE self) {
85
86
  return self;
86
87
  }
87
88
 
89
+ // Size function for the Document#method_references enumerator
90
+ static VALUE document_method_references_size(VALUE self, VALUE _args, VALUE _eobj) {
91
+ HandleData *data;
92
+ TypedData_Get_Struct(self, HandleData, &handle_type, data);
93
+
94
+ void *graph;
95
+ TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
96
+ struct MethodReferencesIter *iter = rdx_document_method_references_iter_new(graph, data->id);
97
+ size_t len = rdx_method_references_iter_len(iter);
98
+ rdx_method_references_iter_free(iter);
99
+
100
+ return SIZET2NUM(len);
101
+ }
102
+
103
+ // Document#method_references: () -> Enumerator[MethodReference]
104
+ // Returns an enumerator that yields all method references for this document lazily
105
+ static VALUE rdxr_document_method_references(VALUE self) {
106
+ if (!rb_block_given_p()) {
107
+ return rb_enumeratorize_with_size(self, rb_str_new2("method_references"), 0, NULL,
108
+ document_method_references_size);
109
+ }
110
+
111
+ HandleData *data;
112
+ TypedData_Get_Struct(self, HandleData, &handle_type, data);
113
+
114
+ void *graph;
115
+ TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph);
116
+ void *iter = rdx_document_method_references_iter_new(graph, data->id);
117
+ VALUE args = rb_ary_new_from_args(2, data->graph_obj, ULL2NUM((uintptr_t)iter));
118
+ rb_ensure(rdxi_method_references_yield, args, rdxi_method_references_ensure, args);
119
+
120
+ return self;
121
+ }
122
+
88
123
  void rdxi_initialize_document(VALUE mRubydex) {
89
124
  cDocument = rb_define_class_under(mRubydex, "Document", rb_cObject);
90
125
 
@@ -92,6 +127,7 @@ void rdxi_initialize_document(VALUE mRubydex) {
92
127
  rb_define_method(cDocument, "initialize", rdxr_handle_initialize, 2);
93
128
  rb_define_method(cDocument, "uri", rdxr_document_uri, 0);
94
129
  rb_define_method(cDocument, "definitions", rdxr_document_definitions, 0);
130
+ rb_define_method(cDocument, "method_references", rdxr_document_method_references, 0);
95
131
 
96
132
  rb_funcall(rb_singleton_class(cDocument), rb_intern("private"), 1, ID2SYM(rb_intern("new")));
97
133
  }
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "mkmf"
4
+ require "fileutils"
4
5
  require "pathname"
5
6
 
6
7
  unless system("cargo", "--version", out: File::NULL, err: File::NULL)
@@ -81,6 +82,12 @@ else
81
82
  end
82
83
 
83
84
  lib_dir = gem_dir.join("lib").join("rubydex")
85
+ mcp_bin_dir = lib_dir.join("bin")
86
+ FileUtils.mkdir_p(mcp_bin_dir)
87
+
88
+ mcp_executable = Gem.win_platform? ? "rubydex_mcp.exe" : "rubydex_mcp"
89
+ mcp_src = target_dir.join(mcp_executable)
90
+ mcp_dst = mcp_bin_dir.join(mcp_executable)
84
91
 
85
92
  copy_dylib_commands = if Gem.win_platform?
86
93
  ""
@@ -107,6 +114,7 @@ new_makefile = makefile.gsub("$(OBJS): $(HDRS) $(ruby_headers)", <<~MAKEFILE.cho
107
114
  .rust_built: $(RUST_SRCS)
108
115
  \t#{cargo_command} || (echo "Compiling Rust failed" && exit 1)
109
116
  \t$(COPY) #{bindings_path} #{__dir__}
117
+ \t$(COPY) #{mcp_src} #{mcp_dst}
110
118
  \ttouch $@
111
119
 
112
120
  compile_rust: .rust_built
data/ext/rubydex/graph.c CHANGED
@@ -16,17 +16,20 @@ static VALUE cKeywordParameter;
16
16
  // Interned once in `rdxi_initialize_graph` to avoid repeated symbol-table lookups on hot completion paths.
17
17
  static ID id_self_receiver;
18
18
 
19
- // Extracts the optional `self_receiver:` kwarg from `opts`. Returns NULL when the kwarg is
20
- // absent or nil; raises ArgumentError when the value is the wrong type or empty.
19
+ // Extracts the required `self_receiver:` kwarg from `opts`. Returns NULL when the value is `nil`,
20
+ // which means "no self-type to walk" (e.g., empty class body where the singleton class hasn't
21
+ // been created). Raises ArgumentError if the kwarg is absent, of the wrong type, or an empty
22
+ // string. The kwarg is required so that callers commit to a self type — there is no implicit
23
+ // default.
21
24
  static const char *extract_self_receiver(VALUE opts) {
22
25
  if (NIL_P(opts)) {
23
- return NULL;
26
+ rb_raise(rb_eArgError, "missing keyword: self_receiver");
24
27
  }
25
28
 
26
29
  VALUE kwarg_val;
27
- rb_get_kwargs(opts, &id_self_receiver, 0, 1, &kwarg_val);
30
+ rb_get_kwargs(opts, &id_self_receiver, 1, 0, &kwarg_val);
28
31
 
29
- if (kwarg_val == Qundef || NIL_P(kwarg_val)) {
32
+ if (NIL_P(kwarg_val)) {
30
33
  return NULL;
31
34
  }
32
35
 
@@ -45,7 +48,18 @@ static void graph_free(void *ptr) {
45
48
  }
46
49
  }
47
50
 
48
- const rb_data_type_t graph_type = {"Graph", {0, graph_free, 0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY};
51
+ const rb_data_type_t graph_type = {
52
+ .wrap_struct_name = "Graph",
53
+ .function = {
54
+ .dmark = NULL,
55
+ .dfree = graph_free,
56
+ .dsize = NULL,
57
+ .dcompact = NULL,
58
+ },
59
+ .parent = NULL,
60
+ .data = NULL,
61
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
62
+ };
49
63
 
50
64
  // Custom allocator for the Graph class. Calls into Rust to create a new `Arc<Mutex<Graph>>` that gets stored internally
51
65
  // as a void pointer
@@ -589,11 +603,10 @@ static VALUE completion_result_to_ruby_array(struct CompletionResult result, VAL
589
603
  return ruby_array;
590
604
  }
591
605
 
592
- // Graph#complete_expression: (Array[String] nesting, self_receiver: nil) -> Array[Declaration | Keyword]
606
+ // Graph#complete_expression: (Array[String] nesting, self_receiver:) -> Array[Declaration | Keyword]
593
607
  // Returns completion candidates for an expression context.
594
- // The nesting array represents the lexical scope stack. The optional self_receiver keyword argument
595
- // overrides the self-type (e.g., "Foo::<Foo>" for `def Foo.bar`); when nil, self is derived from
596
- // the innermost nesting element.
608
+ // The nesting array represents the lexical scope stack. The required self_receiver keyword argument overrides the
609
+ // self-type (e.g., "Foo::<Foo>" for `def Foo.bar`); when nil, self is derived from the innermost nesting element.
597
610
  static VALUE rdxr_graph_complete_expression(int argc, VALUE *argv, VALUE self) {
598
611
  VALUE nesting, opts;
599
612
  rb_scan_args(argc, argv, "1:", &nesting, &opts);
@@ -614,10 +627,11 @@ static VALUE rdxr_graph_complete_expression(int argc, VALUE *argv, VALUE self) {
614
627
  return completion_result_to_ruby_array(result, self);
615
628
  }
616
629
 
617
- // Graph#complete_namespace_access: (String name, self_receiver: nil) -> Array[Declaration]
630
+ // Graph#complete_namespace_access: (String name, self_receiver:) -> Array[Declaration]
618
631
  // Returns completion candidates after a namespace access operator (e.g., `Foo::`).
619
- // The optional self_receiver kwarg is the caller's runtime self type, used to filter
620
- // visibility-restricted singleton methods (e.g., `private_class_method`).
632
+ // The required self_receiver kwarg is the caller's runtime self type, used to filter
633
+ // visibility-restricted singleton methods (e.g., `private_class_method`). Pass `nil` when there
634
+ // is no caller context.
621
635
  static VALUE rdxr_graph_complete_namespace_access(int argc, VALUE *argv, VALUE self) {
622
636
  VALUE name, opts;
623
637
  rb_scan_args(argc, argv, "1:", &name, &opts);
@@ -633,10 +647,10 @@ static VALUE rdxr_graph_complete_namespace_access(int argc, VALUE *argv, VALUE s
633
647
  return completion_result_to_ruby_array(result, self);
634
648
  }
635
649
 
636
- // Graph#complete_method_call: (String name, self_receiver: nil) -> Array[Declaration]
650
+ // Graph#complete_method_call: (String name, self_receiver:) -> Array[Declaration]
637
651
  // Returns completion candidates after a method call operator (e.g., `foo.`).
638
- // The optional self_receiver kwarg is the caller's runtime self type, used for MRI-style
639
- // visibility checks (private/protected).
652
+ // The required self_receiver kwarg is the caller's runtime self type, used for visibility checks (private/protected).
653
+ // Pass `nil` when there is no caller context.
640
654
  static VALUE rdxr_graph_complete_method_call(int argc, VALUE *argv, VALUE self) {
641
655
  VALUE name, opts;
642
656
  rb_scan_args(argc, argv, "1:", &name, &opts);
@@ -652,9 +666,9 @@ static VALUE rdxr_graph_complete_method_call(int argc, VALUE *argv, VALUE self)
652
666
  return completion_result_to_ruby_array(result, self);
653
667
  }
654
668
 
655
- // Graph#complete_method_argument: (String name, Array[String] nesting, self_receiver: nil) -> Array[Declaration | Keyword | KeywordParameter]
669
+ // Graph#complete_method_argument: (String name, Array[String] nesting, self_receiver:) -> Array[Declaration | Keyword | KeywordParameter]
656
670
  // Returns completion candidates inside a method call's argument list (e.g., `foo.bar(|)`).
657
- // See complete_expression for semantics of self_receiver.
671
+ // See complete_expression for semantics of self_receiver (required, may be nil).
658
672
  static VALUE rdxr_graph_complete_method_argument(int argc, VALUE *argv, VALUE self) {
659
673
  VALUE name, nesting, opts;
660
674
  rb_scan_args(argc, argv, "2:", &name, &nesting, &opts);
data/ext/rubydex/handle.h CHANGED
@@ -22,12 +22,25 @@ static void handle_free(void *ptr) {
22
22
  }
23
23
 
24
24
  static const rb_data_type_t handle_type = {
25
- "RubydexHandle", {handle_mark, handle_free, 0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY};
25
+ .wrap_struct_name = "RubydexHandle",
26
+ .function = {
27
+ .dmark = handle_mark,
28
+ .dfree = handle_free,
29
+ .dsize = NULL,
30
+ .dcompact = NULL,
31
+ },
32
+ .parent = NULL,
33
+ .data = NULL,
34
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
35
+ };
26
36
 
27
37
  static VALUE rdxr_handle_alloc(VALUE klass) {
28
38
  HandleData *data = ALLOC(HandleData);
29
- data->graph_obj = Qnil;
30
- data->id = 0;
39
+
40
+ *data = (HandleData) {
41
+ .graph_obj = Qnil,
42
+ .id = 0,
43
+ };
31
44
 
32
45
  return TypedData_Wrap_Struct(klass, &handle_type, data);
33
46
  }
@@ -35,8 +48,11 @@ static VALUE rdxr_handle_alloc(VALUE klass) {
35
48
  static VALUE rdxr_handle_initialize(VALUE self, VALUE graph_obj, VALUE id_val) {
36
49
  HandleData *data;
37
50
  TypedData_Get_Struct(self, HandleData, &handle_type, data);
38
- data->graph_obj = graph_obj;
39
- data->id = NUM2ULL(id_val);
51
+
52
+ *data = (HandleData) {
53
+ .graph_obj = graph_obj,
54
+ .id = NUM2ULL(id_val),
55
+ };
40
56
 
41
57
  return self;
42
58
  }
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -21,9 +21,9 @@ module Rubydex
21
21
  end
22
22
 
23
23
  class Namespace < Declaration
24
- #: (String ancestor_name) -> bool
25
- def has_ancestor?(ancestor_name)
26
- ancestors.any? { |ancestor| ancestor.name == ancestor_name }
24
+ #: (*String ancestor_names) -> bool
25
+ def has_ancestor?(*ancestor_names)
26
+ ancestors.any? { |ancestor| ancestor_names.include?(ancestor.name) }
27
27
  end
28
28
  end
29
29
 
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubydex
4
+ class Error < StandardError; end
5
+
6
+ # Raised when `MethodAliasDefinition#target` walks an alias chain that loops back on itself.
7
+ class AliasCycleError < Error; end
8
+ end
data/lib/rubydex/graph.rb CHANGED
@@ -17,6 +17,8 @@ module Rubydex
17
17
  "tmp",
18
18
  ].freeze
19
19
 
20
+ INDEXABLE_EXTENSIONS = [".rb", ".rake", ".rbs", ".ru"].freeze
21
+
20
22
  #: String
21
23
  attr_accessor :workspace_path
22
24
 
@@ -45,7 +47,7 @@ module Rubydex
45
47
 
46
48
  if File.directory?(full_path)
47
49
  paths << full_path unless IGNORED_DIRECTORIES.include?(entry)
48
- elsif File.extname(entry) == ".rb"
50
+ elsif INDEXABLE_EXTENSIONS.include?(File.extname(entry))
49
51
  paths << full_path
50
52
  end
51
53
  end
Binary file
@@ -14,6 +14,19 @@ module Rubydex
14
14
  #: Integer
15
15
  attr_reader :start_line, :end_line, :start_column, :end_column
16
16
 
17
+ class << self
18
+ #: (Prism::Location prism_location, uri: String) -> Location
19
+ def from_prism(prism_location, uri:)
20
+ Location.new(
21
+ uri: uri,
22
+ start_line: prism_location.start_line - 1,
23
+ start_column: prism_location.start_column,
24
+ end_line: prism_location.end_line - 1,
25
+ end_column: prism_location.end_column,
26
+ )
27
+ end
28
+ end
29
+
17
30
  #: (?uri: String, ?start_line: Integer, ?end_line: Integer, ?start_column: Integer, ?end_column: Integer) -> void
18
31
  def initialize(uri:, start_line:, end_line:, start_column:, end_column:)
19
32
  @uri = uri
@@ -68,6 +81,17 @@ module Rubydex
68
81
  # A one based location intended for display purposes. This is what should be used when displaying a location to users,
69
82
  # like in CLIs
70
83
  class DisplayLocation < Location
84
+ class << self
85
+ #: (Prism::Location prism_location, uri: String) -> Location
86
+ def from_prism(prism_location, uri:)
87
+ raise NotImplementedError, <<~MESSAGE
88
+ Cannot convert Prism::Location directly to a Rubydex::DisplayLocation.
89
+ Start with `Rubydex::Location.from_prism(...)` and then convert the resulting
90
+ location with `to_display`
91
+ MESSAGE
92
+ end
93
+ end
94
+
71
95
  # Returns itself
72
96
  #
73
97
  #: () -> DisplayLocation
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubydex
4
- VERSION = "0.2.4"
4
+ VERSION = "0.2.6"
5
5
  end
data/lib/rubydex.rb CHANGED
@@ -14,6 +14,7 @@ rescue LoadError
14
14
  require "rubydex/rubydex"
15
15
  end
16
16
 
17
+ require "rubydex/errors"
17
18
  require "rubydex/failures"
18
19
  require "rubydex/location"
19
20
  require "rubydex/comment"