Add fn signature query

This commit is contained in:
Florian Diebold 2019-01-06 01:00:34 +01:00
parent e5a6cf8153
commit 98957f4e6f
8 changed files with 86 additions and 7 deletions

View file

@ -108,6 +108,7 @@ salsa::database_storage! {
fn impls_in_module() for hir::db::ImplsInModuleQuery;
fn body_hir() for hir::db::BodyHirQuery;
fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery;
fn fn_signature() for hir::db::FnSignatureQuery;
}
}
}

View file

@ -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<FnSignature> {
type FnSignatureQuery;
use fn crate::function::fn_signature;
}
}
}

View file

@ -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<FnSignature> {
db.fn_signature(self.def_id)
}
pub fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> {
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<TypeRef>,
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<FnSignature> {
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,

View file

@ -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},

View file

@ -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;
}
}
}

View file

@ -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())
}

View file

@ -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<Name> for Path {
fn from(name: Name) -> Path {
Path {
kind: PathKind::Plain,
segments: vec![name],
}
}
}
fn expand_use_tree(
prefix: Option<Path>,
tree: ast::UseTree,

View file

@ -107,4 +107,8 @@ impl TypeRef {
TypeRef::Error
}
}
pub fn unit() -> TypeRef {
TypeRef::Tuple(Vec::new())
}
}