summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
blob: b363a516dd1c0c59d9cfe668115de5cb359bf833 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use either::Either;

use crate::{Diagnostic, DiagnosticsContext};

// Diagnostic: private-assoc-item
//
// This diagnostic is triggered if the referenced associated item is not visible from the current
// module.
pub(crate) fn private_assoc_item(
    ctx: &DiagnosticsContext<'_>,
    d: &hir::PrivateAssocItem,
) -> Diagnostic {
    // FIXME: add quickfix
    let name = match d.item.name(ctx.sema.db) {
        Some(name) => format!("`{}` ", name),
        None => String::new(),
    };
    Diagnostic::new(
        "private-assoc-item",
        format!(
            "{} {}is private",
            match d.item {
                hir::AssocItem::Function(_) => "function",
                hir::AssocItem::Const(_) => "const",
                hir::AssocItem::TypeAlias(_) => "type alias",
            },
            name,
        ),
        ctx.sema
            .diagnostics_display_range(d.expr_or_pat.clone().map(|it| match it {
                Either::Left(it) => it.into(),
                Either::Right(it) => match it {
                    Either::Left(it) => it.into(),
                    Either::Right(it) => it.into(),
                },
            }))
            .range,
    )
}

#[cfg(test)]
mod tests {
    use crate::tests::check_diagnostics;

    #[test]
    fn private_method() {
        check_diagnostics(
            r#"
mod module {
    pub struct Struct;
    impl Struct {
        fn method(&self) {}
    }
}
fn main(s: module::Struct) {
    s.method();
  //^^^^^^^^^^ error: function `method` is private
}
"#,
        );
    }

    #[test]
    fn private_func() {
        check_diagnostics(
            r#"
mod module {
    pub struct Struct;
    impl Struct {
        fn func() {}
    }
}
fn main() {
    module::Struct::func();
  //^^^^^^^^^^^^^^^^^^^^ error: function `func` is private
}
"#,
        );
    }

    #[test]
    fn private_const() {
        check_diagnostics(
            r#"
mod module {
    pub struct Struct;
    impl Struct {
        const CONST: u32 = 0;
    }
}
fn main() {
    module::Struct::CONST;
  //^^^^^^^^^^^^^^^^^^^^^ error: const `CONST` is private
}
"#,
        );
    }

    #[test]
    fn private_but_shadowed_in_deref() {
        check_diagnostics(
            r#"
//- minicore: deref
mod module {
    pub struct Struct { field: Inner }
    pub struct Inner;
    impl core::ops::Deref for Struct {
        type Target = Inner;
        fn deref(&self) -> &Inner { &self.field }
    }
    impl Struct {
        fn method(&self) {}
    }
    impl Inner {
        pub fn method(&self) {}
    }
}
fn main(s: module::Struct) {
    s.method();
}
"#,
        );
    }
}