stern4rust/
registry_parser.rs1use syn::Item;
6use syn::spanned::Spanned;
7
8use crate::registry_item::RegistryItem;
9use crate::source_file::SourceFile;
10
11pub struct RegistryParser;
18
19impl RegistryParser {
20 pub fn strays(file: &SourceFile) -> Option<Vec<RegistryItem>> {
23 let syntax = syn::parse_file(&file.contents()).ok()?;
24 Some(
25 syntax
26 .items
27 .iter()
28 .filter(|item| !Self::is_declaration(item))
29 .map(|item| Self::stray(file, item))
30 .collect(),
31 )
32 }
33
34 fn is_declaration(item: &Item) -> bool {
39 matches!(item, Item::Mod(module) if module.content.is_none())
40 }
41
42 fn stray(file: &SourceFile, item: &Item) -> RegistryItem {
43 let line = item.span().start().line;
44 RegistryItem::new(line, &Self::label(file, item, line))
45 }
46
47 fn label(file: &SourceFile, item: &Item, line: usize) -> String {
52 match item {
53 Item::Const(inner) => format!("the constant `{}`", inner.ident),
54 Item::Enum(inner) => format!("the enum `{}`", inner.ident),
55 Item::Fn(inner) => format!("the function `{}`", inner.sig.ident),
56 Item::Impl(_) => format!("the impl block `{}`", Self::source_line(file, line)),
57 Item::Mod(inner) => format!("the inline module `{}`", inner.ident),
58 Item::Static(inner) => format!("the static `{}`", inner.ident),
59 Item::Struct(inner) => format!("the struct `{}`", inner.ident),
60 Item::Trait(inner) => format!("the trait `{}`", inner.ident),
61 Item::Type(inner) => format!("the type alias `{}`", inner.ident),
62 Item::Use(_) => format!("the import `{}`", Self::source_line(file, line)),
63 _ => format!("`{}`", Self::source_line(file, line)),
64 }
65 }
66
67 fn source_line(file: &SourceFile, line: usize) -> String {
68 file.lines()
69 .get(line.saturating_sub(1))
70 .map_or_else(String::new, |text| text.trim().to_string())
71 }
72}