stern4rust/rules/source/
imported_paths_rule.rs1use crate::finding::model::qualified_call::QualifiedCall;
6use crate::finding::parsing::qualified_call_finder::QualifiedCallFinder;
7use crate::reporting::offence::Offence;
8use crate::reporting::rule_explanation::RuleExplanation;
9use crate::rule::Rule;
10use crate::source_file::SourceFile;
11
12pub struct ImportedPathsRule;
27
28impl ImportedPathsRule {
29 pub fn new() -> Self {
30 Self
31 }
32
33 fn offence(&self, file: &SourceFile, call: &QualifiedCall) -> Offence {
34 Offence::new(
35 file.relative_path(),
36 call.line,
37 self.name(),
38 format!(
39 "`{}` is reached through a path; no import of this file names it",
40 call.path
41 ),
42 format!("add `use {};` and call `{}`", call.import(), call.call()),
43 )
44 .with_subject(&call.path)
45 }
46}
47
48impl Default for ImportedPathsRule {
49 fn default() -> Self {
50 Self::new()
51 }
52}
53
54impl Rule for ImportedPathsRule {
55 fn name(&self) -> &'static str {
56 "imported-paths"
57 }
58
59 fn check(&self, file: &SourceFile) -> Vec<Offence> {
60 QualifiedCallFinder::find(file)
61 .unwrap_or_default()
62 .iter()
63 .map(|call| self.offence(file, call))
64 .collect()
65 }
66
67 fn check_workspace(&self, _files: &[SourceFile]) -> Vec<Offence> {
68 Vec::new()
69 }
70
71 fn requirement(&self) -> Option<&'static str> {
72 None
73 }
74
75 fn is_configured(&self) -> bool {
76 true
77 }
78
79 fn explanation(&self) -> RuleExplanation {
80 RuleExplanation::new(
81 self.name(),
82 "A function is called through a name this file imported, not through a path.",
83 "let parsed = syn::parse_file(text);",
84 "use syn::parse_file;\n\nlet parsed = parse_file(text);",
85 )
86 }
87}