33use crate :: errors:: error;
44use crate :: { parsing, SsrError } ;
55use parsing:: Placeholder ;
6+ use ra_db:: FilePosition ;
67use ra_syntax:: { ast, SmolStr , SyntaxKind , SyntaxNode , SyntaxToken } ;
78use rustc_hash:: { FxHashMap , FxHashSet } ;
89use test_utils:: mark;
910
11+ pub ( crate ) struct ResolutionScope < ' db > {
12+ scope : hir:: SemanticsScope < ' db > ,
13+ hygiene : hir:: Hygiene ,
14+ }
15+
1016pub ( crate ) struct ResolvedRule {
1117 pub ( crate ) pattern : ResolvedPattern ,
1218 pub ( crate ) template : Option < ResolvedPattern > ,
@@ -30,12 +36,11 @@ pub(crate) struct ResolvedPath {
3036impl ResolvedRule {
3137 pub ( crate ) fn new (
3238 rule : parsing:: ParsedRule ,
33- scope : & hir:: SemanticsScope ,
34- hygiene : & hir:: Hygiene ,
39+ resolution_scope : & ResolutionScope ,
3540 index : usize ,
3641 ) -> Result < ResolvedRule , SsrError > {
3742 let resolver =
38- Resolver { scope , hygiene , placeholders_by_stand_in : rule. placeholders_by_stand_in } ;
43+ Resolver { resolution_scope , placeholders_by_stand_in : rule. placeholders_by_stand_in } ;
3944 let resolved_template = if let Some ( template) = rule. template {
4045 Some ( resolver. resolve_pattern_tree ( template) ?)
4146 } else {
@@ -57,8 +62,7 @@ impl ResolvedRule {
5762}
5863
5964struct Resolver < ' a , ' db > {
60- scope : & ' a hir:: SemanticsScope < ' db > ,
61- hygiene : & ' a hir:: Hygiene ,
65+ resolution_scope : & ' a ResolutionScope < ' db > ,
6266 placeholders_by_stand_in : FxHashMap < SmolStr , parsing:: Placeholder > ,
6367}
6468
@@ -104,6 +108,7 @@ impl Resolver<'_, '_> {
104108 && !self . path_contains_placeholder ( & path)
105109 {
106110 let resolution = self
111+ . resolution_scope
107112 . resolve_path ( & path)
108113 . ok_or_else ( || error ! ( "Failed to resolve path `{}`" , node. text( ) ) ) ?;
109114 resolved_paths. insert ( node, ResolvedPath { resolution, depth } ) ;
@@ -131,9 +136,31 @@ impl Resolver<'_, '_> {
131136 }
132137 false
133138 }
139+ }
140+
141+ impl < ' db > ResolutionScope < ' db > {
142+ pub ( crate ) fn new (
143+ sema : & hir:: Semantics < ' db , ra_ide_db:: RootDatabase > ,
144+ lookup_context : FilePosition ,
145+ ) -> ResolutionScope < ' db > {
146+ use ra_syntax:: ast:: AstNode ;
147+ let file = sema. parse ( lookup_context. file_id ) ;
148+ // Find a node at the requested position, falling back to the whole file.
149+ let node = file
150+ . syntax ( )
151+ . token_at_offset ( lookup_context. offset )
152+ . left_biased ( )
153+ . map ( |token| token. parent ( ) )
154+ . unwrap_or_else ( || file. syntax ( ) . clone ( ) ) ;
155+ let scope = sema. scope ( & node) ;
156+ ResolutionScope {
157+ scope,
158+ hygiene : hir:: Hygiene :: new ( sema. db , lookup_context. file_id . into ( ) ) ,
159+ }
160+ }
134161
135162 fn resolve_path ( & self , path : & ast:: Path ) -> Option < hir:: PathResolution > {
136- let hir_path = hir:: Path :: from_src ( path. clone ( ) , self . hygiene ) ?;
163+ let hir_path = hir:: Path :: from_src ( path. clone ( ) , & self . hygiene ) ?;
137164 // First try resolving the whole path. This will work for things like
138165 // `std::collections::HashMap`, but will fail for things like
139166 // `std::collections::HashMap::new`.
0 commit comments