@@ -327,7 +327,8 @@ impl<'a> CompletionContext<'a> {
327327 return None ;
328328 }
329329
330- self . previous_token = previous_token ( syntax_element. clone ( ) ) ;
330+ self . previous_token =
331+ syntax_element. clone ( ) . into_token ( ) . and_then ( previous_non_trivia_token) ;
331332
332333 self . incomplete_let =
333334 syntax_element. ancestors ( ) . take ( 6 ) . find_map ( ast:: LetStmt :: cast) . map_or ( false , |it| {
@@ -647,8 +648,8 @@ impl<'a> CompletionContext<'a> {
647648 None
648649 } ;
649650
650- let type_location = |it : Option < SyntaxNode > | {
651- let parent = it ?;
651+ let type_location = |node : & SyntaxNode | {
652+ let parent = node . parent ( ) ?;
652653 let res = match_ast ! {
653654 match parent {
654655 ast:: Const ( it) => {
@@ -690,6 +691,15 @@ impl<'a> CompletionContext<'a> {
690691 }
691692 TypeLocation :: TypeAscription ( TypeAscriptionTarget :: Let ( find_opt_node_in_file( original_file, it. pat( ) ) ) )
692693 } ,
694+ ast:: Impl ( it) => {
695+ match it. trait_( ) {
696+ Some ( t) if t. syntax( ) == node => TypeLocation :: ImplTrait ,
697+ _ => match it. self_ty( ) {
698+ Some ( t) if t. syntax( ) == node => TypeLocation :: ImplTarget ,
699+ _ => return None ,
700+ } ,
701+ }
702+ } ,
693703 ast:: TypeBound ( _) => TypeLocation :: TypeBound ,
694704 // is this case needed?
695705 ast:: TypeBoundList ( _) => TypeLocation :: TypeBound ,
@@ -703,16 +713,49 @@ impl<'a> CompletionContext<'a> {
703713 Some ( res)
704714 } ;
705715
716+ let is_in_condition = |it : & ast:: Expr | {
717+ ( || {
718+ let parent = it. syntax ( ) . parent ( ) ?;
719+ if let Some ( expr) = ast:: WhileExpr :: cast ( parent. clone ( ) ) {
720+ Some ( expr. condition ( ) ? == * it)
721+ } else if let Some ( expr) = ast:: IfExpr :: cast ( parent) {
722+ Some ( expr. condition ( ) ? == * it)
723+ } else {
724+ None
725+ }
726+ } ) ( )
727+ . unwrap_or ( false )
728+ } ;
729+
730+ let make_path_kind_expr = |expr : ast:: Expr | {
731+ let it = expr. syntax ( ) ;
732+ let in_block_expr = is_in_block ( it) ;
733+ let in_loop_body = is_in_loop_body ( it) ;
734+ let after_if_expr = after_if_expr ( it. clone ( ) ) ;
735+ let ref_expr_parent =
736+ path. as_single_name_ref ( ) . and_then ( |_| it. parent ( ) ) . and_then ( ast:: RefExpr :: cast) ;
737+ let is_func_update = func_update_record ( it) ;
738+ let in_condition = is_in_condition ( & expr) ;
739+
740+ PathKind :: Expr {
741+ in_block_expr,
742+ in_loop_body,
743+ after_if_expr,
744+ in_condition,
745+ ref_expr_parent,
746+ is_func_update,
747+ }
748+ } ;
749+ let make_path_kind_type = |ty : ast:: Type | {
750+ let location = type_location ( ty. syntax ( ) ) ;
751+ PathKind :: Type { location : location. unwrap_or ( TypeLocation :: Other ) }
752+ } ;
753+
706754 // Infer the path kind
707755 let kind = path. syntax ( ) . parent ( ) . and_then ( |it| {
708756 match_ast ! {
709757 match it {
710- ast:: PathType ( it) => {
711- let location = type_location( it. syntax( ) . parent( ) ) ;
712- Some ( PathKind :: Type {
713- location: location. unwrap_or( TypeLocation :: Other ) ,
714- } )
715- } ,
758+ ast:: PathType ( it) => Some ( make_path_kind_type( it. into( ) ) ) ,
716759 ast:: PathExpr ( it) => {
717760 if let Some ( p) = it. syntax( ) . parent( ) {
718761 if ast:: ExprStmt :: can_cast( p. kind( ) ) {
@@ -724,14 +767,8 @@ impl<'a> CompletionContext<'a> {
724767 }
725768
726769 path_ctx. has_call_parens = it. syntax( ) . parent( ) . map_or( false , |it| ast:: CallExpr :: can_cast( it. kind( ) ) ) ;
727- let in_block_expr = is_in_block( it. syntax( ) ) ;
728- let in_loop_body = is_in_loop_body( it. syntax( ) ) ;
729- let after_if_expr = after_if_expr( it. syntax( ) . clone( ) ) ;
730- let ref_expr_parent = path. as_single_name_ref( )
731- . and_then( |_| it. syntax( ) . parent( ) ) . and_then( ast:: RefExpr :: cast) ;
732- let is_func_update = func_update_record( it. syntax( ) ) ;
733-
734- Some ( PathKind :: Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent, is_func_update } )
770+
771+ Some ( make_path_kind_expr( it. into( ) ) )
735772 } ,
736773 ast:: TupleStructPat ( it) => {
737774 path_ctx. has_call_parens = true ;
@@ -748,50 +785,41 @@ impl<'a> CompletionContext<'a> {
748785 Some ( PathKind :: Pat )
749786 } ,
750787 ast:: MacroCall ( it) => {
788+ // A macro call in this position is usually a result of parsing recovery, so check that
751789 if let Some ( kind) = inbetween_body_and_decl_check( it. syntax( ) . clone( ) ) {
752790 nameref_ctx. kind = Some ( NameRefKind :: Keyword ( kind) ) ;
753791 return None ;
754792 }
755793
756794 path_ctx. has_macro_bang = it. excl_token( ) . is_some( ) ;
757- let parent = it. syntax( ) . parent( ) ;
758- match parent. as_ref( ) . map( |it| it. kind( ) ) {
759- Some ( SyntaxKind :: MACRO_PAT ) => Some ( PathKind :: Pat ) ,
760- Some ( SyntaxKind :: MACRO_TYPE ) => {
761- let location = type_location( parent. unwrap( ) . parent( ) ) ;
762- Some ( PathKind :: Type {
763- location: location. unwrap_or( TypeLocation :: Other ) ,
764- } )
765- } ,
766- Some ( SyntaxKind :: ITEM_LIST ) => Some ( PathKind :: Item { kind: ItemListKind :: Module } ) ,
767- Some ( SyntaxKind :: ASSOC_ITEM_LIST ) => Some ( PathKind :: Item { kind: match parent. and_then( |it| it. parent( ) ) {
768- Some ( it) => match_ast! {
769- match it {
770- ast:: Trait ( _) => ItemListKind :: Trait ,
771- ast:: Impl ( it) => if it. trait_( ) . is_some( ) {
772- ItemListKind :: TraitImpl
773- } else {
774- ItemListKind :: Impl
775- } ,
776- _ => return None
777- }
778- } ,
779- None => return None ,
780- } } ) ,
781- Some ( SyntaxKind :: EXTERN_ITEM_LIST ) => Some ( PathKind :: Item { kind: ItemListKind :: ExternBlock } ) ,
782- Some ( SyntaxKind :: SOURCE_FILE ) => Some ( PathKind :: Item { kind: ItemListKind :: SourceFile } ) ,
783- _ => {
784- return parent. and_then( ast:: MacroExpr :: cast) . map( |it| {
785- let in_loop_body = is_in_loop_body( it. syntax( ) ) ;
786- let in_block_expr = is_in_block( it. syntax( ) ) ;
787- let after_if_expr = after_if_expr( it. syntax( ) . clone( ) ) ;
788- let ref_expr_parent = path. as_single_name_ref( )
789- . and_then( |_| it. syntax( ) . parent( ) ) . and_then( ast:: RefExpr :: cast) ;
790- let is_func_update = func_update_record( it. syntax( ) ) ;
791- PathKind :: Expr { in_block_expr, in_loop_body, after_if_expr, ref_expr_parent, is_func_update }
792- } ) ;
793- } ,
794- }
795+ let parent = it. syntax( ) . parent( ) ?;
796+ // Any path in an item list will be treated as a macro call by the parser
797+ let res = match_ast! {
798+ match parent {
799+ ast:: MacroExpr ( expr) => make_path_kind_expr( expr. into( ) ) ,
800+ ast:: MacroPat ( _) => PathKind :: Pat ,
801+ ast:: MacroType ( ty) => make_path_kind_type( ty. into( ) ) ,
802+ ast:: ItemList ( _) => PathKind :: Item { kind: ItemListKind :: Module } ,
803+ ast:: AssocItemList ( _) => PathKind :: Item { kind: match parent. parent( ) {
804+ Some ( it) => match_ast! {
805+ match it {
806+ ast:: Trait ( _) => ItemListKind :: Trait ,
807+ ast:: Impl ( it) => if it. trait_( ) . is_some( ) {
808+ ItemListKind :: TraitImpl
809+ } else {
810+ ItemListKind :: Impl
811+ } ,
812+ _ => return None
813+ }
814+ } ,
815+ None => return None ,
816+ } } ,
817+ ast:: ExternItemList ( _) => PathKind :: Item { kind: ItemListKind :: ExternBlock } ,
818+ ast:: SourceFile ( _) => PathKind :: Item { kind: ItemListKind :: SourceFile } ,
819+ _ => return None ,
820+ }
821+ } ;
822+ Some ( res)
795823 } ,
796824 ast:: Meta ( meta) => ( || {
797825 let attr = meta. parent_attr( ) ?;
@@ -818,10 +846,13 @@ impl<'a> CompletionContext<'a> {
818846
819847 match kind {
820848 Some ( kind) => path_ctx. kind = kind,
849+ // unresolved path kind, so this isn't really a path we should be completing,
850+ // just some random identifier which might be in keyword position
821851 None => return res,
822852 }
823853 path_ctx. has_type_args = segment. generic_arg_list ( ) . is_some ( ) ;
824854
855+ // calculate the qualifier context
825856 if let Some ( ( path, use_tree_parent) ) = path_or_use_tree_qualifier ( & path) {
826857 if !use_tree_parent {
827858 path_ctx. is_absolute_path =
@@ -1034,10 +1065,6 @@ fn has_ref(token: &SyntaxToken) -> bool {
10341065 token. kind ( ) == T ! [ & ]
10351066}
10361067
1037- pub ( crate ) fn previous_token ( element : SyntaxElement ) -> Option < SyntaxToken > {
1038- element. into_token ( ) . and_then ( previous_non_trivia_token)
1039- }
1040-
10411068pub ( crate ) fn is_in_token_of_for_loop ( element : SyntaxElement ) -> bool {
10421069 // oh my ...
10431070 ( || {
0 commit comments