aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assists/add_missing_impl_members.rs49
-rw-r--r--crates/ra_hir/src/code_model.rs13
-rw-r--r--crates/ra_hir/src/from_id.rs16
-rw-r--r--crates/ra_hir/src/source_binder.rs4
-rw-r--r--crates/ra_hir_def/src/path.rs44
-rw-r--r--crates/ra_hir_def/src/resolver.rs5
6 files changed, 128 insertions, 3 deletions
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs
index f0dfe7780..2b0726869 100644
--- a/crates/ra_assists/src/assists/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs
@@ -139,6 +139,12 @@ fn add_missing_impl_members_inner(
139 139
140 ctx.add_assist(AssistId(assist_id), label, |edit| { 140 ctx.add_assist(AssistId(assist_id), label, |edit| {
141 let n_existing_items = impl_item_list.impl_items().count(); 141 let n_existing_items = impl_item_list.impl_items().count();
142 let module = hir::SourceAnalyzer::new(
143 db,
144 hir::InFile::new(file_id.into(), impl_node.syntax()),
145 None,
146 )
147 .module();
142 let substs = get_syntactic_substs(impl_node).unwrap_or_default(); 148 let substs = get_syntactic_substs(impl_node).unwrap_or_default();
143 let generic_def: hir::GenericDef = trait_.into(); 149 let generic_def: hir::GenericDef = trait_.into();
144 let substs_by_param: HashMap<_, _> = generic_def 150 let substs_by_param: HashMap<_, _> = generic_def
@@ -150,6 +156,10 @@ fn add_missing_impl_members_inner(
150 .collect(); 156 .collect();
151 let items = missing_items 157 let items = missing_items
152 .into_iter() 158 .into_iter()
159 .map(|it| match module {
160 Some(module) => qualify_paths(db, hir::InFile::new(file_id.into(), it), module),
161 None => it,
162 })
153 .map(|it| { 163 .map(|it| {
154 substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param) 164 substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param)
155 }) 165 })
@@ -227,6 +237,41 @@ fn substitute_type_params<N: AstNode>(
227 } 237 }
228} 238}
229 239
240use hir::PathResolution;
241
242// TODO handle partial paths, with generic args
243// TODO handle value ns?
244
245fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: hir::Module) -> N {
246 let path_replacements = node
247 .value
248 .syntax()
249 .descendants()
250 .filter_map(ast::Path::cast)
251 .filter_map(|p| {
252 let analyzer = hir::SourceAnalyzer::new(db, node.with_value(p.syntax()), None);
253 let resolution = analyzer.resolve_path(db, &p)?;
254 match resolution {
255 PathResolution::Def(def) => {
256 let found_path = from.find_path(db, def)?;
257 Some((p, found_path.to_ast()))
258 }
259 PathResolution::Local(_)
260 | PathResolution::TypeParam(_)
261 | PathResolution::SelfType(_) => None,
262 PathResolution::Macro(_) => None,
263 PathResolution::AssocItem(_) => None,
264 }
265 })
266 .collect::<Vec<_>>();
267
268 if path_replacements.is_empty() {
269 node.value
270 } else {
271 edit::replace_descendants(&node.value, path_replacements.into_iter())
272 }
273}
274
230/// Given an `ast::ImplBlock`, resolves the target trait (the one being 275/// Given an `ast::ImplBlock`, resolves the target trait (the one being
231/// implemented) to a `ast::TraitDef`. 276/// implemented) to a `ast::TraitDef`.
232fn resolve_target_trait_def( 277fn resolve_target_trait_def(
@@ -406,14 +451,14 @@ impl Foo for S {
406 add_missing_impl_members, 451 add_missing_impl_members,
407 " 452 "
408mod foo { 453mod foo {
409 struct Bar; 454 pub struct Bar;
410 trait Foo { fn foo(&self, bar: Bar); } 455 trait Foo { fn foo(&self, bar: Bar); }
411} 456}
412struct S; 457struct S;
413impl foo::Foo for S { <|> }", 458impl foo::Foo for S { <|> }",
414 " 459 "
415mod foo { 460mod foo {
416 struct Bar; 461 pub struct Bar;
417 trait Foo { fn foo(&self, bar: Bar); } 462 trait Foo { fn foo(&self, bar: Bar); }
418} 463}
419struct S; 464struct S;
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index cc42068a1..4da3db0d6 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -227,6 +227,19 @@ impl Module {
227 pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module { 227 pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module {
228 Module::new(self.krate(), module_id) 228 Module::new(self.krate(), module_id)
229 } 229 }
230
231 pub fn find_path(
232 self,
233 db: &impl DefDatabase,
234 item: ModuleDef,
235 ) -> Option<hir_def::path::ModPath> {
236 // FIXME expose namespace choice
237 hir_def::find_path::find_path(
238 db,
239 hir_def::item_scope::ItemInNs::Types(item.into()),
240 self.into(),
241 )
242 }
230} 243}
231 244
232#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 245#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
index 75a1a7772..c16c17072 100644
--- a/crates/ra_hir/src/from_id.rs
+++ b/crates/ra_hir/src/from_id.rs
@@ -91,6 +91,22 @@ impl From<ModuleDefId> for ModuleDef {
91 } 91 }
92} 92}
93 93
94impl From<ModuleDef> for ModuleDefId {
95 fn from(id: ModuleDef) -> Self {
96 match id {
97 ModuleDef::Module(it) => ModuleDefId::ModuleId(it.into()),
98 ModuleDef::Function(it) => ModuleDefId::FunctionId(it.into()),
99 ModuleDef::Adt(it) => ModuleDefId::AdtId(it.into()),
100 ModuleDef::EnumVariant(it) => ModuleDefId::EnumVariantId(it.into()),
101 ModuleDef::Const(it) => ModuleDefId::ConstId(it.into()),
102 ModuleDef::Static(it) => ModuleDefId::StaticId(it.into()),
103 ModuleDef::Trait(it) => ModuleDefId::TraitId(it.into()),
104 ModuleDef::TypeAlias(it) => ModuleDefId::TypeAliasId(it.into()),
105 ModuleDef::BuiltinType(it) => ModuleDefId::BuiltinType(it),
106 }
107 }
108}
109
94impl From<DefWithBody> for DefWithBodyId { 110impl From<DefWithBody> for DefWithBodyId {
95 fn from(def: DefWithBody) -> Self { 111 fn from(def: DefWithBody) -> Self {
96 match def { 112 match def {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 2c422af8b..71339565f 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -205,6 +205,10 @@ impl SourceAnalyzer {
205 } 205 }
206 } 206 }
207 207
208 pub fn module(&self) -> Option<crate::code_model::Module> {
209 Some(crate::code_model::Module { id: self.resolver.module_id()? })
210 }
211
208 fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> { 212 fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> {
209 let src = InFile { file_id: self.file_id, value: expr }; 213 let src = InFile { file_id: self.file_id, value: expr };
210 self.body_source_map.as_ref()?.node_expr(src) 214 self.body_source_map.as_ref()?.node_expr(src)
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 82cfa67a9..7dd1939b9 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -1,7 +1,7 @@
1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`. 1//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
2mod lower; 2mod lower;
3 3
4use std::{iter, sync::Arc}; 4use std::{fmt::Display, iter, sync::Arc};
5 5
6use hir_expand::{ 6use hir_expand::{
7 hygiene::Hygiene, 7 hygiene::Hygiene,
@@ -78,6 +78,12 @@ impl ModPath {
78 } 78 }
79 self.segments.first() 79 self.segments.first()
80 } 80 }
81
82 pub fn to_ast(&self) -> ast::Path {
83 use ast::AstNode;
84 let parse = ast::SourceFile::parse(&self.to_string());
85 parse.tree().syntax().descendants().find_map(ast::Path::cast).unwrap()
86 }
81} 87}
82 88
83#[derive(Debug, Clone, PartialEq, Eq, Hash)] 89#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -248,6 +254,42 @@ impl From<Name> for ModPath {
248 } 254 }
249} 255}
250 256
257impl Display for ModPath {
258 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
259 let mut first_segment = true;
260 let mut add_segment = |s| {
261 if !first_segment {
262 f.write_str("::")?;
263 }
264 first_segment = false;
265 f.write_str(s)?;
266 Ok(())
267 };
268 match self.kind {
269 PathKind::Plain => {}
270 PathKind::Super(n) => {
271 if n == 0 {
272 add_segment("self")?;
273 }
274 for _ in 0..n {
275 add_segment("super")?;
276 }
277 }
278 PathKind::Crate => add_segment("crate")?,
279 PathKind::Abs => add_segment("")?,
280 PathKind::DollarCrate(_) => add_segment("$crate")?,
281 }
282 for segment in &self.segments {
283 if !first_segment {
284 f.write_str("::")?;
285 }
286 first_segment = false;
287 write!(f, "{}", segment)?;
288 }
289 Ok(())
290 }
291}
292
251pub use hir_expand::name as __name; 293pub use hir_expand::name as __name;
252 294
253#[macro_export] 295#[macro_export]
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 5d16dd087..40d0cb588 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -411,6 +411,11 @@ impl Resolver {
411 }) 411 })
412 } 412 }
413 413
414 pub fn module_id(&self) -> Option<ModuleId> {
415 let (def_map, local_id) = self.module()?;
416 Some(ModuleId { krate: def_map.krate, local_id })
417 }
418
414 pub fn krate(&self) -> Option<CrateId> { 419 pub fn krate(&self) -> Option<CrateId> {
415 self.module().map(|t| t.0.krate) 420 self.module().map(|t| t.0.krate)
416 } 421 }