@@ -37,7 +37,6 @@ pub struct Snippet {
37
37
pub description : Option < String > ,
38
38
pub requires : Box < [ String ] > ,
39
39
}
40
-
41
40
impl Snippet {
42
41
pub fn new (
43
42
label : String ,
@@ -46,19 +45,7 @@ impl Snippet {
46
45
requires : & [ String ] ,
47
46
scope : SnippetScope ,
48
47
) -> Option < Self > {
49
- // validate that these are indeed simple paths
50
- if requires. iter ( ) . any ( |path| match ast:: Path :: parse ( path) {
51
- Ok ( path) => path. segments ( ) . any ( |seg| {
52
- !matches ! ( seg. kind( ) , Some ( ast:: PathSegmentKind :: Name ( _) ) )
53
- || seg. generic_arg_list ( ) . is_some ( )
54
- } ) ,
55
- Err ( _) => true ,
56
- } ) {
57
- return None ;
58
- }
59
- let snippet = snippet. iter ( ) . join ( "\n " ) ;
60
- let description = description. iter ( ) . join ( "\n " ) ;
61
- let description = if description. is_empty ( ) { None } else { Some ( description) } ;
48
+ let ( snippet, description) = validate_snippet ( snippet, description, requires) ?;
62
49
Some ( Snippet {
63
50
scope,
64
51
label,
@@ -68,12 +55,12 @@ impl Snippet {
68
55
} )
69
56
}
70
57
71
- // FIXME: This shouldn't be fallible
58
+ /// Returns None if the required items do not resolve.
72
59
pub ( crate ) fn imports (
73
60
& self ,
74
61
ctx : & CompletionContext ,
75
62
import_scope : & ImportScope ,
76
- ) -> Result < Vec < ImportEdit > , ( ) > {
63
+ ) -> Option < Vec < ImportEdit > > {
77
64
import_edits ( ctx, import_scope, & self . requires )
78
65
}
79
66
@@ -94,19 +81,7 @@ impl PostfixSnippet {
94
81
requires : & [ String ] ,
95
82
scope : PostfixSnippetScope ,
96
83
) -> Option < Self > {
97
- // validate that these are indeed simple paths
98
- if requires. iter ( ) . any ( |path| match ast:: Path :: parse ( path) {
99
- Ok ( path) => path. segments ( ) . any ( |seg| {
100
- !matches ! ( seg. kind( ) , Some ( ast:: PathSegmentKind :: Name ( _) ) )
101
- || seg. generic_arg_list ( ) . is_some ( )
102
- } ) ,
103
- Err ( _) => true ,
104
- } ) {
105
- return None ;
106
- }
107
- let snippet = snippet. iter ( ) . join ( "\n " ) ;
108
- let description = description. iter ( ) . join ( "\n " ) ;
109
- let description = if description. is_empty ( ) { None } else { Some ( description) } ;
84
+ let ( snippet, description) = validate_snippet ( snippet, description, requires) ?;
110
85
Some ( PostfixSnippet {
111
86
scope,
112
87
label,
@@ -116,12 +91,12 @@ impl PostfixSnippet {
116
91
} )
117
92
}
118
93
119
- // FIXME: This shouldn't be fallible
94
+ /// Returns None if the required items do not resolve.
120
95
pub ( crate ) fn imports (
121
96
& self ,
122
97
ctx : & CompletionContext ,
123
98
import_scope : & ImportScope ,
124
- ) -> Result < Vec < ImportEdit > , ( ) > {
99
+ ) -> Option < Vec < ImportEdit > > {
125
100
import_edits ( ctx, import_scope, & self . requires )
126
101
}
127
102
@@ -142,32 +117,52 @@ fn import_edits(
142
117
ctx : & CompletionContext ,
143
118
import_scope : & ImportScope ,
144
119
requires : & [ String ] ,
145
- ) -> Result < Vec < ImportEdit > , ( ) > {
120
+ ) -> Option < Vec < ImportEdit > > {
146
121
let resolve = |import| {
147
122
let path = ast:: Path :: parse ( import) . ok ( ) ?;
148
- match ctx. scope . speculative_resolve ( & path) ? {
149
- hir:: PathResolution :: Macro ( _) => None ,
150
- hir:: PathResolution :: Def ( def) => {
151
- let item = def. into ( ) ;
152
- let path = ctx. scope . module ( ) ?. find_use_path_prefixed (
153
- ctx. db ,
154
- item,
155
- ctx. config . insert_use . prefix_kind ,
156
- ) ?;
157
- Some ( ( path. len ( ) > 1 ) . then ( || ImportEdit {
158
- import : LocatedImport :: new ( path. clone ( ) , item, item, None ) ,
159
- scope : import_scope. clone ( ) ,
160
- } ) )
161
- }
162
- _ => None ,
163
- }
123
+ let item = match ctx. scope . speculative_resolve ( & path) ? {
124
+ hir:: PathResolution :: Macro ( mac) => mac. into ( ) ,
125
+ hir:: PathResolution :: Def ( def) => def. into ( ) ,
126
+ _ => return None ,
127
+ } ;
128
+ let path = ctx. scope . module ( ) ?. find_use_path_prefixed (
129
+ ctx. db ,
130
+ item,
131
+ ctx. config . insert_use . prefix_kind ,
132
+ ) ?;
133
+ Some ( ( path. len ( ) > 1 ) . then ( || ImportEdit {
134
+ import : LocatedImport :: new ( path. clone ( ) , item, item, None ) ,
135
+ scope : import_scope. clone ( ) ,
136
+ } ) )
164
137
} ;
165
138
let mut res = Vec :: with_capacity ( requires. len ( ) ) ;
166
139
for import in requires {
167
140
match resolve ( import) {
168
141
Some ( first) => res. extend ( first) ,
169
- None => return Err ( ( ) ) ,
142
+ None => return None ,
170
143
}
171
144
}
172
- Ok ( res)
145
+ Some ( res)
146
+ }
147
+
148
+ fn validate_snippet (
149
+ snippet : & [ String ] ,
150
+ description : & [ String ] ,
151
+ requires : & [ String ] ,
152
+ ) -> Option < ( String , Option < String > ) > {
153
+ // validate that these are indeed simple paths
154
+ // we can't save the paths unfortunately due to them not being Send+Sync
155
+ if requires. iter ( ) . any ( |path| match ast:: Path :: parse ( path) {
156
+ Ok ( path) => path. segments ( ) . any ( |seg| {
157
+ !matches ! ( seg. kind( ) , Some ( ast:: PathSegmentKind :: Name ( _) ) )
158
+ || seg. generic_arg_list ( ) . is_some ( )
159
+ } ) ,
160
+ Err ( _) => true ,
161
+ } ) {
162
+ return None ;
163
+ }
164
+ let snippet = snippet. iter ( ) . join ( "\n " ) ;
165
+ let description = description. iter ( ) . join ( "\n " ) ;
166
+ let description = if description. is_empty ( ) { None } else { Some ( description) } ;
167
+ Some ( ( snippet, description) )
173
168
}
0 commit comments