Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/has_source.rs')
| -rw-r--r-- | crates/hir/src/has_source.rs | 75 |
1 files changed, 69 insertions, 6 deletions
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 7cdcdd76d1..929c8b3c09 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -8,13 +8,14 @@ use hir_def::{ Lookup, MacroId, VariantId, }; use hir_expand::{HirFileId, InFile}; +use hir_ty::{db::InternedClosure, CallableDefId}; use syntax::ast; use tt::TextRange; use crate::{ - db::HirDatabase, Adt, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl, - LifetimeParam, LocalSource, Macro, Module, Static, Struct, Trait, TraitAlias, TypeAlias, - TypeOrConstParam, Union, Variant, + db::HirDatabase, Adt, Callee, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl, + Label, LifetimeParam, LocalSource, Macro, Module, Param, SelfParam, Static, Struct, Trait, + TraitAlias, TypeAlias, TypeOrConstParam, Union, Variant, }; pub trait HasSource { @@ -25,7 +26,7 @@ pub trait HasSource { /// /// The current some implementations can return `InFile` instead of `Option<InFile>`. /// But we made this method `Option` to support rlib in the future - /// by https://github.com/rust-lang/rust-analyzer/issues/6913 + /// by <https://github.com/rust-lang/rust-analyzer/issues/6913> fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>>; } @@ -202,7 +203,7 @@ impl HasSource for TypeOrConstParam { type Ast = Either<ast::TypeOrConstParam, ast::TraitOrAlias>; fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { let child_source = self.id.parent.child_source(db.upcast()); - Some(child_source.map(|it| it[self.id.local_id].clone())) + child_source.map(|it| it.get(self.id.local_id).cloned()).transpose() } } @@ -210,7 +211,7 @@ impl HasSource for LifetimeParam { type Ast = ast::LifetimeParam; fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { let child_source = self.id.parent.child_source(db.upcast()); - Some(child_source.map(|it| it[self.id.local_id].clone())) + child_source.map(|it| it.get(self.id.local_id).cloned()).transpose() } } @@ -222,6 +223,68 @@ impl HasSource for LocalSource { } } +impl HasSource for Param { + type Ast = Either<ast::SelfParam, ast::Param>; + + fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { + match self.func { + Callee::Def(CallableDefId::FunctionId(func)) => { + let InFile { file_id, value } = Function { id: func }.source(db)?; + let params = value.param_list()?; + if let Some(self_param) = params.self_param() { + if let Some(idx) = self.idx.checked_sub(1) { + params.params().nth(idx).map(Either::Right) + } else { + Some(Either::Left(self_param)) + } + } else { + params.params().nth(self.idx).map(Either::Right) + } + .map(|value| InFile { file_id, value }) + } + Callee::Closure(closure, _) => { + let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into()); + let (_, source_map) = db.body_with_source_map(owner); + let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?; + let root = db.parse_or_expand(file_id); + match value.to_node(&root) { + ast::Expr::ClosureExpr(it) => it + .param_list()? + .params() + .nth(self.idx) + .map(Either::Right) + .map(|value| InFile { file_id: ast.file_id, value }), + _ => None, + } + } + _ => None, + } + } +} + +impl HasSource for SelfParam { + type Ast = ast::SelfParam; + + fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { + let InFile { file_id, value } = Function::from(self.func).source(db)?; + value + .param_list() + .and_then(|params| params.self_param()) + .map(|value| InFile { file_id, value }) + } +} + +impl HasSource for Label { + type Ast = ast::Label; + + fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { + let (_body, source_map) = db.body_with_source_map(self.parent); + let src = source_map.label_syntax(self.label_id); + let root = src.file_syntax(db.upcast()); + Some(src.map(|ast| ast.to_node(&root))) + } +} + impl HasSource for ExternCrateDecl { type Ast = ast::ExternCrate; |