@@ -592,7 +592,7 @@ impl<'a> CompletionContext<'a> {
592
592
has_call_parens : false ,
593
593
has_macro_bang : false ,
594
594
qualified : Qualified :: No ,
595
- parent : path . parent_path ( ) ,
595
+ parent : None ,
596
596
path : path. clone ( ) ,
597
597
kind : PathKind :: Item { kind : ItemListKind :: SourceFile } ,
598
598
has_type_args : false ,
@@ -827,92 +827,123 @@ impl<'a> CompletionContext<'a> {
827
827
PathKind :: Type { location : location. unwrap_or ( TypeLocation :: Other ) }
828
828
} ;
829
829
830
+ let mut kind_macro_call = |it : ast:: MacroCall | {
831
+ path_ctx. has_macro_bang = it. excl_token ( ) . is_some ( ) ;
832
+ let parent = it. syntax ( ) . parent ( ) ?;
833
+ // Any path in an item list will be treated as a macro call by the parser
834
+ let kind = match_ast ! {
835
+ match parent {
836
+ ast:: MacroExpr ( expr) => make_path_kind_expr( expr. into( ) ) ,
837
+ ast:: MacroPat ( it) => PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) } ,
838
+ ast:: MacroType ( ty) => make_path_kind_type( ty. into( ) ) ,
839
+ ast:: ItemList ( _) => PathKind :: Item { kind: ItemListKind :: Module } ,
840
+ ast:: AssocItemList ( _) => PathKind :: Item { kind: match parent. parent( ) {
841
+ Some ( it) => match_ast! {
842
+ match it {
843
+ ast:: Trait ( _) => ItemListKind :: Trait ,
844
+ ast:: Impl ( it) => if it. trait_( ) . is_some( ) {
845
+ ItemListKind :: TraitImpl ( find_node_in_file_compensated( sema, original_file, & it) )
846
+ } else {
847
+ ItemListKind :: Impl
848
+ } ,
849
+ _ => return None
850
+ }
851
+ } ,
852
+ None => return None ,
853
+ } } ,
854
+ ast:: ExternItemList ( _) => PathKind :: Item { kind: ItemListKind :: ExternBlock } ,
855
+ ast:: SourceFile ( _) => PathKind :: Item { kind: ItemListKind :: SourceFile } ,
856
+ _ => return None ,
857
+ }
858
+ } ;
859
+ Some ( kind)
860
+ } ;
861
+ let make_path_kind_attr = |meta : ast:: Meta | {
862
+ let attr = meta. parent_attr ( ) ?;
863
+ let kind = attr. kind ( ) ;
864
+ let attached = attr. syntax ( ) . parent ( ) ?;
865
+ let is_trailing_outer_attr = kind != AttrKind :: Inner
866
+ && non_trivia_sibling ( attr. syntax ( ) . clone ( ) . into ( ) , syntax:: Direction :: Next )
867
+ . is_none ( ) ;
868
+ let annotated_item_kind =
869
+ if is_trailing_outer_attr { None } else { Some ( attached. kind ( ) ) } ;
870
+ Some ( PathKind :: Attr { attr_ctx : AttrCtx { kind, annotated_item_kind } } )
871
+ } ;
872
+
830
873
// Infer the path kind
831
874
let parent = path. syntax ( ) . parent ( ) ?;
832
875
let kind = match_ast ! {
833
- match parent {
834
- ast:: PathType ( it) => make_path_kind_type( it. into( ) ) ,
835
- ast:: PathExpr ( it) => {
836
- if let Some ( p) = it. syntax( ) . parent( ) {
837
- if ast:: ExprStmt :: can_cast( p. kind( ) ) {
838
- if let Some ( kind) = inbetween_body_and_decl_check( p) {
839
- return Some ( make_res( NameRefKind :: Keyword ( kind) ) ) ;
840
- }
876
+ match parent {
877
+ ast:: PathType ( it) => make_path_kind_type( it. into( ) ) ,
878
+ ast:: PathExpr ( it) => {
879
+ if let Some ( p) = it. syntax( ) . parent( ) {
880
+ if ast:: ExprStmt :: can_cast( p. kind( ) ) {
881
+ if let Some ( kind) = inbetween_body_and_decl_check( p) {
882
+ return Some ( make_res( NameRefKind :: Keyword ( kind) ) ) ;
841
883
}
842
884
}
885
+ }
843
886
844
- path_ctx. has_call_parens = it. syntax( ) . parent( ) . map_or( false , |it| ast:: CallExpr :: can_cast( it. kind( ) ) ) ;
887
+ path_ctx. has_call_parens = it. syntax( ) . parent( ) . map_or( false , |it| ast:: CallExpr :: can_cast( it. kind( ) ) ) ;
845
888
846
- make_path_kind_expr( it. into( ) )
847
- } ,
848
- ast:: TupleStructPat ( it) => {
849
- path_ctx. has_call_parens = true ;
850
- PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
851
- } ,
852
- ast:: RecordPat ( it) => {
853
- path_ctx. has_call_parens = true ;
854
- PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
855
- } ,
856
- ast:: PathPat ( it) => {
857
- PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
858
- } ,
859
- ast:: MacroCall ( it) => {
860
- // A macro call in this position is usually a result of parsing recovery, so check that
861
- if let Some ( kind) = inbetween_body_and_decl_check( it. syntax( ) . clone( ) ) {
862
- return Some ( make_res( NameRefKind :: Keyword ( kind) ) ) ;
863
- }
889
+ make_path_kind_expr( it. into( ) )
890
+ } ,
891
+ ast:: TupleStructPat ( it) => {
892
+ path_ctx. has_call_parens = true ;
893
+ PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
894
+ } ,
895
+ ast:: RecordPat ( it) => {
896
+ path_ctx. has_call_parens = true ;
897
+ PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
898
+ } ,
899
+ ast:: PathPat ( it) => {
900
+ PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
901
+ } ,
902
+ ast:: MacroCall ( it) => {
903
+ // A macro call in this position is usually a result of parsing recovery, so check that
904
+ if let Some ( kind) = inbetween_body_and_decl_check( it. syntax( ) . clone( ) ) {
905
+ return Some ( make_res( NameRefKind :: Keyword ( kind) ) ) ;
906
+ }
864
907
865
- path_ctx. has_macro_bang = it. excl_token( ) . is_some( ) ;
866
- let parent = it. syntax( ) . parent( ) ?;
867
- // Any path in an item list will be treated as a macro call by the parser
868
- match_ast! {
869
- match parent {
870
- ast:: MacroExpr ( expr) => make_path_kind_expr( expr. into( ) ) ,
871
- ast:: MacroPat ( it) => PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) } ,
872
- ast:: MacroType ( ty) => make_path_kind_type( ty. into( ) ) ,
873
- ast:: ItemList ( _) => PathKind :: Item { kind: ItemListKind :: Module } ,
874
- ast:: AssocItemList ( _) => PathKind :: Item { kind: match parent. parent( ) {
875
- Some ( it) => match_ast! {
876
- match it {
877
- ast:: Trait ( _) => ItemListKind :: Trait ,
878
- ast:: Impl ( it) => if it. trait_( ) . is_some( ) {
879
- ItemListKind :: TraitImpl ( find_node_in_file_compensated( sema, original_file, & it) )
880
- } else {
881
- ItemListKind :: Impl
882
- } ,
883
- _ => return None
884
- }
885
- } ,
886
- None => return None ,
887
- } } ,
888
- ast:: ExternItemList ( _) => PathKind :: Item { kind: ItemListKind :: ExternBlock } ,
889
- ast:: SourceFile ( _) => PathKind :: Item { kind: ItemListKind :: SourceFile } ,
890
- _ => return None ,
891
- }
892
- }
893
- } ,
894
- ast:: Meta ( meta) => {
895
- let attr = meta. parent_attr( ) ?;
896
- let kind = attr. kind( ) ;
897
- let attached = attr. syntax( ) . parent( ) ?;
898
- let is_trailing_outer_attr = kind != AttrKind :: Inner
899
- && non_trivia_sibling( attr. syntax( ) . clone( ) . into( ) , syntax:: Direction :: Next ) . is_none( ) ;
900
- let annotated_item_kind = if is_trailing_outer_attr {
901
- None
902
- } else {
903
- Some ( attached. kind( ) )
904
- } ;
905
- PathKind :: Attr {
906
- attr_ctx: AttrCtx {
907
- kind,
908
- annotated_item_kind,
909
- }
908
+ kind_macro_call( it) ?
909
+ } ,
910
+ ast:: Meta ( meta) => make_path_kind_attr( meta) ?,
911
+ ast:: Visibility ( it) => PathKind :: Vis { has_in_token: it. in_token( ) . is_some( ) } ,
912
+ ast:: UseTree ( _) => PathKind :: Use ,
913
+ // completing inside a qualifier
914
+ ast:: Path ( parent) => {
915
+ path_ctx. parent = Some ( parent. clone( ) ) ;
916
+ let parent = iter:: successors( Some ( parent) , |it| it. parent_path( ) ) . last( ) ?. syntax( ) . parent( ) ?;
917
+ match_ast! {
918
+ match parent {
919
+ ast:: PathType ( it) => make_path_kind_type( it. into( ) ) ,
920
+ ast:: PathExpr ( it) => {
921
+ path_ctx. has_call_parens = it. syntax( ) . parent( ) . map_or( false , |it| ast:: CallExpr :: can_cast( it. kind( ) ) ) ;
922
+
923
+ make_path_kind_expr( it. into( ) )
924
+ } ,
925
+ ast:: TupleStructPat ( it) => {
926
+ path_ctx. has_call_parens = true ;
927
+ PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
928
+ } ,
929
+ ast:: RecordPat ( it) => {
930
+ path_ctx. has_call_parens = true ;
931
+ PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
932
+ } ,
933
+ ast:: PathPat ( it) => {
934
+ PathKind :: Pat { pat_ctx: pattern_context_for( sema, original_file, it. into( ) ) }
935
+ } ,
936
+ ast:: MacroCall ( it) => {
937
+ kind_macro_call( it) ?
938
+ } ,
939
+ ast:: Meta ( meta) => make_path_kind_attr( meta) ?,
940
+ ast:: Visibility ( it) => PathKind :: Vis { has_in_token: it. in_token( ) . is_some( ) } ,
941
+ ast:: UseTree ( _) => PathKind :: Use ,
942
+ _ => return None ,
910
943
}
911
- } ,
912
- ast:: Visibility ( it) => PathKind :: Vis { has_in_token: it. in_token( ) . is_some( ) } ,
913
- ast:: UseTree ( _) => PathKind :: Use ,
914
- _ => return None ,
915
-
944
+ }
945
+ } ,
946
+ _ => return None ,
916
947
}
917
948
} ;
918
949
0 commit comments