diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 43 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 12 |
2 files changed, 35 insertions, 20 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index f08827ed3..540ddd0b5 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -91,7 +91,7 @@ fn def_with_body_from_child_node( | |||
91 | #[derive(Debug)] | 91 | #[derive(Debug)] |
92 | pub struct SourceAnalyzer { | 92 | pub struct SourceAnalyzer { |
93 | // FIXME: this doesn't handle macros at all | 93 | // FIXME: this doesn't handle macros at all |
94 | file_id: FileId, | 94 | file_id: HirFileId, |
95 | resolver: Resolver, | 95 | resolver: Resolver, |
96 | body_owner: Option<DefWithBody>, | 96 | body_owner: Option<DefWithBody>, |
97 | body_source_map: Option<Arc<BodySourceMap>>, | 97 | body_source_map: Option<Arc<BodySourceMap>>, |
@@ -141,13 +141,16 @@ impl SourceAnalyzer { | |||
141 | node: &SyntaxNode, | 141 | node: &SyntaxNode, |
142 | offset: Option<TextUnit>, | 142 | offset: Option<TextUnit>, |
143 | ) -> SourceAnalyzer { | 143 | ) -> SourceAnalyzer { |
144 | let def_with_body = def_with_body_from_child_node(db, Source::new(file_id.into(), node)); | 144 | let node_source = Source::new(file_id.into(), node); |
145 | let def_with_body = def_with_body_from_child_node(db, node_source); | ||
145 | if let Some(def) = def_with_body { | 146 | if let Some(def) = def_with_body { |
146 | let source_map = def.body_source_map(db); | 147 | let source_map = def.body_source_map(db); |
147 | let scopes = def.expr_scopes(db); | 148 | let scopes = def.expr_scopes(db); |
148 | let scope = match offset { | 149 | let scope = match offset { |
149 | None => scope_for(&scopes, &source_map, file_id.into(), &node), | 150 | None => scope_for(&scopes, &source_map, node_source), |
150 | Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), | 151 | Some(offset) => { |
152 | scope_for_offset(&scopes, &source_map, Source::new(file_id.into(), offset)) | ||
153 | } | ||
151 | }; | 154 | }; |
152 | let resolver = expr::resolver_for_scope(db, def, scope); | 155 | let resolver = expr::resolver_for_scope(db, def, scope); |
153 | SourceAnalyzer { | 156 | SourceAnalyzer { |
@@ -156,7 +159,7 @@ impl SourceAnalyzer { | |||
156 | body_source_map: Some(source_map), | 159 | body_source_map: Some(source_map), |
157 | infer: Some(def.infer(db)), | 160 | infer: Some(def.infer(db)), |
158 | scopes: Some(scopes), | 161 | scopes: Some(scopes), |
159 | file_id, | 162 | file_id: file_id.into(), |
160 | } | 163 | } |
161 | } else { | 164 | } else { |
162 | SourceAnalyzer { | 165 | SourceAnalyzer { |
@@ -168,18 +171,18 @@ impl SourceAnalyzer { | |||
168 | body_source_map: None, | 171 | body_source_map: None, |
169 | infer: None, | 172 | infer: None, |
170 | scopes: None, | 173 | scopes: None, |
171 | file_id, | 174 | file_id: file_id.into(), |
172 | } | 175 | } |
173 | } | 176 | } |
174 | } | 177 | } |
175 | 178 | ||
176 | fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> { | 179 | fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> { |
177 | let src = Source { file_id: self.file_id.into(), ast: expr }; | 180 | let src = Source { file_id: self.file_id, ast: expr }; |
178 | self.body_source_map.as_ref()?.node_expr(src) | 181 | self.body_source_map.as_ref()?.node_expr(src) |
179 | } | 182 | } |
180 | 183 | ||
181 | fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { | 184 | fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { |
182 | let src = Source { file_id: self.file_id.into(), ast: pat }; | 185 | let src = Source { file_id: self.file_id, ast: pat }; |
183 | self.body_source_map.as_ref()?.node_pat(src) | 186 | self.body_source_map.as_ref()?.node_pat(src) |
184 | } | 187 | } |
185 | 188 | ||
@@ -287,7 +290,7 @@ impl SourceAnalyzer { | |||
287 | let name = name_ref.as_name(); | 290 | let name = name_ref.as_name(); |
288 | let source_map = self.body_source_map.as_ref()?; | 291 | let source_map = self.body_source_map.as_ref()?; |
289 | let scopes = self.scopes.as_ref()?; | 292 | let scopes = self.scopes.as_ref()?; |
290 | let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax())?; | 293 | let scope = scope_for(scopes, source_map, Source::new(self.file_id, name_ref.syntax()))?; |
291 | let entry = scopes.resolve_name_in_scope(scope, &name)?; | 294 | let entry = scopes.resolve_name_in_scope(scope, &name)?; |
292 | Some(ScopeEntryWithSyntax { | 295 | Some(ScopeEntryWithSyntax { |
293 | name: entry.name().clone(), | 296 | name: entry.name().clone(), |
@@ -408,20 +411,19 @@ impl SourceAnalyzer { | |||
408 | fn scope_for( | 411 | fn scope_for( |
409 | scopes: &ExprScopes, | 412 | scopes: &ExprScopes, |
410 | source_map: &BodySourceMap, | 413 | source_map: &BodySourceMap, |
411 | file_id: HirFileId, | 414 | node: Source<&SyntaxNode>, |
412 | node: &SyntaxNode, | ||
413 | ) -> Option<ScopeId> { | 415 | ) -> Option<ScopeId> { |
414 | node.ancestors() | 416 | node.ast |
417 | .ancestors() | ||
415 | .filter_map(ast::Expr::cast) | 418 | .filter_map(ast::Expr::cast) |
416 | .filter_map(|it| source_map.node_expr(Source { file_id, ast: &it })) | 419 | .filter_map(|it| source_map.node_expr(Source::new(node.file_id, &it))) |
417 | .find_map(|it| scopes.scope_for(it)) | 420 | .find_map(|it| scopes.scope_for(it)) |
418 | } | 421 | } |
419 | 422 | ||
420 | fn scope_for_offset( | 423 | fn scope_for_offset( |
421 | scopes: &ExprScopes, | 424 | scopes: &ExprScopes, |
422 | source_map: &BodySourceMap, | 425 | source_map: &BodySourceMap, |
423 | file_id: HirFileId, | 426 | offset: Source<TextUnit>, |
424 | offset: TextUnit, | ||
425 | ) -> Option<ScopeId> { | 427 | ) -> Option<ScopeId> { |
426 | scopes | 428 | scopes |
427 | .scope_by_expr() | 429 | .scope_by_expr() |
@@ -429,7 +431,7 @@ fn scope_for_offset( | |||
429 | .filter_map(|(id, scope)| { | 431 | .filter_map(|(id, scope)| { |
430 | let source = source_map.expr_syntax(*id)?; | 432 | let source = source_map.expr_syntax(*id)?; |
431 | // FIXME: correctly handle macro expansion | 433 | // FIXME: correctly handle macro expansion |
432 | if source.file_id != file_id { | 434 | if source.file_id != offset.file_id { |
433 | return None; | 435 | return None; |
434 | } | 436 | } |
435 | let syntax_node_ptr = | 437 | let syntax_node_ptr = |
@@ -438,9 +440,14 @@ fn scope_for_offset( | |||
438 | }) | 440 | }) |
439 | // find containing scope | 441 | // find containing scope |
440 | .min_by_key(|(ptr, _scope)| { | 442 | .min_by_key(|(ptr, _scope)| { |
441 | (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) | 443 | ( |
444 | !(ptr.range().start() <= offset.ast && offset.ast <= ptr.range().end()), | ||
445 | ptr.range().len(), | ||
446 | ) | ||
447 | }) | ||
448 | .map(|(ptr, scope)| { | ||
449 | adjust(scopes, source_map, ptr, offset.file_id, offset.ast).unwrap_or(*scope) | ||
442 | }) | 450 | }) |
443 | .map(|(ptr, scope)| adjust(scopes, source_map, ptr, file_id, offset).unwrap_or(*scope)) | ||
444 | } | 451 | } |
445 | 452 | ||
446 | // XXX: during completion, cursor might be outside of any particular | 453 | // XXX: during completion, cursor might be outside of any particular |
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 437d73e94..26531cb05 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -223,9 +223,12 @@ impl<N: AstNode> AstId<N> { | |||
223 | } | 223 | } |
224 | } | 224 | } |
225 | 225 | ||
226 | /// FIXME: https://github.com/matklad/with ? | ||
226 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | 227 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] |
227 | pub struct Source<T> { | 228 | pub struct Source<T> { |
228 | pub file_id: HirFileId, | 229 | pub file_id: HirFileId, |
230 | // FIXME: this stores all kind of things, not only `ast`. | ||
231 | // There should be a better name... | ||
229 | pub ast: T, | 232 | pub ast: T, |
230 | } | 233 | } |
231 | 234 | ||
@@ -234,11 +237,16 @@ impl<T> Source<T> { | |||
234 | Source { file_id, ast } | 237 | Source { file_id, ast } |
235 | } | 238 | } |
236 | 239 | ||
240 | // Similarly, naming here is stupid... | ||
241 | pub fn with_ast<U>(&self, ast: U) -> Source<U> { | ||
242 | Source::new(self.file_id, ast) | ||
243 | } | ||
244 | |||
237 | pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { | 245 | pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { |
238 | Source { file_id: self.file_id, ast: f(self.ast) } | 246 | Source::new(self.file_id, f(self.ast)) |
239 | } | 247 | } |
240 | pub fn as_ref(&self) -> Source<&T> { | 248 | pub fn as_ref(&self) -> Source<&T> { |
241 | Source { file_id: self.file_id, ast: &self.ast } | 249 | self.with_ast(&self.ast) |
242 | } | 250 | } |
243 | pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode { | 251 | pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode { |
244 | db.parse_or_expand(self.file_id).expect("source created from invalid file") | 252 | db.parse_or_expand(self.file_id).expect("source created from invalid file") |