method-ray 0.1.9 → 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.
@@ -31,18 +31,3 @@ pub use install::AstInstaller;
31
31
  pub(crate) fn bytes_to_name(bytes: &[u8]) -> String {
32
32
  String::from_utf8_lossy(bytes).to_string()
33
33
  }
34
-
35
- #[cfg(test)]
36
- mod tests {
37
- use super::bytes_to_name;
38
-
39
- #[test]
40
- fn test_bytes_to_name_valid_utf8() {
41
- assert_eq!(bytes_to_name(b"hello"), "hello");
42
- }
43
-
44
- #[test]
45
- fn test_bytes_to_name_invalid_utf8_replaced() {
46
- assert_eq!(bytes_to_name(b"hello\xff"), "hello\u{FFFD}");
47
- }
48
- }
@@ -77,208 +77,3 @@ pub(crate) fn process_not_operator(genv: &mut GlobalEnv) -> VertexId {
77
77
  genv.add_edge(false_vtx, result_vtx);
78
78
  result_vtx
79
79
  }
80
-
81
- #[cfg(test)]
82
- mod tests {
83
- use crate::analyzer::install::AstInstaller;
84
- use crate::env::{GlobalEnv, LocalEnv};
85
- use crate::graph::VertexId;
86
- use crate::parser::ParseSession;
87
- use crate::types::Type;
88
-
89
- /// Helper: parse Ruby source, process with AstInstaller, and return GlobalEnv
90
- fn analyze(source: &str) -> GlobalEnv {
91
- let session = ParseSession::new();
92
- let parse_result = session.parse_source(source, "test.rb").unwrap();
93
- let root = parse_result.node();
94
- let program = root.as_program_node().unwrap();
95
-
96
- let mut genv = GlobalEnv::new();
97
- let mut lenv = LocalEnv::new();
98
-
99
- let mut installer = AstInstaller::new(&mut genv, &mut lenv, source);
100
- for stmt in &program.statements().body() {
101
- installer.install_node(&stmt);
102
- }
103
- installer.finish();
104
-
105
- genv
106
- }
107
-
108
- /// Helper: get the type string for a vertex ID
109
- fn get_type_show(genv: &GlobalEnv, vtx: VertexId) -> String {
110
- if let Some(vertex) = genv.get_vertex(vtx) {
111
- vertex.show()
112
- } else if let Some(source) = genv.get_source(vtx) {
113
- source.ty.show()
114
- } else {
115
- panic!("vertex {:?} not found as either Vertex or Source", vtx);
116
- }
117
- }
118
-
119
- #[test]
120
- fn test_and_node_union_type() {
121
- let source = r#"
122
- class Foo
123
- def bar
124
- true && "hello"
125
- end
126
- end
127
- "#;
128
- let genv = analyze(source);
129
- let info = genv
130
- .resolve_method(&Type::instance("Foo"), "bar")
131
- .expect("Foo#bar should be registered");
132
- let ret_vtx = info.return_vertex.unwrap();
133
- let type_str = get_type_show(&genv, ret_vtx);
134
- assert!(type_str.contains("TrueClass"), "should contain TrueClass: {}", type_str);
135
- assert!(type_str.contains("String"), "should contain String: {}", type_str);
136
- }
137
-
138
- #[test]
139
- fn test_and_node_same_type() {
140
- let source = r#"
141
- class Foo
142
- def bar
143
- "a" && "b"
144
- end
145
- end
146
- "#;
147
- let genv = analyze(source);
148
- let info = genv
149
- .resolve_method(&Type::instance("Foo"), "bar")
150
- .expect("Foo#bar should be registered");
151
- let ret_vtx = info.return_vertex.unwrap();
152
- assert_eq!(get_type_show(&genv, ret_vtx), "String");
153
- }
154
-
155
- #[test]
156
- fn test_or_node_union_type() {
157
- let source = r#"
158
- class Foo
159
- def bar
160
- 42 || "hello"
161
- end
162
- end
163
- "#;
164
- let genv = analyze(source);
165
- let info = genv
166
- .resolve_method(&Type::instance("Foo"), "bar")
167
- .expect("Foo#bar should be registered");
168
- let ret_vtx = info.return_vertex.unwrap();
169
- let type_str = get_type_show(&genv, ret_vtx);
170
- assert!(type_str.contains("Integer"), "should contain Integer: {}", type_str);
171
- assert!(type_str.contains("String"), "should contain String: {}", type_str);
172
- }
173
-
174
- #[test]
175
- fn test_or_node_same_type() {
176
- let source = r#"
177
- class Foo
178
- def bar
179
- 1 || 2
180
- end
181
- end
182
- "#;
183
- let genv = analyze(source);
184
- let info = genv
185
- .resolve_method(&Type::instance("Foo"), "bar")
186
- .expect("Foo#bar should be registered");
187
- let ret_vtx = info.return_vertex.unwrap();
188
- assert_eq!(get_type_show(&genv, ret_vtx), "Integer");
189
- }
190
-
191
- #[test]
192
- fn test_nested_logical_operators() {
193
- let source = r#"
194
- class Foo
195
- def bar
196
- 1 && "a" || :b
197
- end
198
- end
199
- "#;
200
- let genv = analyze(source);
201
- let info = genv
202
- .resolve_method(&Type::instance("Foo"), "bar")
203
- .expect("Foo#bar should be registered");
204
- let ret_vtx = info.return_vertex.unwrap();
205
- let type_str = get_type_show(&genv, ret_vtx);
206
- assert!(type_str.contains("Integer"), "should contain Integer: {}", type_str);
207
- assert!(type_str.contains("String"), "should contain String: {}", type_str);
208
- assert!(type_str.contains("Symbol"), "should contain Symbol: {}", type_str);
209
- }
210
-
211
- // ============================================
212
- // Not operator (!) tests
213
- // ============================================
214
-
215
- #[test]
216
- fn test_not_operator_returns_boolean_union() {
217
- let source = r#"
218
- class Foo
219
- def bar
220
- !true
221
- end
222
- end
223
- "#;
224
- let genv = analyze(source);
225
- let info = genv
226
- .resolve_method(&Type::instance("Foo"), "bar")
227
- .expect("bar should be registered");
228
- let ty = get_type_show(&genv, info.return_vertex.unwrap());
229
- assert!(ty.contains("TrueClass"), "expected TrueClass in {}", ty);
230
- assert!(ty.contains("FalseClass"), "expected FalseClass in {}", ty);
231
- }
232
-
233
- #[test]
234
- fn test_not_operator_receiver_side_effects_analyzed() {
235
- let source = r#"
236
- class Foo
237
- def bar
238
- !(1.upcase)
239
- end
240
- end
241
- "#;
242
- let genv = analyze(source);
243
- assert!(
244
- !genv.type_errors.is_empty(),
245
- "expected type error for Integer#upcase"
246
- );
247
- }
248
-
249
- #[test]
250
- fn test_double_not_operator_union() {
251
- let source = r#"
252
- class Foo
253
- def bar
254
- !!true
255
- end
256
- end
257
- "#;
258
- let genv = analyze(source);
259
- let info = genv
260
- .resolve_method(&Type::instance("Foo"), "bar")
261
- .expect("bar should be registered");
262
- let ty = get_type_show(&genv, info.return_vertex.unwrap());
263
- assert!(ty.contains("TrueClass"), "expected TrueClass in {}", ty);
264
- assert!(ty.contains("FalseClass"), "expected FalseClass in {}", ty);
265
- }
266
-
267
- #[test]
268
- fn test_not_nil_returns_boolean() {
269
- let source = r#"
270
- class Foo
271
- def bar
272
- !nil
273
- end
274
- end
275
- "#;
276
- let genv = analyze(source);
277
- let info = genv
278
- .resolve_method(&Type::instance("Foo"), "bar")
279
- .expect("bar should be registered");
280
- let ty = get_type_show(&genv, info.return_vertex.unwrap());
281
- assert!(ty.contains("TrueClass"), "expected TrueClass in {}", ty);
282
- assert!(ty.contains("FalseClass"), "expected FalseClass in {}", ty);
283
- }
284
- }
@@ -24,7 +24,7 @@ use super::bytes_to_name;
24
24
  /// name.upcase
25
25
  /// end
26
26
  /// ```
27
- pub fn install_required_parameter(genv: &mut GlobalEnv, lenv: &mut LocalEnv, name: String) -> VertexId {
27
+ pub(crate) fn install_required_parameter(genv: &mut GlobalEnv, lenv: &mut LocalEnv, name: String) -> VertexId {
28
28
  // Create a vertex for the parameter (starts as Bot/untyped)
29
29
  let param_vtx = genv.new_vertex();
30
30
 
@@ -44,7 +44,7 @@ pub fn install_required_parameter(genv: &mut GlobalEnv, lenv: &mut LocalEnv, nam
44
44
  /// name.upcase
45
45
  /// end
46
46
  /// ```
47
- pub fn install_optional_parameter(
47
+ pub(crate) fn install_optional_parameter(
48
48
  genv: &mut GlobalEnv,
49
49
  lenv: &mut LocalEnv,
50
50
  _changes: &mut ChangeSet,
@@ -75,7 +75,7 @@ pub fn install_optional_parameter(
75
75
  /// items.first
76
76
  /// end
77
77
  /// ```
78
- pub fn install_rest_parameter(genv: &mut GlobalEnv, lenv: &mut LocalEnv, name: String) -> VertexId {
78
+ pub(crate) fn install_rest_parameter(genv: &mut GlobalEnv, lenv: &mut LocalEnv, name: String) -> VertexId {
79
79
  // Create a vertex for the parameter
80
80
  let param_vtx = genv.new_vertex();
81
81
 
@@ -99,7 +99,7 @@ pub fn install_rest_parameter(genv: &mut GlobalEnv, lenv: &mut LocalEnv, name: S
99
99
  /// options[:debug]
100
100
  /// end
101
101
  /// ```
102
- pub fn install_keyword_rest_parameter(
102
+ pub(crate) fn install_keyword_rest_parameter(
103
103
  genv: &mut GlobalEnv,
104
104
  lenv: &mut LocalEnv,
105
105
  name: String,
@@ -204,226 +204,3 @@ pub(crate) fn install_parameters(
204
204
 
205
205
  (param_vtxs, keyword_param_vtxs)
206
206
  }
207
-
208
- #[cfg(test)]
209
- mod tests {
210
- use super::*;
211
- use crate::analyzer::install::AstInstaller;
212
- use crate::parser::ParseSession;
213
-
214
- fn analyze(source: &str) -> GlobalEnv {
215
- let session = ParseSession::new();
216
- let parse_result = session.parse_source(source, "test.rb").unwrap();
217
- let root = parse_result.node();
218
- let program = root.as_program_node().unwrap();
219
-
220
- let mut genv = GlobalEnv::new();
221
- let mut lenv = LocalEnv::new();
222
-
223
- let mut installer = AstInstaller::new(&mut genv, &mut lenv, source);
224
- for stmt in &program.statements().body() {
225
- installer.install_node(&stmt);
226
- }
227
- installer.finish();
228
-
229
- genv
230
- }
231
-
232
- fn get_type_show(genv: &GlobalEnv, vtx: VertexId) -> String {
233
- if let Some(vertex) = genv.get_vertex(vtx) {
234
- vertex.show()
235
- } else if let Some(source) = genv.get_source(vtx) {
236
- source.ty.show()
237
- } else {
238
- panic!("vertex {:?} not found as either Vertex or Source", vtx);
239
- }
240
- }
241
-
242
- #[test]
243
- fn test_install_required_parameter() {
244
- let mut genv = GlobalEnv::new();
245
- let mut lenv = LocalEnv::new();
246
-
247
- let vtx = install_required_parameter(&mut genv, &mut lenv, "name".to_string());
248
-
249
- // Parameter should be registered in LocalEnv
250
- assert_eq!(lenv.get_var("name"), Some(vtx));
251
-
252
- // Vertex should exist in GlobalEnv (as untyped)
253
- let vertex = genv.get_vertex(vtx);
254
- assert!(vertex.is_some());
255
- }
256
-
257
- #[test]
258
- fn test_install_multiple_parameters() {
259
- let mut genv = GlobalEnv::new();
260
- let mut lenv = LocalEnv::new();
261
-
262
- let vtx_a = install_required_parameter(&mut genv, &mut lenv, "a".to_string());
263
- let vtx_b = install_required_parameter(&mut genv, &mut lenv, "b".to_string());
264
- let vtx_c = install_required_parameter(&mut genv, &mut lenv, "c".to_string());
265
-
266
- // All parameters should be registered
267
- assert_eq!(lenv.get_var("a"), Some(vtx_a));
268
- assert_eq!(lenv.get_var("b"), Some(vtx_b));
269
- assert_eq!(lenv.get_var("c"), Some(vtx_c));
270
-
271
- // All vertices should be different
272
- assert_ne!(vtx_a, vtx_b);
273
- assert_ne!(vtx_b, vtx_c);
274
- assert_ne!(vtx_a, vtx_c);
275
- }
276
-
277
- #[test]
278
- fn test_install_optional_parameter_inherits_default_type() {
279
- let mut genv = GlobalEnv::new();
280
- let mut lenv = LocalEnv::new();
281
- let mut changes = ChangeSet::new();
282
-
283
- // Default value: 0 (Integer)
284
- let default_vtx = genv.new_source(Type::integer());
285
- let vtx = install_optional_parameter(
286
- &mut genv,
287
- &mut lenv,
288
- &mut changes,
289
- "age".to_string(),
290
- default_vtx,
291
- );
292
-
293
- assert_eq!(lenv.get_var("age"), Some(vtx));
294
-
295
- // Type should propagate from default value
296
- let vertex = genv.get_vertex(vtx).unwrap();
297
- assert_eq!(vertex.show(), "Integer");
298
- }
299
-
300
- #[test]
301
- fn test_required_parameter_type_propagation() {
302
- let source = r#"
303
- class Foo
304
- def greet(name)
305
- name
306
- end
307
- end
308
-
309
- Foo.new.greet("Alice")
310
- "#;
311
- let genv = analyze(source);
312
- let info = genv.resolve_method(&Type::instance("Foo"), "greet").unwrap();
313
- let ret_vtx = info.return_vertex.unwrap();
314
- assert_eq!(get_type_show(&genv, ret_vtx), "String");
315
- }
316
-
317
- #[test]
318
- fn test_optional_parameter_default_type() {
319
- let source = r#"
320
- class Foo
321
- def greet(name = "World")
322
- name
323
- end
324
- end
325
- "#;
326
- let genv = analyze(source);
327
- let info = genv.resolve_method(&Type::instance("Foo"), "greet").unwrap();
328
- let ret_vtx = info.return_vertex.unwrap();
329
- assert_eq!(get_type_show(&genv, ret_vtx), "String");
330
- }
331
-
332
- #[test]
333
- fn test_multiple_parameters_from_call_site() {
334
- let source = r#"
335
- class Calc
336
- def add(x, y)
337
- x
338
- end
339
- end
340
-
341
- Calc.new.add(1, 2)
342
- "#;
343
- let genv = analyze(source);
344
- let info = genv.resolve_method(&Type::instance("Calc"), "add").unwrap();
345
- let param_vtxs = info.param_vertices.as_ref().unwrap();
346
- assert_eq!(param_vtxs.len(), 2);
347
- // Verify return type is Integer (method returns x, which receives 1)
348
- let ret_vtx = info.return_vertex.unwrap();
349
- assert_eq!(get_type_show(&genv, ret_vtx), "Integer");
350
- }
351
-
352
- #[test]
353
- fn test_keyword_parameter_propagation() {
354
- let source = r#"
355
- class Foo
356
- def greet(name:)
357
- name
358
- end
359
- end
360
-
361
- Foo.new.greet(name: "Alice")
362
- "#;
363
- let genv = analyze(source);
364
- let info = genv.resolve_method(&Type::instance("Foo"), "greet").unwrap();
365
- let ret_vtx = info.return_vertex.unwrap();
366
- assert_eq!(get_type_show(&genv, ret_vtx), "String");
367
- }
368
-
369
- #[test]
370
- fn test_optional_keyword_parameter_default() {
371
- let source = r#"
372
- class Counter
373
- def count(step: 1)
374
- step
375
- end
376
- end
377
- "#;
378
- let genv = analyze(source);
379
- let info = genv.resolve_method(&Type::instance("Counter"), "count").unwrap();
380
- let ret_vtx = info.return_vertex.unwrap();
381
- assert_eq!(get_type_show(&genv, ret_vtx), "Integer");
382
- }
383
-
384
- #[test]
385
- fn test_mixed_positional_and_keyword_params() {
386
- let source = r#"
387
- class User
388
- def initialize(id, name:)
389
- @id = id
390
- @name = name
391
- end
392
- end
393
-
394
- User.new(1, name: "Alice")
395
- "#;
396
- let genv = analyze(source);
397
- assert!(genv.type_errors.is_empty());
398
- }
399
-
400
- #[test]
401
- fn test_rest_parameter() {
402
- let source = r#"
403
- class Foo
404
- def bar(*args)
405
- args
406
- end
407
- end
408
- "#;
409
- let genv = analyze(source);
410
- let info = genv.resolve_method(&Type::instance("Foo"), "bar").unwrap();
411
- let ret_vtx = info.return_vertex.unwrap();
412
- assert_eq!(get_type_show(&genv, ret_vtx), "Array");
413
- }
414
-
415
- #[test]
416
- fn test_no_parameters() {
417
- let source = r#"
418
- class Foo
419
- def bar
420
- "hello"
421
- end
422
- end
423
- "#;
424
- let genv = analyze(source);
425
- let info = genv.resolve_method(&Type::instance("Foo"), "bar").unwrap();
426
- let param_vtxs = info.param_vertices.as_ref().unwrap();
427
- assert!(param_vtxs.is_empty());
428
- }
429
- }
@@ -23,91 +23,3 @@ pub(crate) fn process_parentheses_node(
23
23
  install_node(genv, lenv, changes, source, &body)
24
24
  }
25
25
  }
26
-
27
- #[cfg(test)]
28
- mod tests {
29
- use crate::analyzer::install::AstInstaller;
30
- use crate::env::{GlobalEnv, LocalEnv};
31
- use crate::graph::VertexId;
32
- use crate::parser::ParseSession;
33
- use crate::types::Type;
34
-
35
- fn analyze(source: &str) -> GlobalEnv {
36
- let session = ParseSession::new();
37
- let parse_result = session.parse_source(source, "test.rb").unwrap();
38
- let root = parse_result.node();
39
- let program = root.as_program_node().unwrap();
40
-
41
- let mut genv = GlobalEnv::new();
42
- let mut lenv = LocalEnv::new();
43
-
44
- let mut installer = AstInstaller::new(&mut genv, &mut lenv, source);
45
- for stmt in &program.statements().body() {
46
- installer.install_node(&stmt);
47
- }
48
- installer.finish();
49
-
50
- genv
51
- }
52
-
53
- fn get_type_show(genv: &GlobalEnv, vtx: VertexId) -> String {
54
- if let Some(vertex) = genv.get_vertex(vtx) {
55
- vertex.show()
56
- } else if let Some(source) = genv.get_source(vtx) {
57
- source.ty.show()
58
- } else {
59
- panic!("vertex {:?} not found as either Vertex or Source", vtx);
60
- }
61
- }
62
-
63
- #[test]
64
- fn test_parenthesized_integer() {
65
- let source = r#"
66
- class Foo
67
- def bar
68
- x = (42)
69
- end
70
- end
71
- "#;
72
- let genv = analyze(source);
73
- let info = genv
74
- .resolve_method(&Type::instance("Foo"), "bar")
75
- .expect("Foo#bar should be registered");
76
- let ret_vtx = info.return_vertex.unwrap();
77
- assert_eq!(get_type_show(&genv, ret_vtx), "Integer");
78
- }
79
-
80
- #[test]
81
- fn test_parenthesized_string() {
82
- let source = r#"
83
- class Foo
84
- def bar
85
- x = ("hello")
86
- end
87
- end
88
- "#;
89
- let genv = analyze(source);
90
- let info = genv
91
- .resolve_method(&Type::instance("Foo"), "bar")
92
- .expect("Foo#bar should be registered");
93
- let ret_vtx = info.return_vertex.unwrap();
94
- assert_eq!(get_type_show(&genv, ret_vtx), "String");
95
- }
96
-
97
- #[test]
98
- fn test_parenthesized_multiple_statements() {
99
- let source = r#"
100
- class Foo
101
- def bar
102
- x = (a = 1; "hello")
103
- end
104
- end
105
- "#;
106
- let genv = analyze(source);
107
- let info = genv
108
- .resolve_method(&Type::instance("Foo"), "bar")
109
- .expect("Foo#bar should be registered");
110
- let ret_vtx = info.return_vertex.unwrap();
111
- assert_eq!(get_type_show(&genv, ret_vtx), "String");
112
- }
113
- }