use super::{DomFacts, LiteralExpressions, ValueKind};
use crate::decision::{DecisionBuildError, DecisionTables, NativeAnalysis, TargetPolicy, build};
use alloc::vec::Vec;
use vize_l0::id::NodeId;
use vize_l2::{
artifact::Artifact,
file::{BindingRef, FileArtifact, FileResolution, vue::VueExposure},
resolution::Occurrence,
};
pub(in crate::decision) mod policy;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VueReadKind {
SetupLet,
}
pub struct VueRenderRead<'owner, 'arena> {
pub(in crate::decision::dom) occurrence: &'owner Occurrence<'arena>,
pub(in crate::decision::dom) binding: BindingRef<'owner, 'arena>,
pub(in crate::decision::dom) kind: VueReadKind,
}
impl<'owner, 'arena> VueRenderRead<'owner, 'arena> {
#[must_use]
pub fn occurrence(&self) -> &'owner Occurrence<'arena> {
self.occurrence
}
#[must_use]
pub fn binding(&self) -> BindingRef<'owner, 'arena> {
self.binding
}
#[must_use]
pub fn kind(&self) -> VueReadKind {
self.kind
}
}
pub struct VueRenderExpression<'owner, 'arena> {
pub(in crate::decision::dom) resolution: FileResolution<'owner, 'arena>,
pub(in crate::decision::dom) reads: Vec<VueRenderRead<'owner, 'arena>>,
pub(in crate::decision::dom) value: ValueKind,
}
impl core::fmt::Debug for VueRenderExpression<'_, '_> {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter
.debug_struct("VueRenderExpression")
.field("node", &self.resolution.node())
.field("read_count", &self.reads.len())
.finish_non_exhaustive()
}
}
impl<'owner, 'arena> VueRenderExpression<'owner, 'arena> {
#[must_use]
pub fn resolution(&self) -> FileResolution<'owner, 'arena> {
self.resolution
}
#[must_use]
pub fn reads(&self) -> &[VueRenderRead<'owner, 'arena>] {
&self.reads
}
#[must_use]
pub fn value(&self) -> ValueKind {
self.value
}
}
pub struct NativeVueRenderAnalysis<'view, 'owner, 'descriptor, 'program, 'arena> {
exposure: &'view VueExposure<'owner, 'descriptor, 'program, 'arena>,
analysis: NativeAnalysis<'owner, 'arena>,
}
impl<'owner, 'arena> NativeVueRenderAnalysis<'_, 'owner, '_, '_, 'arena> {
#[must_use]
pub fn file(&self) -> &'owner FileArtifact<'arena> {
self.exposure.file()
}
#[must_use]
pub fn artifact(&self) -> &'owner Artifact<'arena> {
self.file().artifact()
}
#[must_use]
pub fn policy(&self) -> TargetPolicy {
self.analysis.policy()
}
#[must_use]
pub fn tables(&self) -> &DecisionTables {
self.analysis.tables()
}
#[must_use]
pub fn dom(&self) -> Option<&DomFacts<'owner, 'arena>> {
self.analysis.dom()
}
#[must_use]
pub fn expression(&self, node: NodeId) -> Option<&VueRenderExpression<'owner, 'arena>> {
self.analysis.dom()?.vue_expressions.get(node)
}
}
pub fn build_vue_render_decisions<'view, 'owner, 'descriptor, 'program, 'arena>(
exposure: &'view VueExposure<'owner, 'descriptor, 'program, 'arena>,
) -> Result<NativeVueRenderAnalysis<'view, 'owner, 'descriptor, 'program, 'arena>, DecisionBuildError>
{
let file = exposure.file();
if !file.is_complete() {
return Err(DecisionBuildError::IncompleteFile);
}
let analysis = build::build_with(
file.artifact(),
TargetPolicy::Dom,
&LiteralExpressions,
Some(file),
&policy::ExposureReads(exposure),
)?;
Ok(NativeVueRenderAnalysis { exposure, analysis })
}