aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model_impl/function.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model_impl/function.rs')
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
new file mode 100644
index 000000000..13c57ed21
--- /dev/null
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -0,0 +1,82 @@
1mod scope;
2
3use std::sync::Arc;
4
5use ra_db::Cancelable;
6use ra_syntax::{
7 TreePtr,
8 ast::{self, AstNode},
9};
10
11use crate::{
12 DefId, DefKind, HirDatabase, Name, Function, FnSignature, Module,
13 type_ref::{TypeRef, Mutability},
14 expr::Body,
15 impl_block::ImplBlock,
16};
17
18pub use self::scope::{FnScopes, ScopesWithSyntaxMapping};
19
20impl Function {
21 pub(crate) fn new(def_id: DefId) -> Function {
22 Function { def_id }
23 }
24
25 pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> TreePtr<ast::FnDef> {
26 let def_loc = self.def_id.loc(db);
27 assert!(def_loc.kind == DefKind::Function);
28 let syntax = db.file_item(def_loc.source_item_id);
29 ast::FnDef::cast(&syntax).unwrap().to_owned()
30 }
31
32 pub(crate) fn body(&self, db: &impl HirDatabase) -> Cancelable<Arc<Body>> {
33 db.body_hir(self.def_id)
34 }
35
36 pub(crate) fn module(&self, db: &impl HirDatabase) -> Cancelable<Module> {
37 self.def_id.module(db)
38 }
39
40 /// The containing impl block, if this is a method.
41 pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Cancelable<Option<ImplBlock>> {
42 self.def_id.impl_block(db)
43 }
44}
45
46impl FnSignature {
47 pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> {
48 let func = Function::new(def_id);
49 let node = func.source(db);
50 let mut args = Vec::new();
51 if let Some(param_list) = node.param_list() {
52 if let Some(self_param) = param_list.self_param() {
53 let self_type = if let Some(type_ref) = self_param.type_ref() {
54 TypeRef::from_ast(type_ref)
55 } else {
56 let self_type = TypeRef::Path(Name::self_type().into());
57 match self_param.flavor() {
58 ast::SelfParamFlavor::Owned => self_type,
59 ast::SelfParamFlavor::Ref => {
60 TypeRef::Reference(Box::new(self_type), Mutability::Shared)
61 }
62 ast::SelfParamFlavor::MutRef => {
63 TypeRef::Reference(Box::new(self_type), Mutability::Mut)
64 }
65 }
66 };
67 args.push(self_type);
68 }
69 for param in param_list.params() {
70 let type_ref = TypeRef::from_ast_opt(param.type_ref());
71 args.push(type_ref);
72 }
73 }
74 let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) {
75 TypeRef::from_ast(type_ref)
76 } else {
77 TypeRef::unit()
78 };
79 let sig = FnSignature { args, ret_type };
80 Arc::new(sig)
81 }
82}