Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_db/src/call_info.rs')
-rw-r--r--crates/ide_db/src/call_info.rs174
1 files changed, 0 insertions, 174 deletions
diff --git a/crates/ide_db/src/call_info.rs b/crates/ide_db/src/call_info.rs
deleted file mode 100644
index 9e15702c5f..0000000000
--- a/crates/ide_db/src/call_info.rs
+++ /dev/null
@@ -1,174 +0,0 @@
-//! This crate provides primitives for tracking the information about a call site.
-use base_db::FilePosition;
-use either::Either;
-use hir::{HasAttrs, HirDisplay, Semantics, Type};
-use stdx::format_to;
-use syntax::{
- algo,
- ast::{self, HasArgList, HasName},
- AstNode, Direction, SyntaxToken, TextRange, TextSize,
-};
-
-use crate::RootDatabase;
-
-/// Contains information about a call site. Specifically the
-/// `FunctionSignature`and current parameter.
-#[derive(Debug)]
-pub struct CallInfo {
- pub doc: Option<String>,
- pub signature: String,
- pub active_parameter: Option<usize>,
- parameters: Vec<TextRange>,
-}
-
-impl CallInfo {
- pub fn parameter_labels(&self) -> impl Iterator<Item = &str> + '_ {
- self.parameters.iter().map(move |&it| &self.signature[it])
- }
-
- pub fn parameter_ranges(&self) -> &[TextRange] {
- &self.parameters
- }
-
- fn push_param(&mut self, param: &str) {
- if !self.signature.ends_with('(') {
- self.signature.push_str(", ");
- }
- let start = TextSize::of(&self.signature);
- self.signature.push_str(param);
- let end = TextSize::of(&self.signature);
- self.parameters.push(TextRange::new(start, end))
- }
-}
-
-/// Computes parameter information for the given call expression.
-pub fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
- let sema = Semantics::new(db);
- let file = sema.parse(position.file_id);
- let file = file.syntax();
- let token = file
- .token_at_offset(position.offset)
- .left_biased()
- // if the cursor is sandwiched between two space tokens and the call is unclosed
- // this prevents us from leaving the CallExpression
- .and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?;
- let token = sema.descend_into_macros_single(token);
-
- let (callable, active_parameter) = call_info_impl(&sema, token)?;
-
- let mut res =
- CallInfo { doc: None, signature: String::new(), parameters: vec![], active_parameter };
-
- match callable.kind() {
- hir::CallableKind::Function(func) => {
- res.doc = func.docs(db).map(|it| it.into());
- format_to!(res.signature, "fn {}", func.name(db));
- }
- hir::CallableKind::TupleStruct(strukt) => {
- res.doc = strukt.docs(db).map(|it| it.into());
- format_to!(res.signature, "struct {}", strukt.name(db));
- }
- hir::CallableKind::TupleEnumVariant(variant) => {
- res.doc = variant.docs(db).map(|it| it.into());
- format_to!(
- res.signature,
- "enum {}::{}",
- variant.parent_enum(db).name(db),
- variant.name(db)
- );
- }
- hir::CallableKind::Closure => (),
- }
-
- res.signature.push('(');
- {
- if let Some(self_param) = callable.receiver_param(db) {
- format_to!(res.signature, "{}", self_param)
- }
- let mut buf = String::new();
- for (pat, ty) in callable.params(db) {
- buf.clear();
- if let Some(pat) = pat {
- match pat {
- Either::Left(_self) => format_to!(buf, "self: "),
- Either::Right(pat) => format_to!(buf, "{}: ", pat),
- }
- }
- format_to!(buf, "{}", ty.display(db));
- res.push_param(&buf);
- }
- }
- res.signature.push(')');
-
- match callable.kind() {
- hir::CallableKind::Function(_) | hir::CallableKind::Closure => {
- let ret_type = callable.return_type();
- if !ret_type.is_unit() {
- format_to!(res.signature, " -> {}", ret_type.display(db));
- }
- }
- hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
- }
- Some(res)
-}
-
-fn call_info_impl(
- sema: &Semantics<RootDatabase>,
- token: SyntaxToken,
-) -> Option<(hir::Callable, Option<usize>)> {
- // Find the calling expression and it's NameRef
- let parent = token.parent()?;
- let calling_node = parent.ancestors().filter_map(ast::CallableExpr::cast).find(|it| {
- it.arg_list()
- .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start()))
- })?;
-
- let callable = match &calling_node {
- ast::CallableExpr::Call(call) => {
- let expr = call.expr()?;
- sema.type_of_expr(&expr)?.adjusted().as_callable(sema.db)
- }
- ast::CallableExpr::MethodCall(call) => sema.resolve_method_call_as_callable(call),
- }?;
- let active_param = if let Some(arg_list) = calling_node.arg_list() {
- let param = arg_list
- .args()
- .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
- .count();
- Some(param)
- } else {
- None
- };
- Some((callable, active_param))
-}
-
-#[derive(Debug)]
-pub struct ActiveParameter {
- pub ty: Type,
- pub pat: Either<ast::SelfParam, ast::Pat>,
-}
-
-impl ActiveParameter {
- pub fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> {
- let (signature, active_parameter) = call_info_impl(sema, token)?;
-
- let idx = active_parameter?;
- let mut params = signature.params(sema.db);
- if !(idx < params.len()) {
- cov_mark::hit!(too_many_arguments);
- return None;
- }
- let (pat, ty) = params.swap_remove(idx);
- pat.map(|pat| ActiveParameter { ty, pat })
- }
-
- pub fn ident(&self) -> Option<ast::Name> {
- self.pat.as_ref().right().and_then(|param| match param {
- ast::Pat::IdentPat(ident) => ident.name(),
- _ => None,
- })
- }
-}
-
-#[cfg(test)]
-mod tests;