aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/imp.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-01-08 15:16:26 +0000
committerAleksey Kladov <[email protected]>2019-01-08 15:16:26 +0000
commite6a4383bb475b866b67df6bb83ecbdf823d73667 (patch)
tree6dbf7da77cd26e44597c40d1b5c802c552007ae8 /crates/ra_analysis/src/imp.rs
parent2f07976cb51f7be216678f410175ba4c09bc7e71 (diff)
move call-info to a separate file
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r--crates/ra_analysis/src/imp.rs114
1 files changed, 3 insertions, 111 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 98554dd4c..b3f75fdbe 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -3,13 +3,13 @@ use std::sync::Arc;
3use salsa::Database; 3use salsa::Database;
4 4
5use hir::{ 5use hir::{
6 self, FnSignatureInfo, Problem, source_binder, 6 self, Problem, source_binder,
7}; 7};
8use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; 8use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase};
9use ra_editor::{self, find_node_at_offset, assists, LocalEdit, Severity}; 9use ra_editor::{self, find_node_at_offset, assists, LocalEdit, Severity};
10use ra_syntax::{ 10use ra_syntax::{
11 SyntaxNode, TextRange, TextUnit, AstNode, SourceFile, 11 TextRange, AstNode, SourceFile,
12 ast::{self, ArgListOwner, NameOwner}, 12 ast::{self, NameOwner},
13 SyntaxKind::*, 13 SyntaxKind::*,
14}; 14};
15 15
@@ -262,75 +262,6 @@ impl db::RootDatabase {
262 .collect() 262 .collect()
263 } 263 }
264 264
265 pub(crate) fn resolve_callable(
266 &self,
267 position: FilePosition,
268 ) -> Cancelable<Option<(FnSignatureInfo, Option<usize>)>> {
269 let file = self.source_file(position.file_id);
270 let syntax = file.syntax();
271
272 // Find the calling expression and it's NameRef
273 let calling_node = ctry!(FnCallNode::with_node(syntax, position.offset));
274 let name_ref = ctry!(calling_node.name_ref());
275
276 // Resolve the function's NameRef (NOTE: this isn't entirely accurate).
277 let file_symbols = self.index_resolve(name_ref)?;
278 for symbol in file_symbols {
279 if symbol.ptr.kind() == FN_DEF {
280 let fn_file = self.source_file(symbol.file_id);
281 let fn_def = symbol.ptr.resolve(&fn_file);
282 let fn_def = ast::FnDef::cast(&fn_def).unwrap();
283 let descr = ctry!(source_binder::function_from_source(
284 self,
285 symbol.file_id,
286 fn_def
287 )?);
288 if let Some(descriptor) = descr.signature_info(self) {
289 // If we have a calling expression let's find which argument we are on
290 let mut current_parameter = None;
291
292 let num_params = descriptor.params.len();
293 let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();
294
295 if num_params == 1 {
296 if !has_self {
297 current_parameter = Some(0);
298 }
299 } else if num_params > 1 {
300 // Count how many parameters into the call we are.
301 // TODO: This is best effort for now and should be fixed at some point.
302 // It may be better to see where we are in the arg_list and then check
303 // where offset is in that list (or beyond).
304 // Revisit this after we get documentation comments in.
305 if let Some(ref arg_list) = calling_node.arg_list() {
306 let start = arg_list.syntax().range().start();
307
308 let range_search = TextRange::from_to(start, position.offset);
309 let mut commas: usize = arg_list
310 .syntax()
311 .text()
312 .slice(range_search)
313 .to_string()
314 .matches(',')
315 .count();
316
317 // If we have a method call eat the first param since it's just self.
318 if has_self {
319 commas += 1;
320 }
321
322 current_parameter = Some(commas);
323 }
324 }
325
326 return Ok(Some((descriptor, current_parameter)));
327 }
328 }
329 }
330
331 Ok(None)
332 }
333
334 pub(crate) fn rename( 265 pub(crate) fn rename(
335 &self, 266 &self,
336 position: FilePosition, 267 position: FilePosition,
@@ -375,42 +306,3 @@ impl SourceChange {
375 } 306 }
376 } 307 }
377} 308}
378
379enum FnCallNode<'a> {
380 CallExpr(&'a ast::CallExpr),
381 MethodCallExpr(&'a ast::MethodCallExpr),
382}
383
384impl<'a> FnCallNode<'a> {
385 pub fn with_node(syntax: &'a SyntaxNode, offset: TextUnit) -> Option<FnCallNode<'a>> {
386 if let Some(expr) = find_node_at_offset::<ast::CallExpr>(syntax, offset) {
387 return Some(FnCallNode::CallExpr(expr));
388 }
389 if let Some(expr) = find_node_at_offset::<ast::MethodCallExpr>(syntax, offset) {
390 return Some(FnCallNode::MethodCallExpr(expr));
391 }
392 None
393 }
394
395 pub fn name_ref(&self) -> Option<&'a ast::NameRef> {
396 match *self {
397 FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()?.kind() {
398 ast::ExprKind::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
399 _ => return None,
400 }),
401
402 FnCallNode::MethodCallExpr(call_expr) => call_expr
403 .syntax()
404 .children()
405 .filter_map(ast::NameRef::cast)
406 .nth(0),
407 }
408 }
409
410 pub fn arg_list(&self) -> Option<&'a ast::ArgList> {
411 match *self {
412 FnCallNode::CallExpr(expr) => expr.arg_list(),
413 FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
414 }
415 }
416}