Skip to content

Commit 7f2ac29

Browse files
committed
Auto merge of rust-lang#14938 - Veykril:sig-help, r=Veykril
Add signature help for tuple patterns and expressions ~~These are somewhat wonky since their signature changes as you type depending on context but they help out nevertheless.~~ should be less wonky now with added parser and lowering recoveries
2 parents bafa6c4 + 0e28202 commit 7f2ac29

File tree

8 files changed

+518
-34
lines changed

8 files changed

+518
-34
lines changed

crates/hir-def/src/body/lower.rs

+34-6
Original file line numberDiff line numberDiff line change
@@ -542,9 +542,18 @@ impl ExprCollector<'_> {
542542
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
543543
}
544544
ast::Expr::TupleExpr(e) => {
545-
let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
545+
let mut exprs: Vec<_> = e.fields().map(|expr| self.collect_expr(expr)).collect();
546+
// if there is a leading comma, the user is most likely to type out a leading expression
547+
// so we insert a missing expression at the beginning for IDE features
548+
if comma_follows_token(e.l_paren_token()) {
549+
exprs.insert(0, self.missing_expr());
550+
}
551+
546552
self.alloc_expr(
547-
Expr::Tuple { exprs, is_assignee_expr: self.is_lowering_assignee_expr },
553+
Expr::Tuple {
554+
exprs: exprs.into_boxed_slice(),
555+
is_assignee_expr: self.is_lowering_assignee_expr,
556+
},
548557
syntax_ptr,
549558
)
550559
}
@@ -1180,7 +1189,11 @@ impl ExprCollector<'_> {
11801189
ast::Pat::TupleStructPat(p) => {
11811190
let path =
11821191
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
1183-
let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
1192+
let (args, ellipsis) = self.collect_tuple_pat(
1193+
p.fields(),
1194+
comma_follows_token(p.l_paren_token()),
1195+
binding_list,
1196+
);
11841197
Pat::TupleStruct { path, args, ellipsis }
11851198
}
11861199
ast::Pat::RefPat(p) => {
@@ -1199,7 +1212,11 @@ impl ExprCollector<'_> {
11991212
}
12001213
ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat(), binding_list),
12011214
ast::Pat::TuplePat(p) => {
1202-
let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
1215+
let (args, ellipsis) = self.collect_tuple_pat(
1216+
p.fields(),
1217+
comma_follows_token(p.l_paren_token()),
1218+
binding_list,
1219+
);
12031220
Pat::Tuple { args, ellipsis }
12041221
}
12051222
ast::Pat::WildcardPat(_) => Pat::Wild,
@@ -1323,18 +1340,24 @@ impl ExprCollector<'_> {
13231340
fn collect_tuple_pat(
13241341
&mut self,
13251342
args: AstChildren<ast::Pat>,
1343+
has_leading_comma: bool,
13261344
binding_list: &mut BindingList,
13271345
) -> (Box<[PatId]>, Option<usize>) {
13281346
// Find the location of the `..`, if there is one. Note that we do not
13291347
// consider the possibility of there being multiple `..` here.
13301348
let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
13311349
// We want to skip the `..` pattern here, since we account for it above.
1332-
let args = args
1350+
let mut args: Vec<_> = args
13331351
.filter(|p| !matches!(p, ast::Pat::RestPat(_)))
13341352
.map(|p| self.collect_pat(p, binding_list))
13351353
.collect();
1354+
// if there is a leading comma, the user is most likely to type out a leading pattern
1355+
// so we insert a missing pattern at the beginning for IDE features
1356+
if has_leading_comma {
1357+
args.insert(0, self.missing_pat());
1358+
}
13361359

1337-
(args, ellipsis)
1360+
(args.into_boxed_slice(), ellipsis)
13381361
}
13391362

13401363
// endregion: patterns
@@ -1493,3 +1516,8 @@ impl ExprCollector<'_> {
14931516
self.body.labels.alloc(label)
14941517
}
14951518
}
1519+
1520+
fn comma_follows_token(t: Option<syntax::SyntaxToken>) -> bool {
1521+
(|| syntax::algo::skip_trivia_token(t?.next_token()?, syntax::Direction::Next))()
1522+
.map_or(false, |it| it.kind() == syntax::T![,])
1523+
}

0 commit comments

Comments
 (0)