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