@@ -83,6 +83,11 @@ impl PathResolution {
8383/// Primary API to get semantic information, like types, from syntax trees.
8484pub struct Semantics < ' db , DB > {
8585 pub db : & ' db DB ,
86+ imp : SemanticsImpl < ' db > ,
87+ }
88+
89+ pub struct SemanticsImpl < ' db > {
90+ pub db : & ' db dyn HirDatabase ,
8691 s2d_cache : RefCell < SourceToDefCache > ,
8792 cache : RefCell < FxHashMap < SyntaxNode , HirFileId > > ,
8893}
@@ -95,20 +100,180 @@ impl<DB> fmt::Debug for Semantics<'_, DB> {
95100
96101impl < ' db , DB : HirDatabase > Semantics < ' db , DB > {
97102 pub fn new ( db : & DB ) -> Semantics < DB > {
98- Semantics { db, s2d_cache : Default :: default ( ) , cache : Default :: default ( ) }
103+ let impl_ = SemanticsImpl :: new ( db) ;
104+ Semantics { db, imp : impl_ }
99105 }
100106
101107 pub fn parse ( & self , file_id : FileId ) -> ast:: SourceFile {
102- let tree = self . db . parse ( file_id) . tree ( ) ;
103- self . cache ( tree. syntax ( ) . clone ( ) , file_id. into ( ) ) ;
104- tree
108+ self . imp . parse ( file_id)
105109 }
106110
107111 pub fn ast < T : AstDiagnostic + Diagnostic > ( & self , d : & T ) -> <T as AstDiagnostic >:: AST {
108112 let file_id = d. source ( ) . file_id ;
109113 let root = self . db . parse_or_expand ( file_id) . unwrap ( ) ;
110- self . cache ( root, file_id) ;
111- d. ast ( self . db )
114+ self . imp . cache ( root, file_id) ;
115+ d. ast ( self . db . upcast ( ) )
116+ }
117+
118+ pub fn expand ( & self , macro_call : & ast:: MacroCall ) -> Option < SyntaxNode > {
119+ self . imp . expand ( macro_call)
120+ }
121+
122+ pub fn expand_hypothetical (
123+ & self ,
124+ actual_macro_call : & ast:: MacroCall ,
125+ hypothetical_args : & ast:: TokenTree ,
126+ token_to_map : SyntaxToken ,
127+ ) -> Option < ( SyntaxNode , SyntaxToken ) > {
128+ self . imp . expand_hypothetical ( actual_macro_call, hypothetical_args, token_to_map)
129+ }
130+
131+ pub fn descend_into_macros ( & self , token : SyntaxToken ) -> SyntaxToken {
132+ self . imp . descend_into_macros ( token)
133+ }
134+
135+ pub fn descend_node_at_offset < N : ast:: AstNode > (
136+ & self ,
137+ node : & SyntaxNode ,
138+ offset : TextSize ,
139+ ) -> Option < N > {
140+ self . imp . descend_node_at_offset ( node, offset) . find_map ( N :: cast)
141+ }
142+
143+ pub fn original_range ( & self , node : & SyntaxNode ) -> FileRange {
144+ self . imp . original_range ( node)
145+ }
146+
147+ pub fn diagnostics_range ( & self , diagnostics : & dyn Diagnostic ) -> FileRange {
148+ self . imp . diagnostics_range ( diagnostics)
149+ }
150+
151+ pub fn ancestors_with_macros ( & self , node : SyntaxNode ) -> impl Iterator < Item = SyntaxNode > + ' _ {
152+ self . imp . ancestors_with_macros ( node)
153+ }
154+
155+ pub fn ancestors_at_offset_with_macros (
156+ & self ,
157+ node : & SyntaxNode ,
158+ offset : TextSize ,
159+ ) -> impl Iterator < Item = SyntaxNode > + ' _ {
160+ self . imp . ancestors_at_offset_with_macros ( node, offset)
161+ }
162+
163+ /// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*,
164+ /// search up until it is of the target AstNode type
165+ pub fn find_node_at_offset_with_macros < N : AstNode > (
166+ & self ,
167+ node : & SyntaxNode ,
168+ offset : TextSize ,
169+ ) -> Option < N > {
170+ self . imp . ancestors_at_offset_with_macros ( node, offset) . find_map ( N :: cast)
171+ }
172+
173+ /// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*,
174+ /// descend it and find again
175+ pub fn find_node_at_offset_with_descend < N : AstNode > (
176+ & self ,
177+ node : & SyntaxNode ,
178+ offset : TextSize ,
179+ ) -> Option < N > {
180+ if let Some ( it) = find_node_at_offset ( & node, offset) {
181+ return Some ( it) ;
182+ }
183+
184+ self . imp . descend_node_at_offset ( node, offset) . find_map ( N :: cast)
185+ }
186+
187+ pub fn type_of_expr ( & self , expr : & ast:: Expr ) -> Option < Type > {
188+ self . imp . type_of_expr ( expr)
189+ }
190+
191+ pub fn type_of_pat ( & self , pat : & ast:: Pat ) -> Option < Type > {
192+ self . imp . type_of_pat ( pat)
193+ }
194+
195+ pub fn resolve_method_call ( & self , call : & ast:: MethodCallExpr ) -> Option < Function > {
196+ self . imp . resolve_method_call ( call)
197+ }
198+
199+ pub fn resolve_field ( & self , field : & ast:: FieldExpr ) -> Option < Field > {
200+ self . imp . resolve_field ( field)
201+ }
202+
203+ pub fn resolve_record_field ( & self , field : & ast:: RecordField ) -> Option < ( Field , Option < Local > ) > {
204+ self . imp . resolve_record_field ( field)
205+ }
206+
207+ pub fn resolve_record_field_pat ( & self , field : & ast:: RecordFieldPat ) -> Option < Field > {
208+ self . imp . resolve_record_field_pat ( field)
209+ }
210+
211+ pub fn resolve_macro_call ( & self , macro_call : & ast:: MacroCall ) -> Option < MacroDef > {
212+ self . imp . resolve_macro_call ( macro_call)
213+ }
214+
215+ pub fn resolve_path ( & self , path : & ast:: Path ) -> Option < PathResolution > {
216+ self . imp . resolve_path ( path)
217+ }
218+
219+ pub fn resolve_variant ( & self , record_lit : ast:: RecordLit ) -> Option < VariantId > {
220+ self . imp . resolve_variant ( record_lit)
221+ }
222+
223+ pub fn lower_path ( & self , path : & ast:: Path ) -> Option < Path > {
224+ self . imp . lower_path ( path)
225+ }
226+
227+ pub fn resolve_bind_pat_to_const ( & self , pat : & ast:: BindPat ) -> Option < ModuleDef > {
228+ self . imp . resolve_bind_pat_to_const ( pat)
229+ }
230+
231+ // FIXME: use this instead?
232+ // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
233+
234+ pub fn record_literal_missing_fields ( & self , literal : & ast:: RecordLit ) -> Vec < ( Field , Type ) > {
235+ self . imp . record_literal_missing_fields ( literal)
236+ }
237+
238+ pub fn record_pattern_missing_fields ( & self , pattern : & ast:: RecordPat ) -> Vec < ( Field , Type ) > {
239+ self . imp . record_pattern_missing_fields ( pattern)
240+ }
241+
242+ pub fn to_def < T : ToDef > ( & self , src : & T ) -> Option < T :: Def > {
243+ let src = self . imp . find_file ( src. syntax ( ) . clone ( ) ) . with_value ( src) . cloned ( ) ;
244+ T :: to_def ( & self . imp , src)
245+ }
246+
247+ pub fn to_module_def ( & self , file : FileId ) -> Option < Module > {
248+ self . imp . to_module_def ( file)
249+ }
250+
251+ pub fn scope ( & self , node : & SyntaxNode ) -> SemanticsScope < ' db > {
252+ self . imp . scope ( node)
253+ }
254+
255+ pub fn scope_at_offset ( & self , node : & SyntaxNode , offset : TextSize ) -> SemanticsScope < ' db > {
256+ self . imp . scope_at_offset ( node, offset)
257+ }
258+
259+ pub fn scope_for_def ( & self , def : Trait ) -> SemanticsScope < ' db > {
260+ self . imp . scope_for_def ( def)
261+ }
262+
263+ pub fn assert_contains_node ( & self , node : & SyntaxNode ) {
264+ self . imp . assert_contains_node ( node)
265+ }
266+ }
267+
268+ impl < ' db > SemanticsImpl < ' db > {
269+ pub fn new ( db : & ' db dyn HirDatabase ) -> Self {
270+ Self { db, s2d_cache : Default :: default ( ) , cache : Default :: default ( ) }
271+ }
272+
273+ pub fn parse ( & self , file_id : FileId ) -> ast:: SourceFile {
274+ let tree = self . db . parse ( file_id) . tree ( ) ;
275+ self . cache ( tree. syntax ( ) . clone ( ) , file_id. into ( ) ) ;
276+ tree
112277 }
113278
114279 pub fn expand ( & self , macro_call : & ast:: MacroCall ) -> Option < SyntaxNode > {
@@ -130,9 +295,15 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
130295 self . find_file ( actual_macro_call. syntax ( ) . clone ( ) ) . with_value ( actual_macro_call) ;
131296 let sa = self . analyze2 ( macro_call. map ( |it| it. syntax ( ) ) , None ) ;
132297 let krate = sa. resolver . krate ( ) ?;
133- let macro_call_id = macro_call
134- . as_call_id ( self . db , krate, |path| sa. resolver . resolve_path_as_macro ( self . db , & path) ) ?;
135- hir_expand:: db:: expand_hypothetical ( self . db , macro_call_id, hypothetical_args, token_to_map)
298+ let macro_call_id = macro_call. as_call_id ( self . db . upcast ( ) , krate, |path| {
299+ sa. resolver . resolve_path_as_macro ( self . db . upcast ( ) , & path)
300+ } ) ?;
301+ hir_expand:: db:: expand_hypothetical (
302+ self . db . upcast ( ) ,
303+ macro_call_id,
304+ hypothetical_args,
305+ token_to_map,
306+ )
136307 }
137308
138309 pub fn descend_into_macros ( & self , token : SyntaxToken ) -> SyntaxToken {
@@ -147,7 +318,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
147318 return None ;
148319 }
149320 let file_id = sa. expand ( self . db , token. with_value ( & macro_call) ) ?;
150- let token = file_id. expansion_info ( self . db ) ?. map_token_down ( token. as_ref ( ) ) ?;
321+ let token = file_id. expansion_info ( self . db . upcast ( ) ) ?. map_token_down ( token. as_ref ( ) ) ?;
151322
152323 self . cache ( find_root ( & token. value . parent ( ) ) , token. file_id ) ;
153324
@@ -159,15 +330,16 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
159330 token. value
160331 }
161332
162- pub fn descend_node_at_offset < N : ast :: AstNode > (
333+ pub fn descend_node_at_offset (
163334 & self ,
164335 node : & SyntaxNode ,
165336 offset : TextSize ,
166- ) -> Option < N > {
337+ ) -> impl Iterator < Item = SyntaxNode > + ' _ {
167338 // Handle macro token cases
168339 node. token_at_offset ( offset)
169340 . map ( |token| self . descend_into_macros ( token) )
170- . find_map ( |it| self . ancestors_with_macros ( it. parent ( ) ) . find_map ( N :: cast) )
341+ . map ( |it| self . ancestors_with_macros ( it. parent ( ) ) )
342+ . flatten ( )
171343 }
172344
173345 pub fn original_range ( & self , node : & SyntaxNode ) -> FileRange {
@@ -184,7 +356,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
184356
185357 pub fn ancestors_with_macros ( & self , node : SyntaxNode ) -> impl Iterator < Item = SyntaxNode > + ' _ {
186358 let node = self . find_file ( node) ;
187- node. ancestors_with_macros ( self . db ) . map ( |it| it. value )
359+ node. ancestors_with_macros ( self . db . upcast ( ) ) . map ( |it| it. value )
188360 }
189361
190362 pub fn ancestors_at_offset_with_macros (
@@ -197,29 +369,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
197369 . kmerge_by ( |node1, node2| node1. text_range ( ) . len ( ) < node2. text_range ( ) . len ( ) )
198370 }
199371
200- /// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*,
201- /// search up until it is of the target AstNode type
202- pub fn find_node_at_offset_with_macros < N : AstNode > (
203- & self ,
204- node : & SyntaxNode ,
205- offset : TextSize ,
206- ) -> Option < N > {
207- self . ancestors_at_offset_with_macros ( node, offset) . find_map ( N :: cast)
208- }
209-
210- /// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*,
211- /// descend it and find again
212- pub fn find_node_at_offset_with_descend < N : AstNode > (
213- & self ,
214- node : & SyntaxNode ,
215- offset : TextSize ,
216- ) -> Option < N > {
217- if let Some ( it) = find_node_at_offset ( & node, offset) {
218- return Some ( it) ;
219- }
220- self . descend_node_at_offset ( & node, offset)
221- }
222-
223372 pub fn type_of_expr ( & self , expr : & ast:: Expr ) -> Option < Type > {
224373 self . analyze ( expr. syntax ( ) ) . type_of ( self . db , & expr)
225374 }
@@ -267,9 +416,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
267416 self . analyze ( pat. syntax ( ) ) . resolve_bind_pat_to_const ( self . db , pat)
268417 }
269418
270- // FIXME: use this instead?
271- // pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
272-
273419 pub fn record_literal_missing_fields ( & self , literal : & ast:: RecordLit ) -> Vec < ( Field , Type ) > {
274420 self . analyze ( literal. syntax ( ) )
275421 . record_literal_missing_fields ( self . db , literal)
@@ -282,11 +428,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
282428 . unwrap_or_default ( )
283429 }
284430
285- pub fn to_def < T : ToDef > ( & self , src : & T ) -> Option < T :: Def > {
286- let src = self . find_file ( src. syntax ( ) . clone ( ) ) . with_value ( src) . cloned ( ) ;
287- T :: to_def ( self , src)
288- }
289-
290431 fn with_ctx < F : FnOnce ( & mut SourceToDefCtx ) -> T , T > ( & self , f : F ) -> T {
291432 let mut cache = self . s2d_cache . borrow_mut ( ) ;
292433 let mut ctx = SourceToDefCtx { db : self . db , cache : & mut * cache } ;
@@ -310,7 +451,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
310451 }
311452
312453 pub fn scope_for_def ( & self , def : Trait ) -> SemanticsScope < ' db > {
313- let resolver = def. id . resolver ( self . db ) ;
454+ let resolver = def. id . resolver ( self . db . upcast ( ) ) ;
314455 SemanticsScope { db : self . db , resolver }
315456 }
316457
@@ -331,17 +472,17 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
331472 ChildContainer :: DefWithBodyId ( def) => {
332473 return SourceAnalyzer :: new_for_body ( self . db , def, src, offset)
333474 }
334- ChildContainer :: TraitId ( it) => it. resolver ( self . db ) ,
335- ChildContainer :: ImplId ( it) => it. resolver ( self . db ) ,
336- ChildContainer :: ModuleId ( it) => it. resolver ( self . db ) ,
337- ChildContainer :: EnumId ( it) => it. resolver ( self . db ) ,
338- ChildContainer :: VariantId ( it) => it. resolver ( self . db ) ,
339- ChildContainer :: GenericDefId ( it) => it. resolver ( self . db ) ,
475+ ChildContainer :: TraitId ( it) => it. resolver ( self . db . upcast ( ) ) ,
476+ ChildContainer :: ImplId ( it) => it. resolver ( self . db . upcast ( ) ) ,
477+ ChildContainer :: ModuleId ( it) => it. resolver ( self . db . upcast ( ) ) ,
478+ ChildContainer :: EnumId ( it) => it. resolver ( self . db . upcast ( ) ) ,
479+ ChildContainer :: VariantId ( it) => it. resolver ( self . db . upcast ( ) ) ,
480+ ChildContainer :: GenericDefId ( it) => it. resolver ( self . db . upcast ( ) ) ,
340481 } ;
341482 SourceAnalyzer :: new_for_resolver ( resolver, src)
342483 }
343484
344- fn cache ( & self , root_node : SyntaxNode , file_id : HirFileId ) {
485+ pub fn cache ( & self , root_node : SyntaxNode , file_id : HirFileId ) {
345486 assert ! ( root_node. parent( ) . is_none( ) ) ;
346487 let mut cache = self . cache . borrow_mut ( ) ;
347488 let prev = cache. insert ( root_node, file_id) ;
@@ -357,7 +498,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
357498 cache. get ( root_node) . copied ( )
358499 }
359500
360- fn find_file ( & self , node : SyntaxNode ) -> InFile < SyntaxNode > {
501+ pub fn find_file ( & self , node : SyntaxNode ) -> InFile < SyntaxNode > {
361502 let root_node = find_root ( & node) ;
362503 let file_id = self . lookup ( & root_node) . unwrap_or_else ( || {
363504 panic ! (
@@ -382,14 +523,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
382523pub trait ToDef : AstNode + Clone {
383524 type Def ;
384525
385- fn to_def < DB : HirDatabase > ( sema : & Semantics < DB > , src : InFile < Self > ) -> Option < Self :: Def > ;
526+ fn to_def ( sema : & SemanticsImpl , src : InFile < Self > ) -> Option < Self :: Def > ;
386527}
387528
388529macro_rules! to_def_impls {
389530 ( $( ( $def: path, $ast: path, $meth: ident) ) ,* , ) => { $(
390531 impl ToDef for $ast {
391532 type Def = $def;
392- fn to_def< DB : HirDatabase > ( sema: & Semantics < DB > , src: InFile <Self >) -> Option <Self :: Def > {
533+ fn to_def( sema: & SemanticsImpl , src: InFile <Self >) -> Option <Self :: Def > {
393534 sema. with_ctx( |ctx| ctx. $meth( src) ) . map( <$def>:: from)
394535 }
395536 }
0 commit comments