@@ -327,7 +327,8 @@ impl<'a> CompletionContext<'a> {
327
327
return None ;
328
328
}
329
329
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) ;
331
332
332
333
self . incomplete_let =
333
334
syntax_element. ancestors ( ) . take ( 6 ) . find_map ( ast:: LetStmt :: cast) . map_or ( false , |it| {
@@ -647,8 +648,8 @@ impl<'a> CompletionContext<'a> {
647
648
None
648
649
} ;
649
650
650
- let type_location = |it : Option < SyntaxNode > | {
651
- let parent = it ?;
651
+ let type_location = |node : & SyntaxNode | {
652
+ let parent = node . parent ( ) ?;
652
653
let res = match_ast ! {
653
654
match parent {
654
655
ast:: Const ( it) => {
@@ -690,6 +691,15 @@ impl<'a> CompletionContext<'a> {
690
691
}
691
692
TypeLocation :: TypeAscription ( TypeAscriptionTarget :: Let ( find_opt_node_in_file( original_file, it. pat( ) ) ) )
692
693
} ,
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
+ } ,
693
703
ast:: TypeBound ( _) => TypeLocation :: TypeBound ,
694
704
// is this case needed?
695
705
ast:: TypeBoundList ( _) => TypeLocation :: TypeBound ,
@@ -703,16 +713,49 @@ impl<'a> CompletionContext<'a> {
703
713
Some ( res)
704
714
} ;
705
715
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
+
706
754
// Infer the path kind
707
755
let kind = path. syntax ( ) . parent ( ) . and_then ( |it| {
708
756
match_ast ! {
709
757
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( ) ) ) ,
716
759
ast:: PathExpr ( it) => {
717
760
if let Some ( p) = it. syntax( ) . parent( ) {
718
761
if ast:: ExprStmt :: can_cast( p. kind( ) ) {
@@ -724,14 +767,8 @@ impl<'a> CompletionContext<'a> {
724
767
}
725
768
726
769
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( ) ) )
735
772
} ,
736
773
ast:: TupleStructPat ( it) => {
737
774
path_ctx. has_call_parens = true ;
@@ -748,50 +785,41 @@ impl<'a> CompletionContext<'a> {
748
785
Some ( PathKind :: Pat )
749
786
} ,
750
787
ast:: MacroCall ( it) => {
788
+ // A macro call in this position is usually a result of parsing recovery, so check that
751
789
if let Some ( kind) = inbetween_body_and_decl_check( it. syntax( ) . clone( ) ) {
752
790
nameref_ctx. kind = Some ( NameRefKind :: Keyword ( kind) ) ;
753
791
return None ;
754
792
}
755
793
756
794
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)
795
823
} ,
796
824
ast:: Meta ( meta) => ( || {
797
825
let attr = meta. parent_attr( ) ?;
@@ -818,10 +846,13 @@ impl<'a> CompletionContext<'a> {
818
846
819
847
match kind {
820
848
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
821
851
None => return res,
822
852
}
823
853
path_ctx. has_type_args = segment. generic_arg_list ( ) . is_some ( ) ;
824
854
855
+ // calculate the qualifier context
825
856
if let Some ( ( path, use_tree_parent) ) = path_or_use_tree_qualifier ( & path) {
826
857
if !use_tree_parent {
827
858
path_ctx. is_absolute_path =
@@ -1034,10 +1065,6 @@ fn has_ref(token: &SyntaxToken) -> bool {
1034
1065
token. kind ( ) == T ! [ & ]
1035
1066
}
1036
1067
1037
- pub ( crate ) fn previous_token ( element : SyntaxElement ) -> Option < SyntaxToken > {
1038
- element. into_token ( ) . and_then ( previous_non_trivia_token)
1039
- }
1040
-
1041
1068
pub ( crate ) fn is_in_token_of_for_loop ( element : SyntaxElement ) -> bool {
1042
1069
// oh my ...
1043
1070
( || {
0 commit comments