aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-11-14 07:30:30 +0000
committerAleksey Kladov <[email protected]>2019-11-14 07:30:30 +0000
commitda2ca01ebaaaaa47aa09c5848c53b145a68af8fa (patch)
treebed1d8bfef7cd3c42917d30fae2d8002dd00c38c /crates/ra_hir/src
parenta73b7bb3f6af134c781cba1126350749c5a91144 (diff)
Handle macro-generated expressions slightly less wrong
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/expr/scope.rs6
-rw-r--r--crates/ra_hir/src/from_source.rs3
-rw-r--r--crates/ra_hir/src/source_binder.rs44
3 files changed, 38 insertions, 15 deletions
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index fe5e836f2..afba66069 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -166,6 +166,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
166 166
167#[cfg(test)] 167#[cfg(test)]
168mod tests { 168mod tests {
169 use hir_expand::Source;
169 use ra_db::{fixture::WithFixture, SourceDatabase}; 170 use ra_db::{fixture::WithFixture, SourceDatabase};
170 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 171 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
171 use test_utils::{assert_eq_text, extract_offset}; 172 use test_utils::{assert_eq_text, extract_offset};
@@ -189,7 +190,10 @@ mod tests {
189 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); 190 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None);
190 191
191 let scopes = analyzer.scopes(); 192 let scopes = analyzer.scopes();
192 let expr_id = analyzer.body_source_map().node_expr(&marker.into()).unwrap(); 193 let expr_id = analyzer
194 .body_source_map()
195 .node_expr(Source { file_id: file_id.into(), ast: &marker.into() })
196 .unwrap();
193 let scope = scopes.scope_for(expr_id); 197 let scope = scopes.scope_for(expr_id);
194 198
195 let actual = scopes 199 let actual = scopes
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 2c441b0f4..4b561c63d 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -145,7 +145,8 @@ impl Local {
145 Some(res) 145 Some(res)
146 })?; 146 })?;
147 let (_body, source_map) = db.body_with_source_map(parent); 147 let (_body, source_map) = db.body_with_source_map(parent);
148 let pat_id = source_map.node_pat(&src.ast.into())?; 148 let src = src.map(ast::Pat::from);
149 let pat_id = source_map.node_pat(src.as_ref())?;
149 Some(Local { parent, pat_id }) 150 Some(Local { parent, pat_id })
150 } 151 }
151} 152}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index f28e9c931..88eed1137 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -7,8 +7,11 @@
7//! purely for "IDE needs". 7//! purely for "IDE needs".
8use std::sync::Arc; 8use std::sync::Arc;
9 9
10use hir_def::path::known; 10use hir_def::{
11use hir_expand::name::AsName; 11 expr::{ExprId, PatId},
12 path::known,
13};
14use hir_expand::{name::AsName, Source};
12use ra_db::FileId; 15use ra_db::FileId;
13use ra_syntax::{ 16use ra_syntax::{
14 ast::{self, AstNode}, 17 ast::{self, AstNode},
@@ -93,6 +96,8 @@ fn def_with_body_from_child_node(
93/// original source files. It should not be used inside the HIR itself. 96/// original source files. It should not be used inside the HIR itself.
94#[derive(Debug)] 97#[derive(Debug)]
95pub struct SourceAnalyzer { 98pub struct SourceAnalyzer {
99 // FIXME: this doesn't handle macros at all
100 file_id: FileId,
96 resolver: Resolver, 101 resolver: Resolver,
97 body_owner: Option<DefWithBody>, 102 body_owner: Option<DefWithBody>,
98 body_source_map: Option<Arc<BodySourceMap>>, 103 body_source_map: Option<Arc<BodySourceMap>>,
@@ -147,7 +152,7 @@ impl SourceAnalyzer {
147 let source_map = def.body_source_map(db); 152 let source_map = def.body_source_map(db);
148 let scopes = db.expr_scopes(def); 153 let scopes = db.expr_scopes(def);
149 let scope = match offset { 154 let scope = match offset {
150 None => scope_for(&scopes, &source_map, &node), 155 None => scope_for(&scopes, &source_map, file_id.into(), &node),
151 Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), 156 Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset),
152 }; 157 };
153 let resolver = expr::resolver_for_scope(db, def, scope); 158 let resolver = expr::resolver_for_scope(db, def, scope);
@@ -157,6 +162,7 @@ impl SourceAnalyzer {
157 body_source_map: Some(source_map), 162 body_source_map: Some(source_map),
158 infer: Some(def.infer(db)), 163 infer: Some(def.infer(db)),
159 scopes: Some(scopes), 164 scopes: Some(scopes),
165 file_id,
160 } 166 }
161 } else { 167 } else {
162 SourceAnalyzer { 168 SourceAnalyzer {
@@ -168,17 +174,28 @@ impl SourceAnalyzer {
168 body_source_map: None, 174 body_source_map: None,
169 infer: None, 175 infer: None,
170 scopes: None, 176 scopes: None,
177 file_id,
171 } 178 }
172 } 179 }
173 } 180 }
174 181
182 fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> {
183 let src = Source { file_id: self.file_id.into(), ast: expr };
184 self.body_source_map.as_ref()?.node_expr(src)
185 }
186
187 fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
188 let src = Source { file_id: self.file_id.into(), ast: pat };
189 self.body_source_map.as_ref()?.node_pat(src)
190 }
191
175 pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { 192 pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> {
176 let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?; 193 let expr_id = self.expr_id(expr)?;
177 Some(self.infer.as_ref()?[expr_id].clone()) 194 Some(self.infer.as_ref()?[expr_id].clone())
178 } 195 }
179 196
180 pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { 197 pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> {
181 let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?; 198 let pat_id = self.pat_id(pat)?;
182 Some(self.infer.as_ref()?[pat_id].clone()) 199 Some(self.infer.as_ref()?[pat_id].clone())
183 } 200 }
184 201
@@ -191,22 +208,22 @@ impl SourceAnalyzer {
191 } 208 }
192 209
193 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 210 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
194 let expr_id = self.body_source_map.as_ref()?.node_expr(&call.clone().into())?; 211 let expr_id = self.expr_id(&call.clone().into())?;
195 self.infer.as_ref()?.method_resolution(expr_id) 212 self.infer.as_ref()?.method_resolution(expr_id)
196 } 213 }
197 214
198 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { 215 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> {
199 let expr_id = self.body_source_map.as_ref()?.node_expr(&field.clone().into())?; 216 let expr_id = self.expr_id(&field.clone().into())?;
200 self.infer.as_ref()?.field_resolution(expr_id) 217 self.infer.as_ref()?.field_resolution(expr_id)
201 } 218 }
202 219
203 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { 220 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> {
204 let expr_id = self.body_source_map.as_ref()?.node_expr(&record_lit.clone().into())?; 221 let expr_id = self.expr_id(&record_lit.clone().into())?;
205 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 222 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
206 } 223 }
207 224
208 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { 225 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> {
209 let pat_id = self.body_source_map.as_ref()?.node_pat(&record_pat.clone().into())?; 226 let pat_id = self.pat_id(&record_pat.clone().into())?;
210 self.infer.as_ref()?.variant_resolution_for_pat(pat_id) 227 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
211 } 228 }
212 229
@@ -264,13 +281,13 @@ impl SourceAnalyzer {
264 281
265 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { 282 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
266 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { 283 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
267 let expr_id = self.body_source_map.as_ref()?.node_expr(&path_expr.into())?; 284 let expr_id = self.expr_id(&path_expr.into())?;
268 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { 285 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
269 return Some(PathResolution::AssocItem(assoc)); 286 return Some(PathResolution::AssocItem(assoc));
270 } 287 }
271 } 288 }
272 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { 289 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
273 let pat_id = self.body_source_map.as_ref()?.node_pat(&path_pat.into())?; 290 let pat_id = self.pat_id(&path_pat.into())?;
274 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { 291 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
275 return Some(PathResolution::AssocItem(assoc)); 292 return Some(PathResolution::AssocItem(assoc));
276 } 293 }
@@ -285,7 +302,7 @@ impl SourceAnalyzer {
285 let name = name_ref.as_name(); 302 let name = name_ref.as_name();
286 let source_map = self.body_source_map.as_ref()?; 303 let source_map = self.body_source_map.as_ref()?;
287 let scopes = self.scopes.as_ref()?; 304 let scopes = self.scopes.as_ref()?;
288 let scope = scope_for(scopes, source_map, name_ref.syntax()); 305 let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax());
289 let ret = scopes 306 let ret = scopes
290 .scope_chain(scope) 307 .scope_chain(scope)
291 .flat_map(|scope| scopes.entries(scope).iter()) 308 .flat_map(|scope| scopes.entries(scope).iter())
@@ -418,11 +435,12 @@ impl SourceAnalyzer {
418fn scope_for( 435fn scope_for(
419 scopes: &ExprScopes, 436 scopes: &ExprScopes,
420 source_map: &BodySourceMap, 437 source_map: &BodySourceMap,
438 file_id: HirFileId,
421 node: &SyntaxNode, 439 node: &SyntaxNode,
422) -> Option<ScopeId> { 440) -> Option<ScopeId> {
423 node.ancestors() 441 node.ancestors()
424 .filter_map(ast::Expr::cast) 442 .filter_map(ast::Expr::cast)
425 .filter_map(|it| source_map.node_expr(&it)) 443 .filter_map(|it| source_map.node_expr(Source { file_id, ast: &it }))
426 .find_map(|it| scopes.scope_for(it)) 444 .find_map(|it| scopes.scope_for(it))
427} 445}
428 446