rust-analyzer/crates/ide/src/annotations/fn_references.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

104 lines
2.7 KiB
Rust
Raw Normal View History

2020-09-02 15:21:20 +00:00
//! This module implements a methods and free functions search in the specified file.
//! We have to skip tests, so cannot reuse file_structure module.
use hir::Semantics;
use ide_assists::utils::test_related_attribute;
use ide_db::RootDatabase;
2022-10-11 07:37:35 +00:00
use syntax::{ast, ast::HasName, AstNode, SyntaxNode, TextRange};
2022-10-11 07:37:35 +00:00
use crate::FileId;
2022-10-11 07:37:35 +00:00
pub(super) fn find_all_methods(
db: &RootDatabase,
file_id: FileId,
) -> Vec<(TextRange, Option<TextRange>)> {
let sema = Semantics::new(db);
let source_file = sema.parse(file_id);
2022-10-11 07:37:35 +00:00
source_file.syntax().descendants().filter_map(|it| method_range(it)).collect()
}
2022-10-11 07:37:35 +00:00
fn method_range(item: SyntaxNode) -> Option<(TextRange, Option<TextRange>)> {
2020-09-02 15:21:20 +00:00
ast::Fn::cast(item).and_then(|fn_def| {
2020-11-17 13:22:04 +00:00
if test_related_attribute(&fn_def).is_some() {
None
} else {
2022-10-11 07:37:35 +00:00
Some((
fn_def.syntax().text_range(),
fn_def.name().map(|name| name.syntax().text_range()),
))
}
})
}
2020-09-02 15:21:20 +00:00
#[cfg(test)]
mod tests {
2022-10-11 07:37:35 +00:00
use syntax::TextRange;
2020-10-02 15:34:31 +00:00
use crate::fixture;
2022-10-11 07:37:35 +00:00
use crate::TextSize;
2020-09-02 15:21:20 +00:00
use std::ops::RangeInclusive;
#[test]
fn test_find_all_methods() {
2020-10-02 15:34:31 +00:00
let (analysis, pos) = fixture::position(
2020-09-02 15:21:20 +00:00
r#"
2021-01-06 20:15:48 +00:00
fn private_fn() {$0}
2020-09-02 15:21:20 +00:00
pub fn pub_fn() {}
pub fn generic_fn<T>(arg: T) {}
"#,
);
2022-10-11 07:37:35 +00:00
let refs = super::find_all_methods(&analysis.db, pos.file_id);
2020-09-02 15:21:20 +00:00
check_result(&refs, &[3..=13, 27..=33, 47..=57]);
}
#[test]
fn test_find_trait_methods() {
2020-10-02 15:34:31 +00:00
let (analysis, pos) = fixture::position(
2020-09-02 15:21:20 +00:00
r#"
trait Foo {
2021-01-06 20:15:48 +00:00
fn bar() {$0}
2020-09-02 15:21:20 +00:00
fn baz() {}
}
"#,
);
2022-10-11 07:37:35 +00:00
let refs = super::find_all_methods(&analysis.db, pos.file_id);
2020-09-02 15:21:20 +00:00
check_result(&refs, &[19..=22, 35..=38]);
}
#[test]
fn test_skip_tests() {
2020-10-02 15:34:31 +00:00
let (analysis, pos) = fixture::position(
2020-09-02 15:21:20 +00:00
r#"
//- /lib.rs
#[test]
2021-01-06 20:15:48 +00:00
fn foo() {$0}
2020-09-02 15:21:20 +00:00
pub fn pub_fn() {}
mod tests {
#[test]
fn bar() {}
}
"#,
);
2022-10-11 07:37:35 +00:00
let refs = super::find_all_methods(&analysis.db, pos.file_id);
2020-09-02 15:21:20 +00:00
check_result(&refs, &[28..=34]);
}
2022-10-11 07:37:35 +00:00
fn check_result(refs: &[(TextRange, Option<TextRange>)], expected: &[RangeInclusive<u32>]) {
2020-09-02 15:21:20 +00:00
assert_eq!(refs.len(), expected.len());
2022-10-11 07:37:35 +00:00
for (i, &(full, focus)) in refs.iter().enumerate() {
2020-09-02 15:21:20 +00:00
let range = &expected[i];
2022-10-11 07:37:35 +00:00
let item = focus.unwrap_or(full);
assert_eq!(TextSize::from(*range.start()), item.start());
assert_eq!(TextSize::from(*range.end()), item.end());
2020-09-02 15:21:20 +00:00
}
}
}