@@ -883,9 +883,10 @@ fn classify_name_ref(
883883 } ,
884884 ast:: MethodCallExpr ( method) => {
885885 let receiver = find_opt_node_in_file( original_file, method. receiver( ) ) ;
886+ let has_parens = has_parens( & method) ;
886887 let kind = NameRefKind :: DotAccess ( DotAccess {
887888 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 } ,
889890 receiver,
890891 ctx: DotAccessExprCtx { in_block_expr: is_in_block( method. syntax( ) ) , in_breakable: is_in_breakable( method. syntax( ) ) }
891892 } ) ;
@@ -1372,7 +1373,7 @@ fn classify_name_ref(
13721373 }
13731374 }
13741375
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 ) ) ) ;
13761377
13771378 make_path_kind_expr( it. into( ) )
13781379 } ,
@@ -1401,7 +1402,7 @@ fn classify_name_ref(
14011402 match parent {
14021403 ast:: PathType ( it) => make_path_kind_type( it. into( ) ) ,
14031404 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 ) ) ) ;
14051406
14061407 make_path_kind_expr( it. into( ) )
14071408 } ,
@@ -1559,6 +1560,30 @@ fn classify_name_ref(
15591560 Some ( ( NameRefContext { nameref, kind : NameRefKind :: Path ( path_ctx) } , qualifier_ctx) )
15601561}
15611562
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+
15621587fn pattern_context_for (
15631588 sema : & Semantics < ' _ , RootDatabase > ,
15641589 original_file : & SyntaxNode ,
0 commit comments