From 98957f4e6f66469310072dff5dfc3e521a7cd555 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 6 Jan 2019 01:00:34 +0100 Subject: Add fn signature query --- crates/ra_hir/src/db.rs | 7 ++++- crates/ra_hir/src/function.rs | 60 ++++++++++++++++++++++++++++++++++++++++++- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/mock.rs | 1 + crates/ra_hir/src/name.rs | 4 +++ crates/ra_hir/src/path.rs | 14 +++++++--- crates/ra_hir/src/type_ref.rs | 4 +++ 7 files changed, 85 insertions(+), 7 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index aaf367e08..96a3c60b9 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -7,7 +7,7 @@ use crate::{ DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId, SourceFileItems, SourceItemId, query_definitions, - FnScopes, + FnSignature, FnScopes, macros::MacroExpansion, module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}}, @@ -103,6 +103,11 @@ pub trait HirDatabase: SyntaxDatabase type BodySyntaxMappingQuery; use fn crate::expr::body_syntax_mapping; } + + fn fn_signature(def_id: DefId) -> Arc { + type FnSignatureQuery; + use fn crate::function::fn_signature; + } } } diff --git a/crates/ra_hir/src/function.rs b/crates/ra_hir/src/function.rs index 4dbdf81d8..4627be071 100644 --- a/crates/ra_hir/src/function.rs +++ b/crates/ra_hir/src/function.rs @@ -11,7 +11,7 @@ use ra_syntax::{ ast::{self, AstNode, DocCommentsOwner, NameOwner}, }; -use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module, Crate, impl_block::ImplBlock, expr::{Body, BodySyntaxMapping}}; +use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module, Crate, impl_block::ImplBlock, expr::{Body, BodySyntaxMapping}, type_ref::{TypeRef, Mutability}, Name}; pub use self::scope::{FnScopes, ScopesWithSyntaxMapping}; @@ -53,6 +53,10 @@ impl Function { }) } + pub fn signature(&self, db: &impl HirDatabase) -> Arc { + db.fn_signature(self.def_id) + } + pub fn signature_info(&self, db: &impl HirDatabase) -> Option { let syntax = self.syntax(db); FnSignatureInfo::new(syntax.borrowed()) @@ -76,6 +80,60 @@ impl Function { } } +/// The declared signature of a function. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FnSignature { + args: Vec, + ret_type: TypeRef, +} + +impl FnSignature { + pub fn args(&self) -> &[TypeRef] { + &self.args + } + + pub fn ret_type(&self) -> &TypeRef { + &self.ret_type + } +} + +pub(crate) fn fn_signature(db: &impl HirDatabase, def_id: DefId) -> Arc { + let func = Function::new(def_id); + let syntax = func.syntax(db); + let node = syntax.borrowed(); + let mut args = Vec::new(); + if let Some(param_list) = node.param_list() { + if let Some(self_param) = param_list.self_param() { + let self_type = if let Some(type_ref) = self_param.type_ref() { + TypeRef::from_ast(type_ref) + } else { + let self_type = TypeRef::Path(Name::self_type().into()); + match self_param.flavor() { + ast::SelfParamFlavor::Owned => self_type, + ast::SelfParamFlavor::Ref => { + TypeRef::Reference(Box::new(self_type), Mutability::Shared) + } + ast::SelfParamFlavor::MutRef => { + TypeRef::Reference(Box::new(self_type), Mutability::Mut) + } + } + }; + args.push(self_type); + } + for param in param_list.params() { + let type_ref = TypeRef::from_ast_opt(param.type_ref()); + args.push(type_ref); + } + } + let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { + TypeRef::from_ast(type_ref) + } else { + TypeRef::unit() + }; + let sig = FnSignature { args, ret_type }; + Arc::new(sig) +} + #[derive(Debug, Clone)] pub struct FnSignatureInfo { pub name: String, diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 82dc287de..d600b91df 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -47,7 +47,7 @@ pub use self::{ ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc}, macros::{MacroDef, MacroInput, MacroExpansion}, module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, - function::{Function, FnScopes, ScopesWithSyntaxMapping}, + function::{Function, FnSignature, FnScopes, ScopesWithSyntaxMapping}, adt::{Struct, Enum}, ty::Ty, impl_block::{ImplBlock, ImplItem}, diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 661a5a26b..8d176662c 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs @@ -210,6 +210,7 @@ salsa::database_storage! { fn impls_in_module() for db::ImplsInModuleQuery; fn body_hir() for db::BodyHirQuery; fn body_syntax_mapping() for db::BodySyntaxMappingQuery; + fn fn_signature() for db::FnSignatureQuery; } } } diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index 6f95b168f..90229bc54 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs @@ -35,6 +35,10 @@ impl Name { Name::new("self".into()) } + pub(crate) fn self_type() -> Name { + Name::new("Self".into()) + } + pub(crate) fn tuple_field_name(idx: usize) -> Name { Name::new(idx.to_string().into()) } diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index 2e42caffe..dcf4cf8b6 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs @@ -67,10 +67,7 @@ impl Path { /// Converts an `ast::NameRef` into a single-identifier `Path`. pub fn from_name_ref(name_ref: ast::NameRef) -> Path { - Path { - kind: PathKind::Plain, - segments: vec![name_ref.as_name()], - } + name_ref.as_name().into() } /// `true` is this path is a single identifier, like `foo` @@ -92,6 +89,15 @@ impl Path { } } +impl From for Path { + fn from(name: Name) -> Path { + Path { + kind: PathKind::Plain, + segments: vec![name], + } + } +} + fn expand_use_tree( prefix: Option, tree: ast::UseTree, diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs index b36bb35d8..859f330c2 100644 --- a/crates/ra_hir/src/type_ref.rs +++ b/crates/ra_hir/src/type_ref.rs @@ -107,4 +107,8 @@ impl TypeRef { TypeRef::Error } } + + pub fn unit() -> TypeRef { + TypeRef::Tuple(Vec::new()) + } } -- cgit v1.2.3