@@ -883,9 +883,10 @@ fn classify_name_ref(
883
883
} ,
884
884
ast:: MethodCallExpr ( method) => {
885
885
let receiver = find_opt_node_in_file( original_file, method. receiver( ) ) ;
886
+ let has_parens = has_parens( & method) ;
886
887
let kind = NameRefKind :: DotAccess ( DotAccess {
887
888
receiver_ty: receiver. as_ref( ) . and_then( |it| sema. type_of_expr( it) ) ,
888
- kind: DotAccessKind :: Method { has_parens: method . arg_list ( ) . is_some_and ( |it| it . l_paren_token ( ) . is_some ( ) ) } ,
889
+ kind: DotAccessKind :: Method { has_parens } ,
889
890
receiver,
890
891
ctx: DotAccessExprCtx { in_block_expr: is_in_block( method. syntax( ) ) , in_breakable: is_in_breakable( method. syntax( ) ) }
891
892
} ) ;
@@ -1372,7 +1373,7 @@ fn classify_name_ref(
1372
1373
}
1373
1374
}
1374
1375
1375
- path_ctx. has_call_parens = it. syntax( ) . parent( ) . is_some_and( |it| ast:: CallExpr :: can_cast ( it. kind ( ) ) ) ;
1376
+ path_ctx. has_call_parens = it. syntax( ) . parent( ) . is_some_and( |it| ast:: CallExpr :: cast ( it) . is_some_and ( |it| has_parens ( & it ) ) ) ;
1376
1377
1377
1378
make_path_kind_expr( it. into( ) )
1378
1379
} ,
@@ -1401,7 +1402,7 @@ fn classify_name_ref(
1401
1402
match parent {
1402
1403
ast:: PathType ( it) => make_path_kind_type( it. into( ) ) ,
1403
1404
ast:: PathExpr ( it) => {
1404
- path_ctx. has_call_parens = it. syntax( ) . parent( ) . is_some_and( |it| ast:: CallExpr :: can_cast ( it. kind ( ) ) ) ;
1405
+ path_ctx. has_call_parens = it. syntax( ) . parent( ) . is_some_and( |it| ast:: CallExpr :: cast ( it) . is_some_and ( |it| has_parens ( & it ) ) ) ;
1405
1406
1406
1407
make_path_kind_expr( it. into( ) )
1407
1408
} ,
@@ -1559,6 +1560,30 @@ fn classify_name_ref(
1559
1560
Some ( ( NameRefContext { nameref, kind : NameRefKind :: Path ( path_ctx) } , qualifier_ctx) )
1560
1561
}
1561
1562
1563
+ /// When writing in the middle of some code the following situation commonly occurs (`|` denotes the cursor):
1564
+ /// ```ignore
1565
+ /// value.method|
1566
+ /// (1, 2, 3)
1567
+ /// ```
1568
+ /// Here, we want to complete the method parentheses & arguments (if the corresponding settings are on),
1569
+ /// but the thing is parsed as a method call with parentheses. Therefore we use heuristics: if the parentheses
1570
+ /// are on the next line, consider them non-existent.
1571
+ fn has_parens ( node : & dyn HasArgList ) -> bool {
1572
+ let Some ( arg_list) = node. arg_list ( ) else { return false } ;
1573
+ if arg_list. l_paren_token ( ) . is_none ( ) {
1574
+ return false ;
1575
+ }
1576
+ let prev_siblings = iter:: successors ( arg_list. syntax ( ) . prev_sibling_or_token ( ) , |it| {
1577
+ it. prev_sibling_or_token ( )
1578
+ } ) ;
1579
+ prev_siblings
1580
+ . take_while ( |syntax| syntax. kind ( ) . is_trivia ( ) )
1581
+ . filter_map ( |syntax| {
1582
+ syntax. into_token ( ) . filter ( |token| token. kind ( ) == SyntaxKind :: WHITESPACE )
1583
+ } )
1584
+ . all ( |whitespace| !whitespace. text ( ) . contains ( '\n' ) )
1585
+ }
1586
+
1562
1587
fn pattern_context_for (
1563
1588
sema : & Semantics < ' _ , RootDatabase > ,
1564
1589
original_file : & SyntaxNode ,
0 commit comments