Skip to content

Commit 702191c

Browse files
1.2系列提交: 在lib中新增iter()调用判别函数, 并正确应用到集合推导式中(新增visit依赖)
1 parent bcf4a4c commit 702191c

File tree

4 files changed

+68
-11
lines changed

4 files changed

+68
-11
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ repository = "https://github.com/Natural-selection1/better-comprehension-in-rust
1414
readme = "README.md"
1515
version = "1.1.0"
1616
edition = "2024"
17-
exclude = ["src/main.rs", "target", ".vscode", "README-CN.md",".gitignore"]
17+
exclude = ["src/main.rs", "target", ".vscode", "README-CN.md", ".gitignore"]
1818

1919

2020
[lib]
2121
proc-macro = true
2222

2323
[dependencies]
24-
syn = { version = "2.0.100", features = ["full", "extra-traits"] }
24+
syn = { version = "2.0.100", features = ["full", "visit", "extra-traits"] }
2525
quote = "1.0.40"
2626
proc-macro2 = "1.0.94"

src/eager_evaluation.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,18 @@ pub(crate) fn handle_nested_loops<'a>(
4343
need_to_shadow.push(iterable);
4444
quote! { &#iterable }
4545
}
46-
Expr::MethodCall(method_call) => {
47-
let method_name = &method_call.method;
48-
if method_name == "iter" {
49-
quote! { #iterable }
50-
} else {
51-
panic!("不支持的类型: {:?}", iterable);
52-
}
53-
}
46+
Expr::MethodCall(_) => match crate::is_iter(iterable) {
47+
true => quote! { #iterable },
48+
_ => panic!(
49+
"please ensure the first method call is iter(): {:?}",
50+
iterable
51+
),
52+
},
5453
Expr::Paren(expr) => {
5554
let iterable = &*expr.expr;
5655
quote! { #iterable }
5756
}
58-
_ => panic!("不支持的类型: {:?}", iterable),
57+
_ => panic!("type is not supported: {:?}", iterable),
5958
};
6059

6160
// 根据是否有if条件生成循环代码

src/lib.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@
267267
//!
268268
//! b_tree_map! : insert() to add key-value pairs
269269
270+
// #![allow(unused, dead_code)]
270271
use proc_macro::TokenStream as TS;
271272

272273
mod eager_evaluation;
@@ -344,3 +345,43 @@ pub(crate) fn common_parse(
344345

345346
(mapping, iter_clauses)
346347
}
348+
349+
struct IterMethodCallFinder {
350+
is_iter: bool,
351+
}
352+
353+
use syn::{ExprMethodCall, visit::Visit};
354+
impl<'ast> Visit<'ast> for IterMethodCallFinder {
355+
fn visit_expr_method_call(&mut self, node: &'ast ExprMethodCall) {
356+
match *node.receiver {
357+
syn::Expr::Path(_) => {
358+
if node.method == "iter" {
359+
self.is_iter = true;
360+
}
361+
}
362+
_ => syn::visit::visit_expr(&mut *self, &node.receiver),
363+
}
364+
}
365+
}
366+
367+
pub(crate) fn is_iter(expr: &syn::Expr) -> bool {
368+
let mut finder = IterMethodCallFinder { is_iter: false };
369+
finder.visit_expr(expr);
370+
371+
finder.is_iter
372+
}
373+
374+
#[test]
375+
fn test_is_iter() {
376+
// 最右侧是iter方法
377+
let expr = syn::parse_quote!(some.method_1().method_2().iter());
378+
assert!(!is_iter(&expr));
379+
eprintln!("--------------------------------");
380+
// 最左侧是iter方法
381+
let expr = syn::parse_quote!(some.iter().method_3().method_4());
382+
assert!(is_iter(&expr));
383+
eprintln!("--------------------------------");
384+
385+
let expr = syn::parse_quote!(some.method_5().iter().method_6());
386+
assert!(!is_iter(&expr));
387+
}

src/main.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ fn main() {
1818
test_pattern_matching();
1919
test_nested_comprehension();
2020
test_ownership_handling();
21+
test_option();
2122
}
2223

2324
fn test_vec() {
@@ -350,3 +351,19 @@ fn test_ref_iterator() {
350351
assert_eq!(vec_1.len(), 3);
351352
assert_eq!(vec_2.len(), 3);
352353
}
354+
355+
fn test_option() {
356+
let vec = [Some("1".to_string()), None, Some("3".to_string())];
357+
358+
let _result = vector![
359+
x.clone()
360+
for x in vec.iter().flatten()
361+
];
362+
363+
let mut result = Vec::new();
364+
for x in vec.iter().flatten() {
365+
result.push(x.clone());
366+
}
367+
368+
assert_eq!(result, vec!["1".to_string(), "3".to_string()]);
369+
}

0 commit comments

Comments
 (0)