aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assist_ctx.rs8
-rw-r--r--crates/ra_assists/src/assists/add_new.rs7
-rw-r--r--crates/ra_hir/src/from_source.rs2
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/source_binder.rs68
-rw-r--r--crates/ra_hir_def/src/keys.rs4
-rw-r--r--crates/ra_ide/src/impls.rs31
-rw-r--r--crates/ra_ide/src/references/classify.rs4
8 files changed, 84 insertions, 41 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index 9d533fa0c..43f0d664b 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -1,6 +1,6 @@
1//! This module defines `AssistCtx` -- the API surface that is exposed to assists. 1//! This module defines `AssistCtx` -- the API surface that is exposed to assists.
2use either::Either; 2use either::Either;
3use hir::{db::HirDatabase, InFile, SourceAnalyzer}; 3use hir::{db::HirDatabase, InFile, SourceAnalyzer, SourceBinder};
4use ra_db::FileRange; 4use ra_db::FileRange;
5use ra_fmt::{leading_indent, reindent}; 5use ra_fmt::{leading_indent, reindent};
6use ra_syntax::{ 6use ra_syntax::{
@@ -142,12 +142,16 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
142 pub(crate) fn covering_element(&self) -> SyntaxElement { 142 pub(crate) fn covering_element(&self) -> SyntaxElement {
143 find_covering_element(self.source_file.syntax(), self.frange.range) 143 find_covering_element(self.source_file.syntax(), self.frange.range)
144 } 144 }
145 pub(crate) fn source_binder(&self) -> SourceBinder<'a, DB> {
146 SourceBinder::new(self.db)
147 }
145 pub(crate) fn source_analyzer( 148 pub(crate) fn source_analyzer(
146 &self, 149 &self,
147 node: &SyntaxNode, 150 node: &SyntaxNode,
148 offset: Option<TextUnit>, 151 offset: Option<TextUnit>,
149 ) -> SourceAnalyzer { 152 ) -> SourceAnalyzer {
150 SourceAnalyzer::new(self.db, InFile::new(self.frange.file_id.into(), node), offset) 153 let src = InFile::new(self.frange.file_id.into(), node);
154 self.source_binder().analyze(src, offset)
151 } 155 }
152 156
153 pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { 157 pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs
index d148d6e73..aedcd6286 100644
--- a/crates/ra_assists/src/assists/add_new.rs
+++ b/crates/ra_assists/src/assists/add_new.rs
@@ -1,5 +1,5 @@
1use format_buf::format; 1use format_buf::format;
2use hir::{db::HirDatabase, FromSource, InFile}; 2use hir::{db::HirDatabase, InFile};
3use join_to_string::join; 3use join_to_string::join;
4use ra_syntax::{ 4use ra_syntax::{
5 ast::{ 5 ast::{
@@ -136,15 +136,16 @@ fn find_struct_impl(
136 let module = strukt.syntax().ancestors().find(|node| { 136 let module = strukt.syntax().ancestors().find(|node| {
137 ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) 137 ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
138 })?; 138 })?;
139 let mut sb = ctx.source_binder();
139 140
140 let struct_ty = { 141 let struct_ty = {
141 let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; 142 let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() };
142 hir::Struct::from_source(db, src)?.ty(db) 143 sb.to_def::<hir::Struct, _>(src)?.ty(db)
143 }; 144 };
144 145
145 let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { 146 let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| {
146 let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; 147 let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() };
147 let blk = hir::ImplBlock::from_source(db, src)?; 148 let blk = sb.to_def::<hir::ImplBlock, _>(src)?;
148 149
149 let same_ty = blk.target_ty(db) == struct_ty; 150 let same_ty = blk.target_ty(db) == struct_ty;
150 let not_trait_impl = blk.target_trait(db).is_none(); 151 let not_trait_impl = blk.target_trait(db).is_none();
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 6314be8d4..59722eba3 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -20,7 +20,7 @@ use crate::{
20 MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, 20 MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union,
21}; 21};
22 22
23pub trait FromSource: Sized { 23pub(crate) trait FromSource: Sized {
24 type Ast; 24 type Ast;
25 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self>; 25 fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self>;
26} 26}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index a2350573c..11829f42a 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -45,7 +45,6 @@ pub use crate::{
45 MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, 45 MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias,
46 TypeParam, Union, VariantDef, 46 TypeParam, Union, VariantDef,
47 }, 47 },
48 from_source::FromSource,
49 has_source::HasSource, 48 has_source::HasSource,
50 source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 49 source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
51 source_binder::SourceBinder, 50 source_binder::SourceBinder,
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 00541dbe1..66930e492 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -11,7 +11,7 @@ use hir_def::{
11 ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ImplId, ModuleId, StaticId, 11 ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ImplId, ModuleId, StaticId,
12 StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, 12 StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
13}; 13};
14use hir_expand::InFile; 14use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind};
15use ra_prof::profile; 15use ra_prof::profile;
16use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit}; 16use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit};
17use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
@@ -62,18 +62,7 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> {
62 } 62 }
63 63
64 fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> { 64 fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> {
65 let container = self.find_container(src.as_ref().map(|it| it.syntax()))?; 65 T::to_id(self, src)
66 let db = self.db;
67 let dyn_map =
68 &*self.child_by_source_cache.entry(container).or_insert_with(|| match container {
69 ChildContainer::DefWithBodyId(it) => it.child_by_source(db),
70 ChildContainer::ModuleId(it) => it.child_by_source(db),
71 ChildContainer::TraitId(it) => it.child_by_source(db),
72 ChildContainer::ImplId(it) => it.child_by_source(db),
73 ChildContainer::EnumId(it) => it.child_by_source(db),
74 ChildContainer::VariantId(it) => it.child_by_source(db),
75 });
76 dyn_map[T::KEY].get(&src).copied()
77 } 66 }
78 67
79 fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { 68 fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
@@ -146,19 +135,46 @@ impl_froms! {
146 135
147pub trait ToId: Sized + AstNode + 'static { 136pub trait ToId: Sized + AstNode + 'static {
148 type ID: Sized + Copy + 'static; 137 type ID: Sized + Copy + 'static;
138 fn to_id<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>)
139 -> Option<Self::ID>;
140}
141
142pub trait ToIdByKey: Sized + AstNode + 'static {
143 type ID: Sized + Copy + 'static;
149 const KEY: Key<Self, Self::ID>; 144 const KEY: Key<Self, Self::ID>;
150} 145}
151 146
152macro_rules! to_id_impls { 147impl<T: ToIdByKey> ToId for T {
148 type ID = <T as ToIdByKey>::ID;
149 fn to_id<DB: HirDatabase>(
150 sb: &mut SourceBinder<'_, DB>,
151 src: InFile<Self>,
152 ) -> Option<Self::ID> {
153 let container = sb.find_container(src.as_ref().map(|it| it.syntax()))?;
154 let db = sb.db;
155 let dyn_map =
156 &*sb.child_by_source_cache.entry(container).or_insert_with(|| match container {
157 ChildContainer::DefWithBodyId(it) => it.child_by_source(db),
158 ChildContainer::ModuleId(it) => it.child_by_source(db),
159 ChildContainer::TraitId(it) => it.child_by_source(db),
160 ChildContainer::ImplId(it) => it.child_by_source(db),
161 ChildContainer::EnumId(it) => it.child_by_source(db),
162 ChildContainer::VariantId(it) => it.child_by_source(db),
163 });
164 dyn_map[T::KEY].get(&src).copied()
165 }
166}
167
168macro_rules! to_id_key_impls {
153 ($(($id:ident, $ast:path, $key:path)),* ,) => {$( 169 ($(($id:ident, $ast:path, $key:path)),* ,) => {$(
154 impl ToId for $ast { 170 impl ToIdByKey for $ast {
155 type ID = $id; 171 type ID = $id;
156 const KEY: Key<Self, Self::ID> = $key; 172 const KEY: Key<Self, Self::ID> = $key;
157 } 173 }
158 )*} 174 )*}
159} 175}
160 176
161to_id_impls![ 177to_id_key_impls![
162 (StructId, ast::StructDef, keys::STRUCT), 178 (StructId, ast::StructDef, keys::STRUCT),
163 (UnionId, ast::UnionDef, keys::UNION), 179 (UnionId, ast::UnionDef, keys::UNION),
164 (EnumId, ast::EnumDef, keys::ENUM), 180 (EnumId, ast::EnumDef, keys::ENUM),
@@ -171,3 +187,23 @@ to_id_impls![
171 (StructFieldId, ast::RecordFieldDef, keys::RECORD_FIELD), 187 (StructFieldId, ast::RecordFieldDef, keys::RECORD_FIELD),
172 (EnumVariantId, ast::EnumVariant, keys::ENUM_VARIANT), 188 (EnumVariantId, ast::EnumVariant, keys::ENUM_VARIANT),
173]; 189];
190
191// FIXME: use DynMap as well?
192impl ToId for ast::MacroCall {
193 type ID = MacroDefId;
194 fn to_id<DB: HirDatabase>(
195 sb: &mut SourceBinder<'_, DB>,
196 src: InFile<Self>,
197 ) -> Option<Self::ID> {
198 let kind = MacroDefKind::Declarative;
199
200 let module_src = ModuleSource::from_child_node(sb.db, src.as_ref().map(|it| it.syntax()));
201 let module = crate::Module::from_definition(sb.db, InFile::new(src.file_id, module_src))?;
202 let krate = Some(module.krate().id);
203
204 let ast_id =
205 Some(AstId::new(src.file_id, sb.db.ast_id_map(src.file_id).ast_id(&src.value)));
206
207 Some(MacroDefId { krate, ast_id, kind })
208 }
209}
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs
index d844f7a62..5913f12b1 100644
--- a/crates/ra_hir_def/src/keys.rs
+++ b/crates/ra_hir_def/src/keys.rs
@@ -2,7 +2,7 @@
2 2
3use std::marker::PhantomData; 3use std::marker::PhantomData;
4 4
5use hir_expand::InFile; 5use hir_expand::{InFile, MacroDefId};
6use ra_syntax::{ast, AstNode, AstPtr}; 6use ra_syntax::{ast, AstNode, AstPtr};
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8 8
@@ -29,6 +29,8 @@ pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new();
29pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new(); 29pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new();
30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); 30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
31 31
32pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
33
32/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are 34/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
33/// equal if they point to exactly the same object. 35/// equal if they point to exactly the same object.
34/// 36///
diff --git a/crates/ra_ide/src/impls.rs b/crates/ra_ide/src/impls.rs
index 31195036e..bd14a6d13 100644
--- a/crates/ra_ide/src/impls.rs
+++ b/crates/ra_ide/src/impls.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{FromSource, ImplBlock}; 3use hir::{ImplBlock, SourceBinder};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 5use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
6 6
@@ -12,6 +12,7 @@ pub(crate) fn goto_implementation(
12) -> Option<RangeInfo<Vec<NavigationTarget>>> { 12) -> Option<RangeInfo<Vec<NavigationTarget>>> {
13 let parse = db.parse(position.file_id); 13 let parse = db.parse(position.file_id);
14 let syntax = parse.tree().syntax().clone(); 14 let syntax = parse.tree().syntax().clone();
15 let mut sb = SourceBinder::new(db);
15 16
16 let src = hir::ModuleSource::from_position(db, position); 17 let src = hir::ModuleSource::from_position(db, position);
17 let module = hir::Module::from_definition( 18 let module = hir::Module::from_definition(
@@ -22,12 +23,12 @@ pub(crate) fn goto_implementation(
22 if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { 23 if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) {
23 return Some(RangeInfo::new( 24 return Some(RangeInfo::new(
24 nominal_def.syntax().text_range(), 25 nominal_def.syntax().text_range(),
25 impls_for_def(db, position, &nominal_def, module)?, 26 impls_for_def(&mut sb, position, &nominal_def, module)?,
26 )); 27 ));
27 } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { 28 } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) {
28 return Some(RangeInfo::new( 29 return Some(RangeInfo::new(
29 trait_def.syntax().text_range(), 30 trait_def.syntax().text_range(),
30 impls_for_trait(db, position, &trait_def, module)?, 31 impls_for_trait(&mut sb, position, &trait_def, module)?,
31 )); 32 ));
32 } 33 }
33 34
@@ -35,7 +36,7 @@ pub(crate) fn goto_implementation(
35} 36}
36 37
37fn impls_for_def( 38fn impls_for_def(
38 db: &RootDatabase, 39 sb: &mut SourceBinder<RootDatabase>,
39 position: FilePosition, 40 position: FilePosition,
40 node: &ast::NominalDef, 41 node: &ast::NominalDef,
41 module: hir::Module, 42 module: hir::Module,
@@ -43,43 +44,43 @@ fn impls_for_def(
43 let ty = match node { 44 let ty = match node {
44 ast::NominalDef::StructDef(def) => { 45 ast::NominalDef::StructDef(def) => {
45 let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; 46 let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() };
46 hir::Struct::from_source(db, src)?.ty(db) 47 sb.to_def::<hir::Struct, _>(src)?.ty(sb.db)
47 } 48 }
48 ast::NominalDef::EnumDef(def) => { 49 ast::NominalDef::EnumDef(def) => {
49 let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; 50 let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() };
50 hir::Enum::from_source(db, src)?.ty(db) 51 sb.to_def::<hir::Enum, _>(src)?.ty(sb.db)
51 } 52 }
52 ast::NominalDef::UnionDef(def) => { 53 ast::NominalDef::UnionDef(def) => {
53 let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; 54 let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() };
54 hir::Union::from_source(db, src)?.ty(db) 55 sb.to_def::<hir::Union, _>(src)?.ty(sb.db)
55 } 56 }
56 }; 57 };
57 58
58 let krate = module.krate(); 59 let krate = module.krate();
59 let impls = ImplBlock::all_in_crate(db, krate); 60 let impls = ImplBlock::all_in_crate(sb.db, krate);
60 61
61 Some( 62 Some(
62 impls 63 impls
63 .into_iter() 64 .into_iter()
64 .filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(db))) 65 .filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(sb.db)))
65 .map(|imp| imp.to_nav(db)) 66 .map(|imp| imp.to_nav(sb.db))
66 .collect(), 67 .collect(),
67 ) 68 )
68} 69}
69 70
70fn impls_for_trait( 71fn impls_for_trait(
71 db: &RootDatabase, 72 sb: &mut SourceBinder<RootDatabase>,
72 position: FilePosition, 73 position: FilePosition,
73 node: &ast::TraitDef, 74 node: &ast::TraitDef,
74 module: hir::Module, 75 module: hir::Module,
75) -> Option<Vec<NavigationTarget>> { 76) -> Option<Vec<NavigationTarget>> {
76 let src = hir::InFile { file_id: position.file_id.into(), value: node.clone() }; 77 let src = hir::InFile { file_id: position.file_id.into(), value: node.clone() };
77 let tr = hir::Trait::from_source(db, src)?; 78 let tr = sb.to_def(src)?;
78 79
79 let krate = module.krate(); 80 let krate = module.krate();
80 let impls = ImplBlock::for_trait(db, krate, tr); 81 let impls = ImplBlock::for_trait(sb.db, krate, tr);
81 82
82 Some(impls.into_iter().map(|imp| imp.to_nav(db)).collect()) 83 Some(impls.into_iter().map(|imp| imp.to_nav(sb.db)).collect())
83} 84}
84 85
85#[cfg(test)] 86#[cfg(test)]
@@ -210,7 +211,7 @@ mod tests {
210 " 211 "
211 //- /lib.rs 212 //- /lib.rs
212 #[derive(Copy)] 213 #[derive(Copy)]
213 struct Foo<|>; 214 struct Foo<|>;
214 ", 215 ",
215 &["impl IMPL_BLOCK FileId(1) [0; 15)"], 216 &["impl IMPL_BLOCK FileId(1) [0; 15)"],
216 ); 217 );
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index 4a6e11e27..dcffc3df2 100644
--- a/crates/ra_ide/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -1,6 +1,6 @@
1//! Functions that are used to classify an element from its definition or reference. 1//! Functions that are used to classify an element from its definition or reference.
2 2
3use hir::{FromSource, InFile, Module, ModuleSource, PathResolution, SourceBinder}; 3use hir::{InFile, Module, ModuleSource, PathResolution, SourceBinder};
4use ra_prof::profile; 4use ra_prof::profile;
5use ra_syntax::{ast, match_ast, AstNode}; 5use ra_syntax::{ast, match_ast, AstNode};
6use test_utils::tested_by; 6use test_utils::tested_by;
@@ -101,7 +101,7 @@ pub(crate) fn classify_name(
101 }, 101 },
102 ast::MacroCall(it) => { 102 ast::MacroCall(it) => {
103 let src = name.with_value(it); 103 let src = name.with_value(it);
104 let def = hir::MacroDef::from_source(sb.db, src.clone())?; 104 let def = sb.to_def(src.clone())?;
105 105
106 let module_src = ModuleSource::from_child_node(sb.db, src.as_ref().map(|it| it.syntax())); 106 let module_src = ModuleSource::from_child_node(sb.db, src.as_ref().map(|it| it.syntax()));
107 let module = Module::from_definition(sb.db, src.with_value(module_src))?; 107 let module = Module::from_definition(sb.db, src.with_value(module_src))?;