Add fn signature query
This commit is contained in:
parent
e5a6cf8153
commit
98957f4e6f
8 changed files with 86 additions and 7 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -107,4 +107,8 @@ impl TypeRef {
|
|||
TypeRef::Error
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unit() -> TypeRef {
|
||||
TypeRef::Tuple(Vec::new())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue