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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +9 -11
- data/core/Cargo.toml +1 -1
- data/core/src/analyzer/assignments.rs +0 -280
- data/core/src/analyzer/blocks.rs +0 -190
- data/core/src/analyzer/calls.rs +3 -32
- data/core/src/analyzer/conditionals.rs +0 -348
- data/core/src/analyzer/definitions.rs +11 -526
- data/core/src/analyzer/dispatch.rs +54 -1000
- data/core/src/analyzer/exceptions.rs +0 -454
- data/core/src/analyzer/literals.rs +0 -54
- data/core/src/analyzer/loops.rs +0 -207
- data/core/src/analyzer/mod.rs +0 -15
- data/core/src/analyzer/operators.rs +0 -205
- data/core/src/analyzer/parameters.rs +4 -227
- data/core/src/analyzer/parentheses.rs +0 -88
- data/core/src/analyzer/returns.rs +0 -152
- data/core/src/analyzer/super_calls.rs +1 -212
- data/core/src/analyzer/variables.rs +5 -25
- data/core/src/checker.rs +0 -13
- data/core/src/diagnostics/diagnostic.rs +0 -41
- data/core/src/diagnostics/formatter.rs +0 -38
- data/core/src/env/box_manager.rs +0 -30
- data/core/src/env/global_env.rs +52 -79
- data/core/src/env/local_env.rs +0 -50
- data/core/src/env/method_registry.rs +52 -233
- data/core/src/env/scope.rs +0 -375
- data/core/src/env/vertex_manager.rs +0 -73
- data/core/src/graph/box.rs +20 -439
- data/core/src/graph/change_set.rs +0 -65
- data/core/src/graph/vertex.rs +0 -69
- data/core/src/parser.rs +0 -77
- data/ext/Cargo.toml +1 -1
- data/lib/methodray/version.rb +1 -1
- metadata +5 -4
data/core/src/analyzer/mod.rs
CHANGED
|
@@ -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
|
-
}
|