diff options
-rw-r--r-- | crates/ra_assists/src/assists/add_missing_impl_members.rs | 49 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/from_id.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 44 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 5 |
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 | ||
240 | use hir::PathResolution; | ||
241 | |||
242 | // TODO handle partial paths, with generic args | ||
243 | // TODO handle value ns? | ||
244 | |||
245 | fn 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`. |
232 | fn resolve_target_trait_def( | 277 | fn resolve_target_trait_def( |
@@ -406,14 +451,14 @@ impl Foo for S { | |||
406 | add_missing_impl_members, | 451 | add_missing_impl_members, |
407 | " | 452 | " |
408 | mod foo { | 453 | mod 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 | } |
412 | struct S; | 457 | struct S; |
413 | impl foo::Foo for S { <|> }", | 458 | impl foo::Foo for S { <|> }", |
414 | " | 459 | " |
415 | mod foo { | 460 | mod 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 | } |
419 | struct S; | 464 | struct 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 | ||
94 | impl 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 | |||
94 | impl From<DefWithBody> for DefWithBodyId { | 110 | impl 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`. |
2 | mod lower; | 2 | mod lower; |
3 | 3 | ||
4 | use std::{iter, sync::Arc}; | 4 | use std::{fmt::Display, iter, sync::Arc}; |
5 | 5 | ||
6 | use hir_expand::{ | 6 | use 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 | ||
257 | impl 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 | |||
251 | pub use hir_expand::name as __name; | 293 | pub 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 | } |