11use fst;
2- use std:: collections:: { HashMap , HashSet } ;
2+ use std:: collections:: { BTreeMap , HashMap , HashSet } ;
33use std:: iter;
44use std:: path:: { Path , PathBuf } ;
55use std:: time:: SystemTime ;
66
77use crate :: raw:: { CrateId , DefKind } ;
88use crate :: { Id , Span , SymbolQuery } ;
9+ use span:: { Column , Row , ZeroIndexed } ;
910
1011/// This is the main database that contains all the collected symbol information,
1112/// such as definitions, their mapping between spans, hierarchy and so on,
1213/// organized in a per-crate fashion.
13- #[ derive( Debug ) ]
1414pub ( crate ) struct Analysis {
1515 /// Contains lowered data with global inter-crate `Id`s per each crate.
1616 pub per_crate : HashMap < CrateId , PerCrateAnalysis > ,
@@ -31,7 +31,6 @@ pub(crate) struct Analysis {
3131 pub src_url_base : String ,
3232}
3333
34- #[ derive( Debug ) ]
3534pub struct PerCrateAnalysis {
3635 // Map span to id of def (either because it is the span of the def, or of
3736 // the def for the ref).
@@ -49,6 +48,7 @@ pub struct PerCrateAnalysis {
4948 pub ref_spans : HashMap < Id , Vec < Span > > ,
5049 pub globs : HashMap < Span , Glob > ,
5150 pub impls : HashMap < Id , Vec < Span > > ,
51+ pub idents : Idents ,
5252
5353 pub root_id : Option < Id > ,
5454 pub timestamp : SystemTime ,
@@ -103,6 +103,34 @@ pub struct Def {
103103 // pub sig: Option<Signature>,
104104}
105105
106+ pub type Idents = HashMap < PathBuf , IdentsByLine > ;
107+ pub type IdentsByLine = BTreeMap < Row < ZeroIndexed > , IdentsByColumn > ;
108+ pub type IdentsByColumn = BTreeMap < Column < ZeroIndexed > , IdentBound > ;
109+
110+ #[ derive( new, Clone , Debug ) ]
111+ pub struct IdentBound {
112+ pub column_end : Column < ZeroIndexed > ,
113+ pub id : Id ,
114+ pub kind : IdentKind ,
115+ }
116+
117+ #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
118+ pub enum IdentKind {
119+ Def ,
120+ Ref ,
121+ }
122+
123+ /// An identifier (either a reference or definition).
124+ ///
125+ /// This struct represents the syntactic name, use the `id` to look up semantic
126+ /// information.
127+ #[ derive( new, Clone , Debug ) ]
128+ pub struct Ident {
129+ pub span : Span ,
130+ pub id : Id ,
131+ pub kind : IdentKind ,
132+ }
133+
106134#[ derive( Debug , Clone ) ]
107135pub struct Signature {
108136 pub span : Span ,
@@ -139,6 +167,7 @@ impl PerCrateAnalysis {
139167 ref_spans : HashMap :: new ( ) ,
140168 globs : HashMap :: new ( ) ,
141169 impls : HashMap :: new ( ) ,
170+ idents : Idents :: new ( ) ,
142171 root_id : None ,
143172 timestamp,
144173 path,
@@ -155,6 +184,48 @@ impl PerCrateAnalysis {
155184 None => false ,
156185 }
157186 }
187+
188+ // Returns all identifiers which overlap with `span`. There is no guarantee about
189+ // the ordering of identifiers in the result, but they will probably be roughly
190+ // in order of appearance.
191+ #[ cfg( feature = "idents" ) ]
192+ fn idents ( & self , span : & Span ) -> Vec < Ident > {
193+ self . idents
194+ . get ( & span. file )
195+ . map ( |by_line| {
196+ ( span. range . row_start ..=span. range . row_end )
197+ . flat_map ( |line| {
198+ let vec = by_line
199+ . get ( & line)
200+ . iter ( )
201+ . flat_map ( |by_col| {
202+ by_col. into_iter ( ) . filter_map ( |( col_start, id) | {
203+ if col_start <= & span. range . col_end
204+ && id. column_end >= span. range . col_start
205+ {
206+ Some ( Ident :: new (
207+ Span :: new (
208+ line,
209+ line,
210+ * col_start,
211+ id. column_end ,
212+ span. file . clone ( ) ,
213+ ) ,
214+ id. id ,
215+ id. kind ,
216+ ) )
217+ } else {
218+ None
219+ }
220+ } )
221+ } )
222+ . collect :: < Vec < Ident > > ( ) ;
223+ vec. into_iter ( )
224+ } )
225+ . collect :: < Vec < Ident > > ( )
226+ } )
227+ . unwrap_or_else ( || Vec :: new ( ) )
228+ }
158229}
159230
160231impl Analysis {
@@ -302,6 +373,19 @@ impl Analysis {
302373 self . for_each_crate ( |c| c. defs_per_file . get ( file) . map ( & f) )
303374 }
304375
376+ #[ cfg( feature = "idents" ) ]
377+ pub fn idents ( & self , span : & Span ) -> Vec < Ident > {
378+ self . for_each_crate ( |c| {
379+ let result = c. idents ( span) ;
380+ if result. is_empty ( ) {
381+ None
382+ } else {
383+ Some ( result)
384+ }
385+ } )
386+ . unwrap_or_else ( Vec :: new)
387+ }
388+
305389 pub fn query_defs ( & self , query : SymbolQuery ) -> Vec < Def > {
306390 let mut crates = Vec :: with_capacity ( self . per_crate . len ( ) ) ;
307391 let stream = query. build_stream ( self . per_crate . values ( ) . map ( |c| {
0 commit comments