Skip to content

Commit e010f46

Browse files
committed
Support else completion for more expressions
- Support else completion in ArrayExpr, ReturnExpr and PrefixExpr etc - Support else completion after MatchArm expression Before this PR, the else branch could not be completed in most expressions Example --- ```rust fn foo() -> [i32; 1] { [if true { 2 } $0] } ``` -> ```rust fn foo() -> [i32; 1] { [if true { 2 } else { $0 }] } ``` --- ```rust fn foo() -> i32 { match () { () => if true { 2 } $0 } } ``` -> ```rust fn foo() -> i32 { match () { () => if true { 2 } else { $0 } } } ```
1 parent db0420c commit e010f46

File tree

4 files changed

+312
-5
lines changed

4 files changed

+312
-5
lines changed

crates/ide-completion/src/completions/pattern.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ pub(crate) fn complete_pattern(
4242
}
4343
}
4444

45+
if pattern_ctx.after_if_expr {
46+
add_keyword("else", "else {\n $0\n}");
47+
add_keyword("else if", "else if $1 {\n $0\n}");
48+
}
49+
4550
if pattern_ctx.record_pat.is_some() {
4651
return;
4752
}

crates/ide-completion/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ pub(crate) struct PatternContext {
276276
pub(crate) param_ctx: Option<ParamContext>,
277277
pub(crate) has_type_ascription: bool,
278278
pub(crate) should_suggest_name: bool,
279+
pub(crate) after_if_expr: bool,
279280
pub(crate) parent_pat: Option<ast::Pat>,
280281
pub(crate) ref_token: Option<SyntaxToken>,
281282
pub(crate) mut_token: Option<SyntaxToken>,

crates/ide-completion/src/context/analysis.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -963,10 +963,6 @@ fn classify_name_ref<'db>(
963963
}
964964
}
965965
};
966-
let after_if_expr = |node: SyntaxNode| {
967-
let prev_expr = prev_expr(node);
968-
matches!(prev_expr, Some(ast::Expr::IfExpr(_)))
969-
};
970966
let after_incomplete_let = |node: SyntaxNode| {
971967
prev_expr(node).and_then(|it| it.syntax().parent()).and_then(ast::LetStmt::cast)
972968
};
@@ -1214,7 +1210,7 @@ fn classify_name_ref<'db>(
12141210
let it = expr.syntax();
12151211
let in_block_expr = is_in_block(it);
12161212
let in_loop_body = is_in_breakable(it);
1217-
let after_if_expr = after_if_expr(it.clone());
1213+
let after_if_expr = is_after_if_expr(it.clone());
12181214
let ref_expr_parent =
12191215
path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
12201216
let after_amp = non_trivia_sibling(it.clone().into(), Direction::Prev)
@@ -1726,6 +1722,7 @@ fn pattern_context_for(
17261722
param_ctx,
17271723
has_type_ascription,
17281724
should_suggest_name,
1725+
after_if_expr: is_after_if_expr(pat.syntax().clone()),
17291726
parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
17301727
mut_token,
17311728
ref_token,
@@ -1870,6 +1867,18 @@ fn is_in_block(node: &SyntaxNode) -> bool {
18701867
.unwrap_or(false)
18711868
}
18721869

1870+
fn is_after_if_expr(node: SyntaxNode) -> bool {
1871+
let node = match node.parent().and_then(Either::<ast::ExprStmt, ast::MatchArm>::cast) {
1872+
Some(stmt) => stmt.syntax().clone(),
1873+
None => node,
1874+
};
1875+
let prev_sibling =
1876+
non_trivia_sibling(node.into(), Direction::Prev).and_then(NodeOrToken::into_node);
1877+
iter::successors(prev_sibling, |it| it.last_child_or_token()?.into_node())
1878+
.find_map(ast::IfExpr::cast)
1879+
.is_some()
1880+
}
1881+
18731882
fn next_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken> {
18741883
let mut token = match e.into() {
18751884
SyntaxElement::Node(n) => n.last_token()?,

crates/ide-completion/src/tests/expression.rs

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,298 @@ fn foo() { let x = if foo {} $0 else {}; }
17061706
sn ppd
17071707
"#]],
17081708
);
1709+
check(
1710+
r#"
1711+
fn foo() { [if foo {} $0]}
1712+
"#,
1713+
expect![[r#"
1714+
fn foo() fn()
1715+
bt u32 u32
1716+
kw async
1717+
kw const
1718+
kw crate::
1719+
kw else
1720+
kw else if
1721+
kw enum
1722+
kw extern
1723+
kw false
1724+
kw fn
1725+
kw for
1726+
kw if
1727+
kw if let
1728+
kw impl
1729+
kw impl for
1730+
kw let
1731+
kw letm
1732+
kw loop
1733+
kw match
1734+
kw mod
1735+
kw return
1736+
kw self::
1737+
kw static
1738+
kw struct
1739+
kw trait
1740+
kw true
1741+
kw type
1742+
kw union
1743+
kw unsafe
1744+
kw use
1745+
kw while
1746+
kw while let
1747+
sn macro_rules
1748+
sn pd
1749+
sn ppd
1750+
"#]],
1751+
);
1752+
check(
1753+
r#"
1754+
fn foo() { [if foo {} el$0]}
1755+
"#,
1756+
expect![[r#"
1757+
fn foo() fn()
1758+
bt u32 u32
1759+
kw async
1760+
kw const
1761+
kw crate::
1762+
kw else
1763+
kw else if
1764+
kw enum
1765+
kw extern
1766+
kw false
1767+
kw fn
1768+
kw for
1769+
kw if
1770+
kw if let
1771+
kw impl
1772+
kw impl for
1773+
kw let
1774+
kw letm
1775+
kw loop
1776+
kw match
1777+
kw mod
1778+
kw return
1779+
kw self::
1780+
kw static
1781+
kw struct
1782+
kw trait
1783+
kw true
1784+
kw type
1785+
kw union
1786+
kw unsafe
1787+
kw use
1788+
kw while
1789+
kw while let
1790+
sn macro_rules
1791+
sn pd
1792+
sn ppd
1793+
"#]],
1794+
);
1795+
check(
1796+
r#"
1797+
fn foo() { 2 + if foo {} $0 }
1798+
"#,
1799+
expect![[r#"
1800+
fn foo() fn()
1801+
bt u32 u32
1802+
kw async
1803+
kw const
1804+
kw crate::
1805+
kw else
1806+
kw else if
1807+
kw enum
1808+
kw extern
1809+
kw false
1810+
kw fn
1811+
kw for
1812+
kw if
1813+
kw if let
1814+
kw impl
1815+
kw impl for
1816+
kw let
1817+
kw letm
1818+
kw loop
1819+
kw match
1820+
kw mod
1821+
kw return
1822+
kw self::
1823+
kw static
1824+
kw struct
1825+
kw trait
1826+
kw true
1827+
kw type
1828+
kw union
1829+
kw unsafe
1830+
kw use
1831+
kw while
1832+
kw while let
1833+
sn macro_rules
1834+
sn pd
1835+
sn ppd
1836+
"#]],
1837+
);
1838+
check(
1839+
r#"
1840+
fn foo() { -if foo {} $0 }
1841+
"#,
1842+
expect![[r#"
1843+
fn foo() fn()
1844+
bt u32 u32
1845+
kw async
1846+
kw const
1847+
kw crate::
1848+
kw else
1849+
kw else if
1850+
kw enum
1851+
kw extern
1852+
kw false
1853+
kw fn
1854+
kw for
1855+
kw if
1856+
kw if let
1857+
kw impl
1858+
kw impl for
1859+
kw let
1860+
kw letm
1861+
kw loop
1862+
kw match
1863+
kw mod
1864+
kw return
1865+
kw self::
1866+
kw static
1867+
kw struct
1868+
kw trait
1869+
kw true
1870+
kw type
1871+
kw union
1872+
kw unsafe
1873+
kw use
1874+
kw while
1875+
kw while let
1876+
sn macro_rules
1877+
sn pd
1878+
sn ppd
1879+
"#]],
1880+
);
1881+
check(
1882+
r#"
1883+
fn foo() { &mut if foo {} $0 }
1884+
"#,
1885+
expect![[r#"
1886+
fn foo() fn()
1887+
bt u32 u32
1888+
kw async
1889+
kw const
1890+
kw crate::
1891+
kw else
1892+
kw else if
1893+
kw enum
1894+
kw extern
1895+
kw false
1896+
kw fn
1897+
kw for
1898+
kw if
1899+
kw if let
1900+
kw impl
1901+
kw impl for
1902+
kw let
1903+
kw letm
1904+
kw loop
1905+
kw match
1906+
kw mod
1907+
kw return
1908+
kw self::
1909+
kw static
1910+
kw struct
1911+
kw trait
1912+
kw true
1913+
kw type
1914+
kw union
1915+
kw unsafe
1916+
kw use
1917+
kw while
1918+
kw while let
1919+
sn macro_rules
1920+
sn pd
1921+
sn ppd
1922+
"#]],
1923+
);
1924+
check(
1925+
r#"
1926+
fn foo() { return if foo {} $0 }
1927+
"#,
1928+
expect![[r#"
1929+
fn foo() fn()
1930+
bt u32 u32
1931+
kw async
1932+
kw const
1933+
kw crate::
1934+
kw else
1935+
kw else if
1936+
kw enum
1937+
kw extern
1938+
kw false
1939+
kw fn
1940+
kw for
1941+
kw if
1942+
kw if let
1943+
kw impl
1944+
kw impl for
1945+
kw let
1946+
kw letm
1947+
kw loop
1948+
kw match
1949+
kw mod
1950+
kw return
1951+
kw self::
1952+
kw static
1953+
kw struct
1954+
kw trait
1955+
kw true
1956+
kw type
1957+
kw union
1958+
kw unsafe
1959+
kw use
1960+
kw while
1961+
kw while let
1962+
sn macro_rules
1963+
sn pd
1964+
sn ppd
1965+
"#]],
1966+
);
1967+
check(
1968+
r#"
1969+
fn foo() { match () { () => if foo {} $0 } }
1970+
"#,
1971+
expect![[r#"
1972+
kw else
1973+
kw else if
1974+
kw mut
1975+
kw ref
1976+
"#]],
1977+
);
1978+
check(
1979+
r#"
1980+
fn foo() { match () { () => if foo {} $0, } }
1981+
"#,
1982+
expect![[r#"
1983+
kw else
1984+
kw else if
1985+
kw mut
1986+
kw ref
1987+
"#]],
1988+
);
1989+
check(
1990+
r#"
1991+
fn foo() { match () { () => if foo {} $0, _ => (), } }
1992+
"#,
1993+
expect![[r#"
1994+
kw else
1995+
kw else if
1996+
kw mut
1997+
kw ref
1998+
"#]],
1999+
);
2000+
// FIXME: support else completion after ast::RecordExprField
17092001
}
17102002

17112003
#[test]

0 commit comments

Comments
 (0)