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 impls_in_module() for hir::db::ImplsInModuleQuery;
fn body_hir() for hir::db::BodyHirQuery; fn body_hir() for hir::db::BodyHirQuery;
fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery; 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, DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId,
SourceFileItems, SourceItemId, SourceFileItems, SourceItemId,
query_definitions, query_definitions,
FnScopes, FnSignature, FnScopes,
macros::MacroExpansion, macros::MacroExpansion,
module::{ModuleId, ModuleTree, ModuleSource, module::{ModuleId, ModuleTree, ModuleSource,
nameres::{ItemMap, InputModuleItems}}, nameres::{ItemMap, InputModuleItems}},
@ -103,6 +103,11 @@ pub trait HirDatabase: SyntaxDatabase
type BodySyntaxMappingQuery; type BodySyntaxMappingQuery;
use fn crate::expr::body_syntax_mapping; 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}, 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}; 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> { pub fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> {
let syntax = self.syntax(db); let syntax = self.syntax(db);
FnSignatureInfo::new(syntax.borrowed()) 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)] #[derive(Debug, Clone)]
pub struct FnSignatureInfo { pub struct FnSignatureInfo {
pub name: String, pub name: String,

View file

@ -47,7 +47,7 @@ pub use self::{
ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc}, ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc},
macros::{MacroDef, MacroInput, MacroExpansion}, macros::{MacroDef, MacroInput, MacroExpansion},
module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
function::{Function, FnScopes, ScopesWithSyntaxMapping}, function::{Function, FnSignature, FnScopes, ScopesWithSyntaxMapping},
adt::{Struct, Enum}, adt::{Struct, Enum},
ty::Ty, ty::Ty,
impl_block::{ImplBlock, ImplItem}, impl_block::{ImplBlock, ImplItem},

View file

@ -210,6 +210,7 @@ salsa::database_storage! {
fn impls_in_module() for db::ImplsInModuleQuery; fn impls_in_module() for db::ImplsInModuleQuery;
fn body_hir() for db::BodyHirQuery; fn body_hir() for db::BodyHirQuery;
fn body_syntax_mapping() for db::BodySyntaxMappingQuery; 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()) Name::new("self".into())
} }
pub(crate) fn self_type() -> Name {
Name::new("Self".into())
}
pub(crate) fn tuple_field_name(idx: usize) -> Name { pub(crate) fn tuple_field_name(idx: usize) -> Name {
Name::new(idx.to_string().into()) Name::new(idx.to_string().into())
} }

View file

@ -67,10 +67,7 @@ impl Path {
/// Converts an `ast::NameRef` into a single-identifier `Path`. /// Converts an `ast::NameRef` into a single-identifier `Path`.
pub fn from_name_ref(name_ref: ast::NameRef) -> Path { pub fn from_name_ref(name_ref: ast::NameRef) -> Path {
Path { name_ref.as_name().into()
kind: PathKind::Plain,
segments: vec![name_ref.as_name()],
}
} }
/// `true` is this path is a single identifier, like `foo` /// `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( fn expand_use_tree(
prefix: Option<Path>, prefix: Option<Path>,
tree: ast::UseTree, tree: ast::UseTree,

View file

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