mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
fix AST for if expressions
then is not always a block...
This commit is contained in:
parent
2d337c88b0
commit
619af1e22c
6 changed files with 112 additions and 5 deletions
|
@ -498,7 +498,13 @@ impl ExprCollector {
|
||||||
let then_branch = self.collect_block_opt(e.then_branch());
|
let then_branch = self.collect_block_opt(e.then_branch());
|
||||||
let else_branch = e
|
let else_branch = e
|
||||||
.else_branch()
|
.else_branch()
|
||||||
.map(|e| self.collect_block(e))
|
.map(|b| match b {
|
||||||
|
ast::ElseBranchFlavor::Block(it) => self.collect_block(it),
|
||||||
|
ast::ElseBranchFlavor::IfExpr(elif) => {
|
||||||
|
let expr: &ast::Expr = ast::Expr::cast(elif.syntax()).unwrap();
|
||||||
|
self.collect_expr(expr)
|
||||||
|
}
|
||||||
|
})
|
||||||
.unwrap_or_else(|| self.empty_block());
|
.unwrap_or_else(|| self.empty_block());
|
||||||
let placeholder_pat = self.pats.alloc(Pat::Missing);
|
let placeholder_pat = self.pats.alloc(Pat::Missing);
|
||||||
let arms = vec![
|
let arms = vec![
|
||||||
|
@ -521,7 +527,13 @@ impl ExprCollector {
|
||||||
} else {
|
} else {
|
||||||
let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr()));
|
let condition = self.collect_expr_opt(e.condition().and_then(|c| c.expr()));
|
||||||
let then_branch = self.collect_block_opt(e.then_branch());
|
let then_branch = self.collect_block_opt(e.then_branch());
|
||||||
let else_branch = e.else_branch().map(|e| self.collect_block(e));
|
let else_branch = e.else_branch().map(|b| match b {
|
||||||
|
ast::ElseBranchFlavor::Block(it) => self.collect_block(it),
|
||||||
|
ast::ElseBranchFlavor::IfExpr(elif) => {
|
||||||
|
let expr: &ast::Expr = ast::Expr::cast(elif.syntax()).unwrap();
|
||||||
|
self.collect_expr(expr)
|
||||||
|
}
|
||||||
|
});
|
||||||
self.alloc_expr(
|
self.alloc_expr(
|
||||||
Expr::If {
|
Expr::If {
|
||||||
condition,
|
condition,
|
||||||
|
|
17
crates/ra_hir/src/ty/snapshots/tests__infer_in_elseif.snap
Normal file
17
crates/ra_hir/src/ty/snapshots/tests__infer_in_elseif.snap
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
created: "2019-01-26T21:36:52.714121185+00:00"
|
||||||
|
creator: insta@0.5.2
|
||||||
|
expression: "&result"
|
||||||
|
source: crates/ra_hir/src/ty/tests.rs
|
||||||
|
---
|
||||||
|
[35; 38) 'foo': Foo
|
||||||
|
[45; 109) '{ ... } }': ()
|
||||||
|
[51; 107) 'if tru... }': ()
|
||||||
|
[54; 58) 'true': bool
|
||||||
|
[59; 67) '{ }': ()
|
||||||
|
[73; 107) 'if fal... }': i32
|
||||||
|
[76; 81) 'false': bool
|
||||||
|
[82; 107) '{ ... }': i32
|
||||||
|
[92; 95) 'foo': Foo
|
||||||
|
[92; 101) 'foo.field': i32
|
||||||
|
|
|
@ -284,6 +284,23 @@ fn test() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_in_elseif() {
|
||||||
|
check_inference(
|
||||||
|
"infer_in_elseif",
|
||||||
|
r#"
|
||||||
|
struct Foo { field: i32 }
|
||||||
|
fn main(foo: Foo) {
|
||||||
|
if true {
|
||||||
|
|
||||||
|
} else if false {
|
||||||
|
foo.field
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_inherent_method() {
|
fn infer_inherent_method() {
|
||||||
check_inference(
|
check_inference(
|
||||||
|
|
|
@ -11,7 +11,10 @@ pub fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> {
|
||||||
let pat = cond.pat()?;
|
let pat = cond.pat()?;
|
||||||
let expr = cond.expr()?;
|
let expr = cond.expr()?;
|
||||||
let then_block = if_expr.then_branch()?;
|
let then_block = if_expr.then_branch()?;
|
||||||
let else_block = if_expr.else_branch()?;
|
let else_block = match if_expr.else_branch()? {
|
||||||
|
ast::ElseBranchFlavor::Block(it) => it,
|
||||||
|
ast::ElseBranchFlavor::IfExpr(_) => return None,
|
||||||
|
};
|
||||||
|
|
||||||
ctx.build("replace with match", |edit| {
|
ctx.build("replace with match", |edit| {
|
||||||
let match_expr = build_match_expr(expr, pat, then_block, else_block);
|
let match_expr = build_match_expr(expr, pat, then_block, else_block);
|
||||||
|
|
|
@ -285,13 +285,27 @@ impl LetStmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum ElseBranchFlavor<'a> {
|
||||||
|
Block(&'a Block),
|
||||||
|
IfExpr(&'a IfExpr),
|
||||||
|
}
|
||||||
|
|
||||||
impl IfExpr {
|
impl IfExpr {
|
||||||
pub fn then_branch(&self) -> Option<&Block> {
|
pub fn then_branch(&self) -> Option<&Block> {
|
||||||
self.blocks().nth(0)
|
self.blocks().nth(0)
|
||||||
}
|
}
|
||||||
pub fn else_branch(&self) -> Option<&Block> {
|
pub fn else_branch(&self) -> Option<ElseBranchFlavor> {
|
||||||
self.blocks().nth(1)
|
let res = match self.blocks().nth(1) {
|
||||||
|
Some(block) => ElseBranchFlavor::Block(block),
|
||||||
|
None => {
|
||||||
|
let elif: &IfExpr = child_opt(self)?;
|
||||||
|
ElseBranchFlavor::IfExpr(elif)
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
|
||||||
fn blocks(&self) -> AstChildren<Block> {
|
fn blocks(&self) -> AstChildren<Block> {
|
||||||
children(self)
|
children(self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -660,6 +660,50 @@ impl ToOwned for DynTraitType {
|
||||||
|
|
||||||
impl DynTraitType {}
|
impl DynTraitType {}
|
||||||
|
|
||||||
|
// ElseBranch
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct ElseBranch {
|
||||||
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
}
|
||||||
|
unsafe impl TransparentNewType for ElseBranch {
|
||||||
|
type Repr = rowan::SyntaxNode<RaTypes>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum ElseBranchKind<'a> {
|
||||||
|
Block(&'a Block),
|
||||||
|
IfExpr(&'a IfExpr),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AstNode for ElseBranch {
|
||||||
|
fn cast(syntax: &SyntaxNode) -> Option<&Self> {
|
||||||
|
match syntax.kind() {
|
||||||
|
| BLOCK
|
||||||
|
| IF_EXPR => Some(ElseBranch::from_repr(syntax.into_repr())),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToOwned for ElseBranch {
|
||||||
|
type Owned = TreeArc<ElseBranch>;
|
||||||
|
fn to_owned(&self) -> TreeArc<ElseBranch> { TreeArc::cast(self.syntax.to_owned()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ElseBranch {
|
||||||
|
pub fn kind(&self) -> ElseBranchKind {
|
||||||
|
match self.syntax.kind() {
|
||||||
|
BLOCK => ElseBranchKind::Block(Block::cast(&self.syntax).unwrap()),
|
||||||
|
IF_EXPR => ElseBranchKind::IfExpr(IfExpr::cast(&self.syntax).unwrap()),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ElseBranch {}
|
||||||
|
|
||||||
// EnumDef
|
// EnumDef
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
|
Loading…
Reference in a new issue