Skip to content

Commit 2c27adc

Browse files
committed
Remove match_ast! macro call
Add node about uncommenting tuple in macro call
1 parent b1ebb82 commit 2c27adc

File tree

1 file changed

+80
-73
lines changed

1 file changed

+80
-73
lines changed

crates/ide_assists/src/handlers/destructure_tuple_binding.rs

Lines changed: 80 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ fn edit_tuple_usage(
227227

228228
// no index access -> make invalid -> requires handling by user
229229
// -> put usage in block comment
230+
//
231+
// Note: For macro invocations this might result in still valid code:
232+
// When a macro accepts the tuple as argument, as well as no arguments at all,
233+
// uncommenting the tuple still leaves the macro call working (see `tests::in_macro_call::empty_macro`).
234+
// But this is an unlikely case. Usually the resulting macro call will become erroneous.
230235
builder.insert(usage.range.start(), "/*");
231236
builder.insert(usage.range.end(), "*/");
232237
}
@@ -322,89 +327,91 @@ fn handle_ref_field_usage(ctx: &AssistContext, field_expr: &FieldExpr) -> RefDat
322327
let mut ref_data =
323328
RefData { range: s.text_range(), needs_deref: true, needs_parentheses: true };
324329

325-
let parent = match s.parent() {
326-
Some(parent) => parent,
330+
let parent = match s.parent().map(ast::Expr::cast) {
331+
Some(Some(parent)) => parent,
332+
Some(None) => {
333+
ref_data.needs_parentheses = false;
334+
return ref_data;
335+
}
327336
None => return ref_data,
328337
};
329338

330-
match_ast! {
331-
match parent {
332-
ast::ParenExpr(it) => {
333-
// already parens in place -> don't replace
334-
ref_data.needs_parentheses = false;
335-
// there might be a ref outside: `&(t.0)` -> can be removed
336-
if let Some(it) = it.syntax().parent().and_then(ast::RefExpr::cast) {
337-
ref_data.needs_deref = false;
338-
ref_data.range = it.syntax().text_range();
339-
}
340-
},
341-
ast::RefExpr(it) => {
342-
// `&*` -> cancel each other out
339+
match parent {
340+
ast::Expr::ParenExpr(it) => {
341+
// already parens in place -> don't replace
342+
ref_data.needs_parentheses = false;
343+
// there might be a ref outside: `&(t.0)` -> can be removed
344+
if let Some(it) = it.syntax().parent().and_then(ast::RefExpr::cast) {
343345
ref_data.needs_deref = false;
344-
ref_data.needs_parentheses = false;
345-
// might be surrounded by parens -> can be removed too
346-
match it.syntax().parent().and_then(ast::ParenExpr::cast) {
347-
Some(parent) => ref_data.range = parent.syntax().text_range(),
348-
None => ref_data.range = it.syntax().text_range(),
349-
};
350-
},
351-
// higher precedence than deref `*`
352-
// https://doc.rust-lang.org/reference/expressions.html#expression-precedence
353-
// -> requires parentheses
354-
ast::PathExpr(_it) => {},
355-
ast::MethodCallExpr(it) => {
356-
// `field_expr` is `self_param` (otherwise it would be in `ArgList`)
346+
ref_data.range = it.syntax().text_range();
347+
}
348+
}
349+
ast::Expr::RefExpr(it) => {
350+
// `&*` -> cancel each other out
351+
ref_data.needs_deref = false;
352+
ref_data.needs_parentheses = false;
353+
// might be surrounded by parens -> can be removed too
354+
match it.syntax().parent().and_then(ast::ParenExpr::cast) {
355+
Some(parent) => ref_data.range = parent.syntax().text_range(),
356+
None => ref_data.range = it.syntax().text_range(),
357+
};
358+
}
359+
// higher precedence than deref `*`
360+
// https://doc.rust-lang.org/reference/expressions.html#expression-precedence
361+
// -> requires parentheses
362+
ast::Expr::PathExpr(_it) => {}
363+
ast::Expr::MethodCallExpr(it) => {
364+
// `field_expr` is `self_param` (otherwise it would be in `ArgList`)
365+
366+
// test if there's already auto-ref in place (`value` -> `&value`)
367+
// -> no method accepting `self`, but `&self` -> no need for deref
368+
//
369+
// other combinations (`&value` -> `value`, `&&value` -> `&value`, `&value` -> `&&value`) might or might not be able to auto-ref/deref,
370+
// but there might be trait implementations an added `&` might resolve to
371+
// -> ONLY handle auto-ref from `value` to `&value`
372+
fn is_auto_ref(ctx: &AssistContext, call_expr: &MethodCallExpr) -> bool {
373+
fn impl_(ctx: &AssistContext, call_expr: &MethodCallExpr) -> Option<bool> {
374+
let rec = call_expr.receiver()?;
375+
let rec_ty = ctx.sema.type_of_expr(&rec)?.adjusted();
376+
// input must be actual value
377+
if rec_ty.is_reference() {
378+
return Some(false);
379+
}
357380

358-
// test if there's already auto-ref in place (`value` -> `&value`)
359-
// -> no method accepting `self`, but `&self` -> no need for deref
360-
//
361-
// other combinations (`&value` -> `value`, `&&value` -> `&value`, `&value` -> `&&value`) might or might not be able to auto-ref/deref,
362-
// but there might be trait implementations an added `&` might resolve to
363-
// -> ONLY handle auto-ref from `value` to `&value`
364-
fn is_auto_ref(ctx: &AssistContext, call_expr: &MethodCallExpr) -> bool {
365-
fn impl_(ctx: &AssistContext, call_expr: &MethodCallExpr) -> Option<bool> {
366-
let rec = call_expr.receiver()?;
367-
let rec_ty = ctx.sema.type_of_expr(&rec)?.adjusted();
368-
// input must be actual value
369-
if rec_ty.is_reference() {
370-
return Some(false);
371-
}
372-
373-
// doesn't resolve trait impl
374-
let f = ctx.sema.resolve_method_call(call_expr)?;
375-
let self_param = f.self_param(ctx.db())?;
376-
// self must be ref
377-
match self_param.access(ctx.db()) {
378-
hir::Access::Shared | hir::Access::Exclusive => Some(true),
379-
hir::Access::Owned => Some(false),
380-
}
381+
// doesn't resolve trait impl
382+
let f = ctx.sema.resolve_method_call(call_expr)?;
383+
let self_param = f.self_param(ctx.db())?;
384+
// self must be ref
385+
match self_param.access(ctx.db()) {
386+
hir::Access::Shared | hir::Access::Exclusive => Some(true),
387+
hir::Access::Owned => Some(false),
381388
}
382-
impl_(ctx, call_expr).unwrap_or(false)
383389
}
390+
impl_(ctx, call_expr).unwrap_or(false)
391+
}
384392

385-
if is_auto_ref(ctx, &it) {
386-
ref_data.needs_deref = false;
387-
ref_data.needs_parentheses = false;
388-
}
389-
},
390-
ast::FieldExpr(_it) => {
391-
// `t.0.my_field`
392-
ref_data.needs_deref = false;
393-
ref_data.needs_parentheses = false;
394-
},
395-
ast::IndexExpr(_it) => {
396-
// `t.0[1]`
393+
if is_auto_ref(ctx, &it) {
397394
ref_data.needs_deref = false;
398395
ref_data.needs_parentheses = false;
399-
},
400-
ast::TryExpr(_it) => {
401-
// `t.0?`
402-
// requires deref and parens: `(*_0)`
403-
},
404-
// lower precedence than deref `*` -> no parens
405-
_ => {
406-
ref_data.needs_parentheses = false;
407-
},
396+
}
397+
}
398+
ast::Expr::FieldExpr(_it) => {
399+
// `t.0.my_field`
400+
ref_data.needs_deref = false;
401+
ref_data.needs_parentheses = false;
402+
}
403+
ast::Expr::IndexExpr(_it) => {
404+
// `t.0[1]`
405+
ref_data.needs_deref = false;
406+
ref_data.needs_parentheses = false;
407+
}
408+
ast::Expr::TryExpr(_it) => {
409+
// `t.0?`
410+
// requires deref and parens: `(*_0)`
411+
}
412+
// lower precedence than deref `*` -> no parens
413+
_ => {
414+
ref_data.needs_parentheses = false;
408415
}
409416
};
410417

0 commit comments

Comments
 (0)