Skip to main content

wowlab_tidy/languages/rust/rules/api/
support.rs

1use ra_ap_syntax::{
2    AstNode,
3    ast::{self, HasAttrs},
4};
5
6// #t(rust_similar_fns) Generic derive lookup intentionally differs from the error rule's specialized Error-derive classification.
7pub(super) fn has_derive(item: &impl HasAttrs, target: &str) -> bool {
8    item.attrs().any(|attr| {
9        attr.as_simple_call().is_some_and(|(name, tokens)| {
10            name == "derive"
11                && tokens.syntax().text().to_string().split(',').any(|entry| {
12                    entry
13                        .trim_matches(|ch: char| ch.is_whitespace() || matches!(ch, '(' | ')'))
14                        .rsplit("::")
15                        .next()
16                        == Some(target)
17                })
18        })
19    })
20}
21
22pub(super) fn type_name(ty: &ast::Type) -> Option<String> {
23    let ast::Type::PathType(path) = ty else {
24        return None;
25    };
26
27    path.path()?
28        .segment()?
29        .name_ref()
30        .map(|name| name.text().to_string())
31}
32
33pub(super) fn path_reachable_from(root: &ast::Type, path: &ast::PathType) -> bool {
34    path.syntax()
35        .ancestors()
36        .take_while(|node| node != root.syntax())
37        .filter_map(ast::Type::cast)
38        .all(|ty| {
39            matches!(
40                ty,
41                ast::Type::PathType(_)
42                    | ast::Type::RefType(_)
43                    | ast::Type::SliceType(_)
44                    | ast::Type::ArrayType(_)
45                    | ast::Type::ParenType(_)
46                    | ast::Type::TupleType(_)
47            )
48        })
49        && matches!(
50            root,
51            ast::Type::PathType(_)
52                | ast::Type::RefType(_)
53                | ast::Type::SliceType(_)
54                | ast::Type::ArrayType(_)
55                | ast::Type::ParenType(_)
56                | ast::Type::TupleType(_)
57        )
58}