Repository: typst/typst
File: crates/typst-library/src/model/bibliography.rs (Rust)

Code before:
                return Ok(CslSource::Named(style, warning));
            }
        }

        DataSource::from_value(value).map(CslSource::Normal)
    }
}

impl IntoValue for CslSource {
    fn into_value(self) -> Value {
        match self {
            // We prefer the shorter names which are at the back of the array.
            Self::Named(v, _) => v.names().last().unwrap().into_value(),
            Self::Normal(v) => v.into_value(),
        }
    }
}

/// Lists all references in the bibliography, with optional prefix
type References = Vec<(Option<Content>, Content)>;

/// Maps from the location of a citation group to its rendered content.
type CitationLocationContentMap = FxHashMap<Location, SourceResult<Content>>;

/// Maps from an item key to the location in the bibliography of that item.
type CitationKeyReferenceLocationMap = FxHashMap<EcoString, Location>;

/// Fully formatted citations and references, generated once (through
/// memoization) for the whole document. This setup is necessary because
/// citation formatting is inherently stateful and we need access to all
/// citations to do it.
pub struct Works {
    /// Maps from the location of a citation group to its rendered content.
    pub citations: CitationLocationContentMap,
    /// Lists all references in the bibliography, with optional prefix, or
    /// `None` if the citation style can't be used for bibliographies.
    pub references: Option<References>,
    /// Maps from an item key to the location in the bibliography of that item.
    pub locations: CitationKeyReferenceLocationMap,
    /// Whether the bibliography should have hanging indent.
    pub hanging_indent: bool,
}

impl Works {
    /// Generate all citations and the whole bibliography.
    pub fn generate(engine: &Engine) -> StrResult<Arc<Works>> {
        Self::generate_impl(engine.routines, engine.world, engine.introspector)
    }

    /// The internal implementation of [`Works::generate`].
    #[comemo::memoize]

Review comment (refactor):
I feel like these aliases don't pull their weight and can be removed. Each alias is also harder to read and reason about than the original type, which is otherwise self-evident on what it is about (maps certain X to Y, and the purpose can be inferred from local context). 

The exception for that last statement is the `References` type, whose context might not be immediately clear (in a vacuum). However, that type is only used once, in the definition of the `references` field, so in practice the context is always clear, so the alias should also be removed.

Notably, it isn't deduplicating an otherwise "long" type repeated in multiple places. As a general rule of thumb, we first wait for the problem (very repeated usage) to arrive before refactoring. Not only for aesthetic reasons, but also to prevent us from constantly "refactoring the world" while developing, keeping us sane :)

Code after:
}

impl Works {
    /// Generate all citations and the whole bibliography.
    pub fn generate(engine: &Engine) -> StrResult<Arc<Works>> {
        Self::generate_impl(engine.routines, engine.world, engine.introspector)
    }

    /// The internal implementation of [`Works::generate`].
    #[comemo::memoize]
    fn generate_impl(
        routines: &Routines,
        world: Tracked<dyn World + '_>,
        introspector: Tracked<Introspector>,
    ) -> StrResult<Arc<Works>> {
        let mut generator = Generator::new(routines, world, introspector)?;
        let rendered = generator.drive();
        let works = generator.display(&rendered)?;
        Ok(Arc::new(works))
    }

    /// Extracts the generated references, failing with an error if none have
    /// been generated.
    pub fn references<'a>(
        &'a self,
        elem: &Packed<BibliographyElem>,
        styles: StyleChain,
    ) -> SourceResult<&'a [(Option<Content>, Content, Location)]> {
        self.references
            .as_deref()
            .ok_or_else(|| match elem.style.get_ref(styles).source {
                CslSource::Named(style, _) => eco_format!(
                    "CSL style \"{}\" is not suitable for bibliographies",
                    style.display_name()
                ),
                CslSource::Normal(..) => {
                    "CSL style is not suitable for bibliographies".into()
                }
            })
            .at(elem.span())
    }
}

/// Context for generating the bibliography.
struct Generator<'a> {
    /// The routines that are used to evaluate mathematical material in citations.
    routines: &'a Routines,
    /// The world that is used to evaluate mathematical material in citations.
    world: Tracked<'a, dyn World + 'a>,
    /// The document's bibliography.
    bibliography: Packed<BibliographyElem>,