-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement any_over_expr
for type alias and type params
#5866
Conversation
PR Check ResultsEcosystem✅ ecosystem check detected no changes. BenchmarkLinux
Windows
|
@@ -1746,4 +1778,118 @@ y = 2 | |||
|
|||
Ok(()) | |||
} | |||
|
|||
#[test] | |||
fn any_over_stmt_type_alias() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is a bit contrived but I'd appreciate any general Rust feedback as I'm using it for practice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine. Or let's say, it's what the API allows you to do. You could have considered changing the Fn
to FnMut
so that you don't need to use RefCell
(I guess it was a good learning opportunity ;)).
I'm normally too lazy to bother with building the tree manually and instead parse the source code. Now, using the source code makes asserting a bit annoying because you don't have access to the node instances. That's where you could collect NodeKind
s instead (you can get the kind by calling AnyNodeRef::from(expr).kind()
). However, NodeKind
only works if you never have to distinguish between two nodes of the same kind. Here some tests that I wrote that use NodeKind
.
ruff/crates/ruff_python_ast/src/visitor/preorder.rs
Lines 955 to 1039 in 5d41c83
#[test] | |
fn function_arguments() { | |
let source = r#"def a(b, c,/, d, e = 20, *args, named=5, other=20, **kwargs): pass"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn function_positional_only_with_default() { | |
let source = r#"def a(b, c = 34,/, e = 20, *args): pass"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn compare() { | |
let source = r#"4 < x < 5"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn list_comprehension() { | |
let source = "[x for x in numbers]"; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn dict_comprehension() { | |
let source = "{x: x**2 for x in numbers}"; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn set_comprehension() { | |
let source = "{x for x in numbers}"; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn match_class_pattern() { | |
let source = r#" | |
match x: | |
case Point2D(0, 0): | |
... | |
case Point3D(x=0, y=0, z=0): | |
... | |
"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn decorators() { | |
let source = r#" | |
@decorator | |
def a(): | |
pass | |
@test | |
class A: | |
pass | |
"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} |
With an example snapshot
Lines 1 to 15 in 5d41c83
--- | |
source: crates/ruff_python_ast/src/visitor/preorder.rs | |
expression: trace | |
--- | |
- ModModule | |
- StmtExpr | |
- ExprCompare | |
- ExprConstant | |
- Int(4) | |
- Lt | |
- ExprName | |
- Lt | |
- ExprConstant | |
- Int(5) | |
That said. I think what you have is good. The only thing I'm not a 100% sure of is if I would bother refactoring this test if I ever end up breaking it (thinking about added value / maintenance cost)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking a look!
You could have considered changing the Fn to FnMut
It seems wrong to change the API just for testing.
I'm not a 100% sure of is if I would bother refactoring this test if I ever end up breaking it
Definitely. That's kind of what I was getting at with it being a bit contrived.
I'm normally too lazy to bother with building the tree manually and instead parse the source code.
Ah that's very wise. I feel like that's much more maintainable. I'll look into doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh this is kind of hard to do. I'd rather address it in a follow-up or next time someone wants to add a test here.
@@ -1746,4 +1778,118 @@ y = 2 | |||
|
|||
Ok(()) | |||
} | |||
|
|||
#[test] | |||
fn any_over_stmt_type_alias() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine. Or let's say, it's what the API allows you to do. You could have considered changing the Fn
to FnMut
so that you don't need to use RefCell
(I guess it was a good learning opportunity ;)).
I'm normally too lazy to bother with building the tree manually and instead parse the source code. Now, using the source code makes asserting a bit annoying because you don't have access to the node instances. That's where you could collect NodeKind
s instead (you can get the kind by calling AnyNodeRef::from(expr).kind()
). However, NodeKind
only works if you never have to distinguish between two nodes of the same kind. Here some tests that I wrote that use NodeKind
.
ruff/crates/ruff_python_ast/src/visitor/preorder.rs
Lines 955 to 1039 in 5d41c83
#[test] | |
fn function_arguments() { | |
let source = r#"def a(b, c,/, d, e = 20, *args, named=5, other=20, **kwargs): pass"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn function_positional_only_with_default() { | |
let source = r#"def a(b, c = 34,/, e = 20, *args): pass"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn compare() { | |
let source = r#"4 < x < 5"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn list_comprehension() { | |
let source = "[x for x in numbers]"; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn dict_comprehension() { | |
let source = "{x: x**2 for x in numbers}"; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn set_comprehension() { | |
let source = "{x for x in numbers}"; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn match_class_pattern() { | |
let source = r#" | |
match x: | |
case Point2D(0, 0): | |
... | |
case Point3D(x=0, y=0, z=0): | |
... | |
"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} | |
#[test] | |
fn decorators() { | |
let source = r#" | |
@decorator | |
def a(): | |
pass | |
@test | |
class A: | |
pass | |
"#; | |
let trace = trace_preorder_visitation(source); | |
assert_snapshot!(trace); | |
} |
With an example snapshot
Lines 1 to 15 in 5d41c83
--- | |
source: crates/ruff_python_ast/src/visitor/preorder.rs | |
expression: trace | |
--- | |
- ModModule | |
- StmtExpr | |
- ExprCompare | |
- ExprConstant | |
- Int(4) | |
- Lt | |
- ExprName | |
- Lt | |
- ExprConstant | |
- Int(5) | |
That said. I think what you have is good. The only thing I'm not a 100% sure of is if I would bother refactoring this test if I ever end up breaking it (thinking about added value / maintenance cost)
Part of #5062