syncdoc_migrate/
rewrite.rs

1// syncdoc-migrate/src/rewrite.rs
2
3mod inject;
4mod reformat;
5mod strip;
6
7pub use inject::{inject_module_doc_attr, inject_omnidoc_attr};
8pub use strip::strip_doc_attrs;
9use unsynn::*;
10
11use crate::discover::ParsedFile;
12use proc_macro2::TokenStream;
13use reformat::rewrite_preserving_format;
14use strip::strip_doc_attrs_from_items;
15use syncdoc_core::parse::ModuleItem;
16
17pub fn rewrite_file(
18    parsed: &ParsedFile,
19    docs_root: &str,
20    strip: bool,
21    annotate: bool,
22) -> Option<String> {
23    if !strip && !annotate {
24        return None;
25    }
26
27    let mut output = if strip {
28        strip_doc_attrs_from_items(&parsed.content)
29    } else {
30        let mut ts = TokenStream::new();
31        quote::ToTokens::to_tokens(&parsed.content, &mut ts);
32        ts
33    };
34
35    if annotate {
36        // Re-parse to inject annotations
37        if let Ok(content) = output
38            .clone()
39            .into_token_iter()
40            .parse::<syncdoc_core::parse::ModuleContent>()
41        {
42            let mut annotated = TokenStream::new();
43
44            // Inject module_doc! for inner docs if any existed
45            if content.inner_attrs.is_some() || parsed.content.inner_attrs.is_some() {
46                annotated.extend(inject_module_doc_attr(docs_root));
47            }
48
49            // Then handle regular items
50            for item_delimited in &content.items.0 {
51                let mut item_ts = TokenStream::new();
52                quote::ToTokens::to_tokens(&item_delimited.value, &mut item_ts);
53
54                let should_annotate = matches!(
55                    &item_delimited.value,
56                    ModuleItem::Function(_)
57                        | ModuleItem::Enum(_)
58                        | ModuleItem::Struct(_)
59                        | ModuleItem::Module(_)
60                        | ModuleItem::Trait(_)
61                        | ModuleItem::ImplBlock(_)
62                        | ModuleItem::TypeAlias(_)
63                        | ModuleItem::Const(_)
64                        | ModuleItem::Static(_)
65                );
66
67                if should_annotate {
68                    annotated.extend(inject_omnidoc_attr(item_ts, docs_root));
69                } else {
70                    annotated.extend(item_ts);
71                }
72            }
73            output = annotated;
74        }
75    }
76
77    let transformed = output.to_string();
78
79    // Apply format-preserving rewrite
80    rewrite_preserving_format(&parsed.original_source, &transformed).ok()
81}
82
83#[cfg(test)]
84mod rewrite_tests;