perl_module_import_match/
lib.rs1#![deny(unsafe_code)]
7#![warn(rust_2018_idioms)]
8#![warn(missing_docs)]
9#![warn(clippy::all)]
10
11use perl_module_boundary::contains_standalone_module_token;
12use perl_module_import::{ModuleImportKind, parse_module_import_head};
13
14#[must_use]
21pub fn line_references_module_import(line: &str, module_name: &str) -> bool {
22 if line.is_empty() || module_name.is_empty() {
23 return false;
24 }
25
26 let Some(parsed) = parse_module_import_head(line) else {
27 return false;
28 };
29
30 match parsed.kind {
31 ModuleImportKind::Use | ModuleImportKind::Require => parsed.token == module_name,
32 ModuleImportKind::UseParent | ModuleImportKind::UseBase => {
33 contains_standalone_module_token(line, module_name)
34 }
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::line_references_module_import;
41
42 #[test]
43 fn matches_direct_use_and_require_statements() {
44 assert!(line_references_module_import("use Foo::Bar;", "Foo::Bar"));
45 assert!(line_references_module_import("require Foo::Bar;", "Foo::Bar"));
46 }
47
48 #[test]
49 fn matches_parent_and_base_lines_with_boundary_checks() {
50 assert!(line_references_module_import("use parent qw(Foo::Bar Other::Base);", "Foo::Bar"));
51 assert!(line_references_module_import("use base 'Foo::Bar';", "Foo::Bar"));
52 }
53
54 #[test]
55 fn rejects_partial_matches_for_direct_imports() {
56 assert!(!line_references_module_import("use Foo::Barista;", "Foo::Bar"));
57 assert!(!line_references_module_import("require Foo::Barista;", "Foo::Bar"));
58 }
59
60 #[test]
61 fn rejects_non_import_contexts() {
62 assert!(!line_references_module_import("my $x = Foo::Bar->new();", "Foo::Bar"));
63 assert!(!line_references_module_import("package Foo::Bar;", "Foo::Bar"));
64 }
65
66 #[test]
67 fn rejects_empty_inputs() {
68 assert!(!line_references_module_import("", "Foo::Bar"));
69 assert!(!line_references_module_import("use Foo::Bar;", ""));
70 }
71}