@@ -43,6 +43,7 @@ use syntax::{
43
43
use text_edit:: TextEdit ;
44
44
45
45
use crate :: {
46
+ context:: { ItemListKind , NameContext , NameKind , NameRefContext , PathCompletionCtx , PathKind } ,
46
47
CompletionContext , CompletionItem , CompletionItemKind , CompletionRelevance , Completions ,
47
48
} ;
48
49
@@ -54,7 +55,6 @@ enum ImplCompletionKind {
54
55
Const ,
55
56
}
56
57
57
- // FIXME: Make this a submodule of [`item_list`]
58
58
pub ( crate ) fn complete_trait_impl ( acc : & mut Completions , ctx : & CompletionContext ) {
59
59
if let Some ( ( kind, replacement_range, impl_def) ) = completion_match ( ctx) {
60
60
if let Some ( hir_impl) = ctx. sema . to_def ( & impl_def) {
@@ -77,74 +77,48 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
77
77
}
78
78
}
79
79
80
- // FIXME: This should be lifted out so that we can do proper smart item keyword completions
81
80
fn completion_match ( ctx : & CompletionContext ) -> Option < ( ImplCompletionKind , TextRange , ast:: Impl ) > {
82
81
let token = ctx. token . clone ( ) ;
83
82
84
- // For keyword without name like `impl .. { fn $0 }`, the current position is inside
85
- // the whitespace token, which is outside `FN` syntax node.
86
- // We need to follow the previous token in this case.
87
- let mut token_before_ws = token. clone ( ) ;
88
- if token. kind ( ) == SyntaxKind :: WHITESPACE {
89
- token_before_ws = token. prev_token ( ) ?;
90
- }
91
-
92
- let parent_kind = token_before_ws. parent ( ) . map_or ( SyntaxKind :: EOF , |it| it. kind ( ) ) ;
93
- if token. parent ( ) . map ( |n| n. kind ( ) ) == Some ( SyntaxKind :: ASSOC_ITEM_LIST )
94
- && matches ! (
95
- token_before_ws. kind( ) ,
96
- SyntaxKind :: SEMICOLON | SyntaxKind :: R_CURLY | SyntaxKind :: L_CURLY
97
- )
98
- {
99
- let impl_def = ast:: Impl :: cast ( token. parent ( ) ?. parent ( ) ?) ?;
100
- let kind = ImplCompletionKind :: All ;
101
- let replacement_range = TextRange :: empty ( ctx. position . offset ) ;
102
- Some ( ( kind, replacement_range, impl_def) )
103
- } else {
104
- let impl_item_offset = match token_before_ws. kind ( ) {
105
- // `impl .. { const $0 }`
106
- // ERROR 0
107
- // CONST_KW <- *
108
- T ! [ const ] => 0 ,
109
- // `impl .. { fn/type $0 }`
110
- // FN/TYPE_ALIAS 0
111
- // FN_KW <- *
112
- T ! [ fn ] | T ! [ type ] => 0 ,
113
- // `impl .. { fn/type/const foo$0 }`
114
- // FN/TYPE_ALIAS/CONST 1
115
- // NAME 0
116
- // IDENT <- *
117
- SyntaxKind :: IDENT if parent_kind == SyntaxKind :: NAME => 1 ,
118
- // `impl .. { foo$0 }`
119
- // MACRO_CALL 3
120
- // PATH 2
121
- // PATH_SEGMENT 1
122
- // NAME_REF 0
123
- // IDENT <- *
124
- SyntaxKind :: IDENT if parent_kind == SyntaxKind :: NAME_REF => 3 ,
83
+ if let Some ( NameContext { name, kind, .. } ) = ctx. name_ctx ( ) {
84
+ let kind = match kind {
85
+ NameKind :: Const => ImplCompletionKind :: Const ,
86
+ NameKind :: Function => ImplCompletionKind :: Fn ,
87
+ NameKind :: TypeAlias => ImplCompletionKind :: TypeAlias ,
125
88
_ => return None ,
126
89
} ;
127
-
128
- let impl_item = token_before_ws. ancestors ( ) . nth ( impl_item_offset) ?;
129
- // Must directly belong to an impl block.
130
- // IMPL
131
- // ASSOC_ITEM_LIST
132
- // <item>
133
- let impl_def = ast:: Impl :: cast ( impl_item. parent ( ) ?. parent ( ) ?) ?;
134
- let kind = match impl_item. kind ( ) {
135
- // `impl ... { const $0 fn/type/const }`
136
- _ if token_before_ws. kind ( ) == T ! [ const ] => ImplCompletionKind :: Const ,
137
- SyntaxKind :: CONST | SyntaxKind :: ERROR => ImplCompletionKind :: Const ,
138
- SyntaxKind :: TYPE_ALIAS => ImplCompletionKind :: TypeAlias ,
139
- SyntaxKind :: FN => ImplCompletionKind :: Fn ,
140
- SyntaxKind :: MACRO_CALL => ImplCompletionKind :: All ,
141
- _ => return None ,
142
- } ;
143
-
144
- let replacement_range = replacement_range ( ctx, & impl_item) ;
145
-
146
- Some ( ( kind, replacement_range, impl_def) )
90
+ let item = match name {
91
+ Some ( name) => name. syntax ( ) . parent ( ) ,
92
+ None => {
93
+ if token. kind ( ) == SyntaxKind :: WHITESPACE { token. prev_token ( ) ? } else { token }
94
+ . parent ( )
95
+ }
96
+ } ?;
97
+ return Some ( (
98
+ kind,
99
+ replacement_range ( ctx, & item) ,
100
+ // item -> ASSOC_ITEM_LIST -> IMPL
101
+ ast:: Impl :: cast ( item. parent ( ) ?. parent ( ) ?) ?,
102
+ ) ) ;
103
+ } else if let Some ( NameRefContext {
104
+ nameref,
105
+ path_ctx :
106
+ Some ( PathCompletionCtx { kind : PathKind :: Item { kind : ItemListKind :: TraitImpl } , .. } ) ,
107
+ ..
108
+ } ) = ctx. nameref_ctx ( )
109
+ {
110
+ if !ctx. is_non_trivial_path ( ) {
111
+ return Some ( (
112
+ ImplCompletionKind :: All ,
113
+ match nameref {
114
+ Some ( name) => name. syntax ( ) . text_range ( ) ,
115
+ None => TextRange :: empty ( ctx. position . offset ) ,
116
+ } ,
117
+ ctx. impl_def . clone ( ) ?,
118
+ ) ) ;
119
+ }
147
120
}
121
+ None
148
122
}
149
123
150
124
fn add_function_impl (
0 commit comments