forge_doc/preprocessor/
inheritdoc.rsuse super::{Preprocessor, PreprocessorId};
use crate::{
document::DocumentContent, Comments, Document, ParseItem, ParseSource, PreprocessorOutput,
};
use alloy_primitives::map::HashMap;
use forge_fmt::solang_ext::SafeUnwrap;
pub const INHERITDOC_ID: PreprocessorId = PreprocessorId("inheritdoc");
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Inheritdoc;
impl Preprocessor for Inheritdoc {
fn id(&self) -> PreprocessorId {
INHERITDOC_ID
}
fn preprocess(&self, documents: Vec<Document>) -> Result<Vec<Document>, eyre::Error> {
for document in documents.iter() {
if let DocumentContent::Single(ref item) = document.content {
let context = self.visit_item(item, &documents);
if !context.is_empty() {
document.add_context(self.id(), PreprocessorOutput::Inheritdoc(context));
}
}
}
Ok(documents)
}
}
impl Inheritdoc {
fn visit_item(&self, item: &ParseItem, documents: &Vec<Document>) -> HashMap<String, Comments> {
let mut context = HashMap::default();
let matched = item
.comments
.find_inheritdoc_base()
.and_then(|base| self.try_match_inheritdoc(base, &item.source, documents));
if let Some((key, comments)) = matched {
context.insert(key, comments);
}
for ch in item.children.iter() {
let matched = ch
.comments
.find_inheritdoc_base()
.and_then(|base| self.try_match_inheritdoc(base, &ch.source, documents));
if let Some((key, comments)) = matched {
context.insert(key, comments);
}
}
context
}
fn try_match_inheritdoc(
&self,
base: &str,
source: &ParseSource,
documents: &Vec<Document>,
) -> Option<(String, Comments)> {
for candidate in documents {
if let DocumentContent::Single(ref item) = candidate.content {
if let ParseSource::Contract(ref contract) = item.source {
if base == contract.name.safe_unwrap().name {
for children in item.children.iter() {
if source.ident() == children.source.ident() {
let key = format!("{}.{}", base, source.ident());
return Some((key, children.comments.clone()))
}
}
}
}
}
}
None
}
}