method-ray 0.1.8 → 0.1.10

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +9 -11
  4. data/{rust → core}/Cargo.toml +1 -1
  5. data/core/src/analyzer/assignments.rs +219 -0
  6. data/{rust → core}/src/analyzer/blocks.rs +0 -50
  7. data/{rust → core}/src/analyzer/calls.rs +3 -32
  8. data/core/src/analyzer/conditionals.rs +190 -0
  9. data/core/src/analyzer/definitions.rs +205 -0
  10. data/core/src/analyzer/dispatch.rs +455 -0
  11. data/core/src/analyzer/exceptions.rs +168 -0
  12. data/{rust → core}/src/analyzer/install.rs +16 -1
  13. data/{rust → core}/src/analyzer/literals.rs +3 -71
  14. data/core/src/analyzer/loops.rs +94 -0
  15. data/{rust → core}/src/analyzer/mod.rs +1 -15
  16. data/core/src/analyzer/operators.rs +79 -0
  17. data/{rust → core}/src/analyzer/parameters.rs +4 -67
  18. data/core/src/analyzer/parentheses.rs +25 -0
  19. data/core/src/analyzer/returns.rs +39 -0
  20. data/core/src/analyzer/super_calls.rs +74 -0
  21. data/{rust → core}/src/analyzer/variables.rs +5 -25
  22. data/{rust → core}/src/checker.rs +0 -13
  23. data/{rust → core}/src/diagnostics/diagnostic.rs +0 -41
  24. data/{rust → core}/src/diagnostics/formatter.rs +0 -38
  25. data/{rust → core}/src/env/box_manager.rs +0 -30
  26. data/{rust → core}/src/env/global_env.rs +67 -80
  27. data/core/src/env/local_env.rs +42 -0
  28. data/core/src/env/method_registry.rs +173 -0
  29. data/core/src/env/scope.rs +299 -0
  30. data/{rust → core}/src/env/vertex_manager.rs +0 -73
  31. data/core/src/graph/box.rs +347 -0
  32. data/{rust → core}/src/graph/change_set.rs +0 -65
  33. data/{rust → core}/src/graph/vertex.rs +0 -69
  34. data/{rust → core}/src/parser.rs +0 -77
  35. data/{rust → core}/src/types.rs +11 -0
  36. data/ext/Cargo.toml +2 -2
  37. data/lib/methodray/binary_locator.rb +2 -2
  38. data/lib/methodray/commands.rb +1 -1
  39. data/lib/methodray/version.rb +1 -1
  40. metadata +58 -56
  41. data/rust/src/analyzer/assignments.rs +0 -152
  42. data/rust/src/analyzer/conditionals.rs +0 -538
  43. data/rust/src/analyzer/definitions.rs +0 -719
  44. data/rust/src/analyzer/dispatch.rs +0 -1137
  45. data/rust/src/analyzer/exceptions.rs +0 -521
  46. data/rust/src/analyzer/loops.rs +0 -176
  47. data/rust/src/analyzer/operators.rs +0 -284
  48. data/rust/src/analyzer/parentheses.rs +0 -113
  49. data/rust/src/analyzer/returns.rs +0 -191
  50. data/rust/src/env/local_env.rs +0 -92
  51. data/rust/src/env/method_registry.rs +0 -268
  52. data/rust/src/env/scope.rs +0 -596
  53. data/rust/src/graph/box.rs +0 -766
  54. /data/{rust → core}/src/analyzer/attributes.rs +0 -0
  55. /data/{rust → core}/src/cache/mod.rs +0 -0
  56. /data/{rust → core}/src/cache/rbs_cache.rs +0 -0
  57. /data/{rust → core}/src/cli/args.rs +0 -0
  58. /data/{rust → core}/src/cli/commands.rs +0 -0
  59. /data/{rust → core}/src/cli/mod.rs +0 -0
  60. /data/{rust → core}/src/diagnostics/mod.rs +0 -0
  61. /data/{rust → core}/src/env/mod.rs +0 -0
  62. /data/{rust → core}/src/env/type_error.rs +0 -0
  63. /data/{rust → core}/src/graph/mod.rs +0 -0
  64. /data/{rust → core}/src/lib.rs +0 -0
  65. /data/{rust → core}/src/lsp/diagnostics.rs +0 -0
  66. /data/{rust → core}/src/lsp/main.rs +0 -0
  67. /data/{rust → core}/src/lsp/mod.rs +0 -0
  68. /data/{rust → core}/src/lsp/server.rs +0 -0
  69. /data/{rust → core}/src/main.rs +0 -0
  70. /data/{rust → core}/src/rbs/converter.rs +0 -0
  71. /data/{rust → core}/src/rbs/error.rs +0 -0
  72. /data/{rust → core}/src/rbs/loader.rs +0 -0
  73. /data/{rust → core}/src/rbs/mod.rs +0 -0
  74. /data/{rust → core}/src/source_map.rs +0 -0
@@ -1,268 +0,0 @@
1
- //! Method registration and resolution
2
-
3
- use std::collections::HashMap;
4
-
5
- use crate::graph::VertexId;
6
- use crate::types::Type;
7
- use smallvec::SmallVec;
8
-
9
- const OBJECT_CLASS: &str = "Object";
10
- const KERNEL_MODULE: &str = "Kernel";
11
-
12
- /// Method information
13
- #[derive(Debug, Clone)]
14
- pub struct MethodInfo {
15
- pub return_type: Type,
16
- pub block_param_types: Option<Vec<Type>>,
17
- pub return_vertex: Option<VertexId>,
18
- pub param_vertices: Option<Vec<VertexId>>,
19
- pub keyword_param_vertices: Option<HashMap<String, VertexId>>,
20
- }
21
-
22
- /// Registry for method definitions
23
- #[derive(Debug, Default)]
24
- pub struct MethodRegistry {
25
- methods: HashMap<(Type, String), MethodInfo>,
26
- }
27
-
28
- impl MethodRegistry {
29
- /// Create a new empty registry
30
- pub fn new() -> Self {
31
- Self {
32
- methods: HashMap::new(),
33
- }
34
- }
35
-
36
- /// Register a method for a receiver type
37
- pub fn register(&mut self, recv_ty: Type, method_name: &str, ret_ty: Type) {
38
- self.register_with_block(recv_ty, method_name, ret_ty, None);
39
- }
40
-
41
- /// Register a method with block parameter types
42
- pub fn register_with_block(
43
- &mut self,
44
- recv_ty: Type,
45
- method_name: &str,
46
- ret_ty: Type,
47
- block_param_types: Option<Vec<Type>>,
48
- ) {
49
- self.methods.insert(
50
- (recv_ty, method_name.to_string()),
51
- MethodInfo {
52
- return_type: ret_ty,
53
- block_param_types,
54
- return_vertex: None,
55
- param_vertices: None,
56
- keyword_param_vertices: None,
57
- },
58
- );
59
- }
60
-
61
- /// Register a user-defined method (return type resolved via graph)
62
- pub fn register_user_method(
63
- &mut self,
64
- recv_ty: Type,
65
- method_name: &str,
66
- return_vertex: VertexId,
67
- param_vertices: Vec<VertexId>,
68
- keyword_param_vertices: Option<HashMap<String, VertexId>>,
69
- ) {
70
- self.methods.insert(
71
- (recv_ty, method_name.to_string()),
72
- MethodInfo {
73
- return_type: Type::Bot,
74
- block_param_types: None,
75
- return_vertex: Some(return_vertex),
76
- param_vertices: Some(param_vertices),
77
- keyword_param_vertices,
78
- },
79
- );
80
- }
81
-
82
- /// Build the method resolution order (MRO) fallback chain for a receiver type.
83
- ///
84
- /// Returns a list of types to search in order:
85
- /// 1. Exact receiver type
86
- /// 2. Generic → base class (e.g., Array[Integer] → Array)
87
- /// 3. Object (for Instance/Generic types only)
88
- /// 4. Kernel (for Instance/Generic types only)
89
- fn fallback_chain(recv_ty: &Type) -> SmallVec<[Type; 4]> {
90
- let mut chain = SmallVec::new();
91
- chain.push(recv_ty.clone());
92
-
93
- if let Type::Generic { name, .. } = recv_ty {
94
- chain.push(Type::Instance { name: name.clone() });
95
- }
96
-
97
- // NOTE: Kernel is a module, not a class. Represented as Type::Instance
98
- // due to lack of Type::Module variant.
99
- if matches!(recv_ty, Type::Instance { .. } | Type::Generic { .. }) {
100
- chain.push(Type::instance(OBJECT_CLASS));
101
- chain.push(Type::instance(KERNEL_MODULE));
102
- }
103
-
104
- chain
105
- }
106
-
107
- /// Resolve a method for a receiver type
108
- ///
109
- /// Searches the MRO fallback chain: exact type → base class (for generics) → Object → Kernel.
110
- /// For non-instance types (Singleton, Nil, Union, Bot), only exact match is attempted.
111
- pub fn resolve(&self, recv_ty: &Type, method_name: &str) -> Option<&MethodInfo> {
112
- let method_key = method_name.to_string();
113
- Self::fallback_chain(recv_ty)
114
- .into_iter()
115
- .find_map(|ty| self.methods.get(&(ty, method_key.clone())))
116
- }
117
- }
118
-
119
- #[cfg(test)]
120
- mod tests {
121
- use super::*;
122
-
123
- #[test]
124
- fn test_register_and_resolve() {
125
- let mut registry = MethodRegistry::new();
126
- registry.register(Type::string(), "length", Type::integer());
127
-
128
- let info = registry.resolve(&Type::string(), "length").unwrap();
129
- assert_eq!(info.return_type.base_class_name(), Some("Integer"));
130
- }
131
-
132
- #[test]
133
- fn test_resolve_not_found() {
134
- let registry = MethodRegistry::new();
135
- assert!(registry.resolve(&Type::string(), "unknown").is_none());
136
- }
137
-
138
- #[test]
139
- fn test_register_user_method_and_resolve() {
140
- let mut registry = MethodRegistry::new();
141
- let return_vtx = VertexId(42);
142
- registry.register_user_method(Type::instance("User"), "name", return_vtx, vec![], None);
143
-
144
- let info = registry.resolve(&Type::instance("User"), "name").unwrap();
145
- assert_eq!(info.return_vertex, Some(VertexId(42)));
146
- assert_eq!(info.return_type, Type::Bot);
147
- }
148
-
149
- #[test]
150
- fn test_register_user_method_with_param_vertices() {
151
- let mut registry = MethodRegistry::new();
152
- let return_vtx = VertexId(10);
153
- let param_vtxs = vec![VertexId(20), VertexId(21)];
154
- registry.register_user_method(
155
- Type::instance("Calc"),
156
- "add",
157
- return_vtx,
158
- param_vtxs,
159
- None,
160
- );
161
-
162
- let info = registry.resolve(&Type::instance("Calc"), "add").unwrap();
163
- assert_eq!(info.return_vertex, Some(VertexId(10)));
164
- let pvs = info.param_vertices.as_ref().unwrap();
165
- assert_eq!(pvs.len(), 2);
166
- assert_eq!(pvs[0], VertexId(20));
167
- assert_eq!(pvs[1], VertexId(21));
168
- }
169
-
170
- // --- Object/Kernel fallback ---
171
-
172
- #[test]
173
- fn test_resolve_falls_back_to_object() {
174
- let mut registry = MethodRegistry::new();
175
- registry.register(Type::instance("Object"), "nil?", Type::instance("TrueClass"));
176
- let info = registry.resolve(&Type::instance("CustomClass"), "nil?").unwrap();
177
- assert_eq!(info.return_type.base_class_name(), Some("TrueClass"));
178
- }
179
-
180
- #[test]
181
- fn test_resolve_falls_back_to_kernel() {
182
- let mut registry = MethodRegistry::new();
183
- registry.register(Type::instance("Kernel"), "puts", Type::Nil);
184
- let info = registry.resolve(&Type::instance("MyApp"), "puts").unwrap();
185
- assert_eq!(info.return_type, Type::Nil);
186
- }
187
-
188
- #[test]
189
- fn test_resolve_object_before_kernel() {
190
- let mut registry = MethodRegistry::new();
191
- registry.register(Type::instance("Object"), "to_s", Type::string());
192
- registry.register(Type::instance("Kernel"), "to_s", Type::integer());
193
- let info = registry.resolve(&Type::instance("Anything"), "to_s").unwrap();
194
- assert_eq!(info.return_type.base_class_name(), Some("String"));
195
- }
196
-
197
- #[test]
198
- fn test_resolve_exact_match_over_fallback() {
199
- let mut registry = MethodRegistry::new();
200
- registry.register(Type::string(), "length", Type::integer());
201
- registry.register(Type::instance("Object"), "length", Type::string());
202
- let info = registry.resolve(&Type::string(), "length").unwrap();
203
- assert_eq!(info.return_type.base_class_name(), Some("Integer"));
204
- }
205
-
206
- // --- Types that skip fallback ---
207
-
208
- #[test]
209
- fn test_singleton_type_skips_fallback() {
210
- let mut registry = MethodRegistry::new();
211
- registry.register(Type::instance("Kernel"), "puts", Type::Nil);
212
- assert!(registry.resolve(&Type::singleton("User"), "puts").is_none());
213
- }
214
-
215
- #[test]
216
- fn test_nil_type_skips_fallback() {
217
- let mut registry = MethodRegistry::new();
218
- registry.register(Type::instance("Kernel"), "puts", Type::Nil);
219
- assert!(registry.resolve(&Type::Nil, "puts").is_none());
220
- }
221
-
222
- #[test]
223
- fn test_union_type_skips_fallback() {
224
- let mut registry = MethodRegistry::new();
225
- registry.register(Type::instance("Kernel"), "puts", Type::Nil);
226
- let union_ty = Type::Union(vec![Type::string(), Type::integer()]);
227
- assert!(registry.resolve(&union_ty, "puts").is_none());
228
- }
229
-
230
- #[test]
231
- fn test_bot_type_skips_fallback() {
232
- let mut registry = MethodRegistry::new();
233
- registry.register(Type::instance("Kernel"), "puts", Type::Nil);
234
- assert!(registry.resolve(&Type::Bot, "puts").is_none());
235
- }
236
-
237
- // --- Generic type fallback chain ---
238
-
239
- #[test]
240
- fn test_resolve_generic_falls_back_to_kernel() {
241
- let mut registry = MethodRegistry::new();
242
- registry.register(Type::instance("Kernel"), "puts", Type::Nil);
243
- let generic_type = Type::array_of(Type::integer());
244
- let info = registry.resolve(&generic_type, "puts").unwrap();
245
- assert_eq!(info.return_type, Type::Nil);
246
- }
247
-
248
- #[test]
249
- fn test_resolve_generic_full_chain() {
250
- // Verify the 4-step fallback: Generic[T] → Base → Object → Kernel
251
- let mut registry = MethodRegistry::new();
252
- registry.register(Type::instance("Kernel"), "object_id", Type::integer());
253
- let generic_type = Type::array_of(Type::string());
254
- // Array[String] → Array (none) → Object (none) → Kernel (exists)
255
- let info = registry.resolve(&generic_type, "object_id").unwrap();
256
- assert_eq!(info.return_type.base_class_name(), Some("Integer"));
257
- }
258
-
259
- // --- Namespaced class fallback ---
260
-
261
- #[test]
262
- fn test_resolve_namespaced_class_falls_back_to_object() {
263
- let mut registry = MethodRegistry::new();
264
- registry.register(Type::instance("Object"), "class", Type::string());
265
- let info = registry.resolve(&Type::instance("Api::V1::User"), "class").unwrap();
266
- assert_eq!(info.return_type.base_class_name(), Some("String"));
267
- }
268
- }