fix: Correctly check for parentheses redundancy in `remove_parentheses` assist b...
source link: https://github.com/rust-lang/rust-analyzer/pull/13764
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Correctly check for parentheses redundancy in `remove_parentheses` assist by WaffleLapkin · Pull Request #13764 · rust-lang/rust-analyzer · GitHub
Member
WaffleLapkin commented Dec 13, 2022
This is quite a bunch of code and some hacks, but I think this time it's correct.
I've added a lot of tests, most of which fail with the assist impl from #13733 :')
added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label
Outdated
ast::StmtList(_) => self.needs_parens_in_stmt(None), |
||
ast::ArgList(_) => false, |
||
ast::MatchArm(_) => false, |
||
_ => unimplemented!() |
I feel like this should just be false? unimplmented seems wrong since other nodes don't make sense here right?
Yeah, right. This was left from the time I was testing things out and haven't figured out possible parents.
fixed :)
return contains_exterior_struct_lit_inner(self).is_some(); |
||
fn contains_exterior_struct_lit_inner(expr: &Expr) -> Option<()> { |
||
use Expr::*; |
||
match expr { |
||
RecordExpr(..) => Some(()), |
||
// X { y: 1 } + X { y: 2 } |
||
BinExpr(e) => e |
||
.lhs() |
||
.as_ref() |
||
.and_then(contains_exterior_struct_lit_inner) |
||
.or_else(|| e.rhs().as_ref().and_then(contains_exterior_struct_lit_inner)), |
||
// `&X { y: 1 }`, `X { y: 1 }.y`, `X { y: 1 }.bar(...)`, etc |
||
IndexExpr(e) => contains_exterior_struct_lit_inner(&e.base()?), |
||
AwaitExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), |
||
PrefixExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), |
||
CastExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), |
||
FieldExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), |
||
MethodCallExpr(e) => contains_exterior_struct_lit_inner(&e.receiver()?), |
||
_ => None, |
||
} |
||
} |
This could use a poor-mans try block aka immediately called closure
return contains_exterior_struct_lit_inner(self).is_some(); | |
fn contains_exterior_struct_lit_inner(expr: &Expr) -> Option<()> { | |
use Expr::*; | |
match expr { | |
RecordExpr(..) => Some(()), | |
// X { y: 1 } + X { y: 2 } | |
BinExpr(e) => e | |
.lhs() | |
.as_ref() | |
.and_then(contains_exterior_struct_lit_inner) | |
.or_else(|| e.rhs().as_ref().and_then(contains_exterior_struct_lit_inner)), | |
// `&X { y: 1 }`, `X { y: 1 }.y`, `X { y: 1 }.bar(...)`, etc | |
IndexExpr(e) => contains_exterior_struct_lit_inner(&e.base()?), | |
AwaitExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), | |
PrefixExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), | |
CastExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), | |
FieldExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), | |
MethodCallExpr(e) => contains_exterior_struct_lit_inner(&e.receiver()?), | |
_ => None, | |
} | |
} | |
(|| { | |
use Expr::*; | |
match expr { | |
RecordExpr(..) => Some(()), | |
// X { y: 1 } + X { y: 2 } | |
BinExpr(e) => e | |
.lhs() | |
.as_ref() | |
.and_then(contains_exterior_struct_lit_inner) | |
.or_else(|| e.rhs().as_ref().and_then(contains_exterior_struct_lit_inner)), | |
// `&X { y: 1 }`, `X { y: 1 }.y`, `X { y: 1 }.bar(...)`, etc | |
IndexExpr(e) => contains_exterior_struct_lit_inner(&e.base()?), | |
AwaitExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), | |
PrefixExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), | |
CastExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), | |
FieldExpr(e) => contains_exterior_struct_lit_inner(&e.expr()?), | |
MethodCallExpr(e) => contains_exterior_struct_lit_inner(&e.receiver()?), | |
_ => None, | |
} | |
})().is_some() |
It kind of makes the code worse, since the recursive calls return bool
that needs to be converted back to Option
...
fn contains_exterior_struct_lit(&self) -> bool {
(|| {
use Expr::*;
(match self {
RecordExpr(..) => true,
// X { y: 1 } + X { y: 2 }
BinExpr(e) => {
return e
.lhs()
.as_ref()
.filter(|e| e.contains_exterior_struct_lit())
.map(drop)
.or_else(|| {
e.rhs().as_ref().filter(|e| e.contains_exterior_struct_lit()).map(drop)
})
}
// `&X { y: 1 }`, `X { y: 1 }.y`, `X { y: 1 }.bar(...)`, etc
IndexExpr(e) => e.base()?.contains_exterior_struct_lit(),
AwaitExpr(e) => e.expr()?.contains_exterior_struct_lit(),
PrefixExpr(e) => e.expr()?.contains_exterior_struct_lit(),
CastExpr(e) => e.expr()?.contains_exterior_struct_lit(),
FieldExpr(e) => e.expr()?.contains_exterior_struct_lit(),
MethodCallExpr(e) => e.receiver()?.contains_exterior_struct_lit(),
_ => return None,
})
.then(|| ())
})()
.is_some()
}
Oh thats a good point, nvm
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK