aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/lib.rs3
-rw-r--r--crates/ra_hir/src/semantics.rs25
-rw-r--r--crates/ra_hir/src/source_analyzer.rs88
3 files changed, 34 insertions, 82 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index e1cb12cca..9f59d590c 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -45,8 +45,7 @@ pub use crate::{
45 StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, 45 StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef,
46 }, 46 },
47 has_source::HasSource, 47 has_source::HasSource,
48 semantics::{original_range, Semantics, SemanticsScope}, 48 semantics::{original_range, PathResolution, Semantics, SemanticsScope},
49 source_analyzer::PathResolution,
50}; 49};
51 50
52pub use hir_def::{ 51pub use hir_def::{
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index afc7f7ee7..965d185a4 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -19,11 +19,24 @@ use rustc_hash::{FxHashMap, FxHashSet};
19use crate::{ 19use crate::{
20 db::HirDatabase, 20 db::HirDatabase,
21 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 21 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
22 source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer}, 22 source_analyzer::{resolve_hir_path, SourceAnalyzer},
23 Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path, 23 AssocItem, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, Name,
24 PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, 24 Origin, Path, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef,
25}; 25};
26 26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum PathResolution {
29 /// An item
30 Def(ModuleDef),
31 /// A local binding (only value namespace)
32 Local(Local),
33 /// A generic parameter
34 TypeParam(TypeParam),
35 SelfType(ImplDef),
36 Macro(MacroDef),
37 AssocItem(AssocItem),
38}
39
27/// Primary API to get semantic information, like types, from syntax trees. 40/// Primary API to get semantic information, like types, from syntax trees.
28pub struct Semantics<'db, DB> { 41pub struct Semantics<'db, DB> {
29 pub db: &'db DB, 42 pub db: &'db DB,
@@ -171,12 +184,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
171 SemanticsScope { db: self.db, resolver } 184 SemanticsScope { db: self.db, resolver }
172 } 185 }
173 186
174 // FIXME: we only use this in `inline_local_variable` assist, ideally, we
175 // should switch to general reference search infra there.
176 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
177 self.analyze(pat.syntax()).find_all_refs(pat)
178 }
179
180 fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer { 187 fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer {
181 let src = self.find_file(node.clone()); 188 let src = self.find_file(node.clone());
182 self.analyze2(src.as_ref(), None) 189 self.analyze2(src.as_ref(), None)
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 015389fb0..f3f1ed05a 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -7,7 +7,6 @@
7//! purely for "IDE needs". 7//! purely for "IDE needs".
8use std::{iter::once, sync::Arc}; 8use std::{iter::once, sync::Arc};
9 9
10use either::Either;
11use hir_def::{ 10use hir_def::{
12 body::{ 11 body::{
13 scope::{ExprScopes, ScopeId}, 12 scope::{ExprScopes, ScopeId},
@@ -21,12 +20,12 @@ use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
21use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; 20use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment};
22use ra_syntax::{ 21use ra_syntax::{
23 ast::{self, AstNode}, 22 ast::{self, AstNode},
24 AstPtr, SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, 23 SyntaxNode, SyntaxNodePtr, TextUnit,
25}; 24};
26 25
27use crate::{ 26use crate::{
28 db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModPath, ModuleDef, Path, 27 db::HirDatabase, semantics::PathResolution, Adt, Const, EnumVariant, Function, Local, MacroDef,
29 PathKind, Static, Struct, Trait, Type, TypeAlias, TypeParam, 28 ModPath, ModuleDef, Path, PathKind, Static, Struct, Trait, Type, TypeAlias, TypeParam,
30}; 29};
31 30
32/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 31/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
@@ -41,25 +40,6 @@ pub(crate) struct SourceAnalyzer {
41 scopes: Option<Arc<ExprScopes>>, 40 scopes: Option<Arc<ExprScopes>>,
42} 41}
43 42
44#[derive(Debug, Clone, PartialEq, Eq)]
45pub enum PathResolution {
46 /// An item
47 Def(crate::ModuleDef),
48 /// A local binding (only value namespace)
49 Local(Local),
50 /// A generic parameter
51 TypeParam(TypeParam),
52 SelfType(crate::ImplDef),
53 Macro(MacroDef),
54 AssocItem(crate::AssocItem),
55}
56
57#[derive(Debug)]
58pub struct ReferenceDescriptor {
59 pub range: TextRange,
60 pub name: String,
61}
62
63impl SourceAnalyzer { 43impl SourceAnalyzer {
64 pub(crate) fn new_for_body( 44 pub(crate) fn new_for_body(
65 db: &impl HirDatabase, 45 db: &impl HirDatabase,
@@ -111,20 +91,16 @@ impl SourceAnalyzer {
111 fn expand_expr( 91 fn expand_expr(
112 &self, 92 &self,
113 db: &impl HirDatabase, 93 db: &impl HirDatabase,
114 expr: InFile<&ast::Expr>, 94 expr: InFile<ast::MacroCall>,
115 ) -> Option<InFile<ast::Expr>> { 95 ) -> Option<InFile<ast::Expr>> {
116 let macro_call = ast::MacroCall::cast(expr.value.syntax().clone())?; 96 let macro_file = self.body_source_map.as_ref()?.node_macro_file(expr.as_ref())?;
117 let macro_file =
118 self.body_source_map.as_ref()?.node_macro_file(expr.with_value(&macro_call))?;
119 let expanded = db.parse_or_expand(macro_file)?; 97 let expanded = db.parse_or_expand(macro_file)?;
120 let kind = expanded.kind();
121 let expr = InFile::new(macro_file, ast::Expr::cast(expanded)?);
122 98
123 if ast::MacroCall::can_cast(kind) { 99 let res = match ast::MacroCall::cast(expanded.clone()) {
124 self.expand_expr(db, expr.as_ref()) 100 Some(call) => self.expand_expr(db, InFile::new(macro_file, call))?,
125 } else { 101 _ => InFile::new(macro_file, ast::Expr::cast(expanded)?),
126 Some(expr) 102 };
127 } 103 Some(res)
128 } 104 }
129 105
130 fn trait_env(&self, db: &impl HirDatabase) -> Arc<TraitEnvironment> { 106 fn trait_env(&self, db: &impl HirDatabase) -> Arc<TraitEnvironment> {
@@ -132,11 +108,13 @@ impl SourceAnalyzer {
132 } 108 }
133 109
134 pub(crate) fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { 110 pub(crate) fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> {
135 let expr_id = if let Some(expr) = self.expand_expr(db, InFile::new(self.file_id, expr)) { 111 let expr_id = match expr {
136 self.body_source_map.as_ref()?.node_expr(expr.as_ref())? 112 ast::Expr::MacroCall(call) => {
137 } else { 113 let expr = self.expand_expr(db, InFile::new(self.file_id, call.clone()))?;
138 self.expr_id(expr)? 114 self.body_source_map.as_ref()?.node_expr(expr.as_ref())
139 }; 115 }
116 _ => self.expr_id(expr),
117 }?;
140 118
141 let ty = self.infer.as_ref()?[expr_id].clone(); 119 let ty = self.infer.as_ref()?[expr_id].clone();
142 let environment = self.trait_env(db); 120 let environment = self.trait_env(db);
@@ -251,38 +229,6 @@ impl SourceAnalyzer {
251 resolve_hir_path(db, &self.resolver, &hir_path) 229 resolve_hir_path(db, &self.resolver, &hir_path)
252 } 230 }
253 231
254 fn resolve_local_name(
255 &self,
256 name_ref: &ast::NameRef,
257 ) -> Option<Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>> {
258 let name = name_ref.as_name();
259 let source_map = self.body_source_map.as_ref()?;
260 let scopes = self.scopes.as_ref()?;
261 let scope = scope_for(scopes, source_map, InFile::new(self.file_id, name_ref.syntax()))?;
262 let entry = scopes.resolve_name_in_scope(scope, &name)?;
263 Some(source_map.pat_syntax(entry.pat())?.value)
264 }
265
266 // FIXME: we only use this in `inline_local_variable` assist, ideally, we
267 // should switch to general reference search infra there.
268 pub(crate) fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
269 let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
270 let ptr = Either::Left(AstPtr::new(&ast::Pat::from(pat.clone())));
271 fn_def
272 .syntax()
273 .descendants()
274 .filter_map(ast::NameRef::cast)
275 .filter(|name_ref| match self.resolve_local_name(&name_ref) {
276 None => false,
277 Some(d_ptr) => d_ptr == ptr,
278 })
279 .map(|name_ref| ReferenceDescriptor {
280 name: name_ref.text().to_string(),
281 range: name_ref.syntax().text_range(),
282 })
283 .collect()
284 }
285
286 pub(crate) fn expand( 232 pub(crate) fn expand(
287 &self, 233 &self,
288 db: &impl HirDatabase, 234 db: &impl HirDatabase,