@@ -7,7 +7,7 @@ use fst::{self, Streamer};
77use hir_expand:: name:: Name ;
88use indexmap:: { map:: Entry , IndexMap } ;
99use itertools:: Itertools ;
10- use rustc_hash:: { FxHashMap , FxHasher } ;
10+ use rustc_hash:: { FxHashMap , FxHashSet , FxHasher } ;
1111use smallvec:: SmallVec ;
1212use syntax:: SmolStr ;
1313
@@ -225,13 +225,27 @@ fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo))
225225 lhs_str. cmp ( & rhs_str)
226226}
227227
228+ #[ derive( Debug , Eq , PartialEq , Hash ) ]
229+ pub enum ImportKind {
230+ Module ,
231+ Function ,
232+ Adt ,
233+ EnumVariant ,
234+ Const ,
235+ Static ,
236+ Trait ,
237+ TypeAlias ,
238+ BuiltinType ,
239+ }
240+
228241#[ derive( Debug ) ]
229242pub struct Query {
230243 query : String ,
231244 lowercased : String ,
232245 anchor_end : bool ,
233246 case_sensitive : bool ,
234247 limit : usize ,
248+ exclude_import_kinds : FxHashSet < ImportKind > ,
235249}
236250
237251impl Query {
@@ -242,6 +256,7 @@ impl Query {
242256 anchor_end : false ,
243257 case_sensitive : false ,
244258 limit : usize:: max_value ( ) ,
259+ exclude_import_kinds : FxHashSet :: default ( ) ,
245260 }
246261 }
247262
@@ -260,6 +275,12 @@ impl Query {
260275 pub fn case_sensitive ( self ) -> Self {
261276 Self { case_sensitive : true , ..self }
262277 }
278+
279+ /// Do not include imports of the specified kind in the search results.
280+ pub fn exclude_import_kind ( mut self , import_kind : ImportKind ) -> Self {
281+ self . exclude_import_kinds . insert ( import_kind) ;
282+ self
283+ }
263284}
264285
265286/// Searches dependencies of `krate` for an importable path matching `query`.
@@ -303,10 +324,17 @@ pub fn search_dependencies<'a>(
303324
304325 // Add the items from this `ModPath` group. Those are all subsequent items in
305326 // `importables` whose paths match `path`.
306- let iter = importables. iter ( ) . copied ( ) . take_while ( |item| {
307- let item_path = & import_map. map [ item] . path ;
308- fst_path ( item_path) == fst_path ( path)
309- } ) ;
327+ let iter = importables
328+ . iter ( )
329+ . copied ( )
330+ . take_while ( |item| {
331+ let item_path = & import_map. map [ item] . path ;
332+ fst_path ( item_path) == fst_path ( path)
333+ } )
334+ . filter ( |& item| match item_import_kind ( item) {
335+ Some ( import_kind) => !query. exclude_import_kinds . contains ( & import_kind) ,
336+ None => true ,
337+ } ) ;
310338
311339 if query. case_sensitive {
312340 // FIXME: This does not do a subsequence match.
@@ -341,6 +369,20 @@ pub fn search_dependencies<'a>(
341369 res
342370}
343371
372+ fn item_import_kind ( item : ItemInNs ) -> Option < ImportKind > {
373+ Some ( match item. as_module_def_id ( ) ? {
374+ ModuleDefId :: ModuleId ( _) => ImportKind :: Module ,
375+ ModuleDefId :: FunctionId ( _) => ImportKind :: Function ,
376+ ModuleDefId :: AdtId ( _) => ImportKind :: Adt ,
377+ ModuleDefId :: EnumVariantId ( _) => ImportKind :: EnumVariant ,
378+ ModuleDefId :: ConstId ( _) => ImportKind :: Const ,
379+ ModuleDefId :: StaticId ( _) => ImportKind :: Static ,
380+ ModuleDefId :: TraitId ( _) => ImportKind :: Trait ,
381+ ModuleDefId :: TypeAliasId ( _) => ImportKind :: TypeAlias ,
382+ ModuleDefId :: BuiltinType ( _) => ImportKind :: BuiltinType ,
383+ } )
384+ }
385+
344386#[ cfg( test) ]
345387mod tests {
346388 use base_db:: { fixture:: WithFixture , SourceDatabase , Upcast } ;
@@ -758,4 +800,34 @@ mod tests {
758800 "# ] ] ,
759801 ) ;
760802 }
803+
804+ #[ test]
805+ fn search_exclusions ( ) {
806+ let ra_fixture = r#"
807+ //- /main.rs crate:main deps:dep
808+ //- /dep.rs crate:dep
809+
810+ pub struct fmt;
811+ pub struct FMT;
812+ "# ;
813+
814+ check_search (
815+ ra_fixture,
816+ "main" ,
817+ Query :: new ( "FMT" ) ,
818+ expect ! [ [ r#"
819+ dep::fmt (t)
820+ dep::fmt (v)
821+ dep::FMT (t)
822+ dep::FMT (v)
823+ "# ] ] ,
824+ ) ;
825+
826+ check_search (
827+ ra_fixture,
828+ "main" ,
829+ Query :: new ( "FMT" ) . exclude_import_kind ( ImportKind :: Adt ) ,
830+ expect ! [ [ r#""# ] ] ,
831+ ) ;
832+ }
761833}
0 commit comments