@@ -592,7 +592,7 @@ impl<'a> CompletionContext<'a> {
592592 has_call_parens : false ,
593593 has_macro_bang : false ,
594594 qualified : Qualified :: No ,
595- parent : path . parent_path ( ) ,
595+ parent : None ,
596596 path : path. clone ( ) ,
597597 kind : PathKind :: Item { kind : ItemListKind :: SourceFile } ,
598598 has_type_args : false ,
@@ -827,92 +827,123 @@ impl<'a> CompletionContext<'a> {
827827 PathKind :: Type { location : location. unwrap_or ( TypeLocation :: Other ) }
828828 } ;
829829
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+
830873 // Infer the path kind
831874 let parent = path. syntax ( ) . parent ( ) ?;
832875 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) ) ) ;
841883 }
842884 }
885+ }
843886
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( ) ) ) ;
845888
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+ }
864907
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 ,
910943 }
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 ,
916947 }
917948 } ;
918949
0 commit comments