@@ -177,13 +177,21 @@ fn cmp((_, lhs): &(&ItemInNs, &ModPath), (_, rhs): &(&ItemInNs, &ModPath)) -> Or
177
177
#[ derive( Debug ) ]
178
178
pub struct Query {
179
179
query : String ,
180
+ lowercased : String ,
180
181
anchor_end : bool ,
182
+ case_sensitive : bool ,
181
183
limit : usize ,
182
184
}
183
185
184
186
impl Query {
185
187
pub fn new ( query : & str ) -> Self {
186
- Self { query : query. to_lowercase ( ) , anchor_end : false , limit : usize:: max_value ( ) }
188
+ Self {
189
+ lowercased : query. to_lowercase ( ) ,
190
+ query : query. to_string ( ) ,
191
+ anchor_end : false ,
192
+ case_sensitive : false ,
193
+ limit : usize:: max_value ( ) ,
194
+ }
187
195
}
188
196
189
197
/// Only returns items whose paths end with the (case-insensitive) query string as their last
@@ -196,6 +204,11 @@ impl Query {
196
204
pub fn limit ( self , limit : usize ) -> Self {
197
205
Self { limit, ..self }
198
206
}
207
+
208
+ /// Respect casing of the query string when matching.
209
+ pub fn case_sensitive ( self ) -> Self {
210
+ Self { case_sensitive : true , ..self }
211
+ }
199
212
}
200
213
201
214
/// Searches dependencies of `krate` for an importable path matching `query`.
@@ -212,7 +225,7 @@ pub fn search_dependencies<'a>(
212
225
let import_maps: Vec < _ > =
213
226
graph[ krate] . dependencies . iter ( ) . map ( |dep| db. import_map ( dep. crate_id ) ) . collect ( ) ;
214
227
215
- let automaton = fst:: automaton:: Subsequence :: new ( & query. query ) ;
228
+ let automaton = fst:: automaton:: Subsequence :: new ( & query. lowercased ) ;
216
229
217
230
let mut op = fst:: map:: OpBuilder :: new ( ) ;
218
231
for map in & import_maps {
@@ -232,17 +245,27 @@ pub fn search_dependencies<'a>(
232
245
if query. anchor_end {
233
246
// Last segment must match query.
234
247
let last = path. segments . last ( ) . unwrap ( ) . to_string ( ) ;
235
- if last. to_lowercase ( ) != query. query {
248
+ if last. to_lowercase ( ) != query. lowercased {
236
249
continue ;
237
250
}
238
251
}
239
252
240
253
// Add the items from this `ModPath` group. Those are all subsequent items in
241
254
// `importables` whose paths match `path`.
242
- res . extend ( importables. iter ( ) . copied ( ) . take_while ( |item| {
255
+ let iter = importables. iter ( ) . copied ( ) . take_while ( |item| {
243
256
let item_path = & import_map. map [ item] ;
244
257
fst_path ( item_path) == fst_path ( path)
245
- } ) ) ;
258
+ } ) ;
259
+
260
+ if query. case_sensitive {
261
+ // FIXME: This does not do a subsequence match.
262
+ res. extend ( iter. filter ( |item| {
263
+ let item_path = & import_map. map [ item] ;
264
+ item_path. to_string ( ) . contains ( & query. query )
265
+ } ) ) ;
266
+ } else {
267
+ res. extend ( iter) ;
268
+ }
246
269
247
270
if res. len ( ) >= query. limit {
248
271
res. truncate ( query. limit ) ;
@@ -582,6 +605,33 @@ mod tests {
582
605
"### ) ;
583
606
}
584
607
608
+ #[ test]
609
+ fn search_casing ( ) {
610
+ let ra_fixture = r#"
611
+ //- /main.rs crate:main deps:dep
612
+ //- /dep.rs crate:dep
613
+
614
+ pub struct fmt;
615
+ pub struct FMT;
616
+ "# ;
617
+
618
+ let res = search_dependencies_of ( ra_fixture, "main" , Query :: new ( "FMT" ) ) ;
619
+
620
+ assert_snapshot ! ( res, @r###"
621
+ dep::FMT (v)
622
+ dep::FMT (t)
623
+ dep::fmt (t)
624
+ dep::fmt (v)
625
+ "### ) ;
626
+
627
+ let res = search_dependencies_of ( ra_fixture, "main" , Query :: new ( "FMT" ) . case_sensitive ( ) ) ;
628
+
629
+ assert_snapshot ! ( res, @r###"
630
+ dep::FMT (v)
631
+ dep::FMT (t)
632
+ "### ) ;
633
+ }
634
+
585
635
#[ test]
586
636
fn search_limit ( ) {
587
637
let res = search_dependencies_of (
0 commit comments