#[cfg(feature = "hypergraph-monotone-fact-propagation")]
use std::collections::BTreeSet;
use super::shared::*;
use super::substrate::OmenaQueryWorkspaceDiagnosticsSubstrateV0;
pub(super) struct OmenaQueryCrossFileSccDiagnosticTargetV0<'a> {
pub(super) style_path: &'a str,
pub(super) style_source: &'a str,
}
#[cfg(feature = "hypergraph-monotone-fact-propagation")]
pub(super) fn summarize_omena_query_unified_cross_file_scc_diagnostics_for_workspace(
target: OmenaQueryCrossFileSccDiagnosticTargetV0<'_>,
style_sources: &[OmenaQueryStyleSourceInputV0],
source_documents: &[OmenaQuerySourceDocumentInputV0],
package_manifests: &[OmenaQueryStylePackageManifestV0],
resolution_inputs: &OmenaQueryStyleResolutionInputsV0,
substrate: &OmenaQueryWorkspaceDiagnosticsSubstrateV0,
resolver_identity_index: Option<&OmenaResolverStyleModuleConfirmationIdentityIndexV0>,
) -> Vec<OmenaQueryStyleDiagnosticV0> {
let report = collect_omena_query_unified_cross_file_scc_report_shared(
style_sources,
source_documents,
package_manifests,
resolution_inputs,
substrate,
resolver_identity_index,
);
summarize_omena_query_unified_cross_file_scc_diagnostics_from_report(
target.style_path,
target.style_source,
&report,
)
}
#[cfg(feature = "hypergraph-monotone-fact-propagation")]
pub(in crate::style) fn collect_omena_query_unified_cross_file_scc_report_shared(
style_sources: &[OmenaQueryStyleSourceInputV0],
source_documents: &[OmenaQuerySourceDocumentInputV0],
package_manifests: &[OmenaQueryStylePackageManifestV0],
resolution_inputs: &OmenaQueryStyleResolutionInputsV0,
substrate: &OmenaQueryWorkspaceDiagnosticsSubstrateV0,
resolver_identity_index: Option<&OmenaResolverStyleModuleConfirmationIdentityIndexV0>,
) -> crate::OmenaQueryUnifiedCrossFileSccReportV0 {
let summary = super::super::cross_file_summary::summarize_omena_query_workspace_cross_file_summary_with_substrate(
style_sources,
source_documents,
package_manifests,
super::super::cross_file_summary::OmenaQueryWorkspaceCrossFileSummarySubstrateV0 {
style_fact_entries: &substrate.style_fact_entries,
css_modules_resolution: &substrate.css_modules_resolution,
sass_module_resolution: &substrate.sass_resolution_without_path_mappings,
},
resolution_inputs,
resolver_identity_index,
);
let hypergraph = super::super::summarize_omena_query_unified_cross_file_hypergraph(&summary);
super::super::summarize_omena_query_unified_cross_file_scc_report(&hypergraph)
}
#[cfg(feature = "hypergraph-monotone-fact-propagation")]
pub(in crate::style) fn summarize_omena_query_unified_cross_file_scc_diagnostics_from_report(
target_style_path: &str,
target_style_source: &str,
report: &crate::OmenaQueryUnifiedCrossFileSccReportV0,
) -> Vec<OmenaQueryStyleDiagnosticV0> {
if report.sccs.is_empty() {
return Vec::new();
}
let whole_file_range = parser_range_for_byte_span(
target_style_source,
ParserByteSpanV0 {
start: 0,
end: target_style_source.len(),
},
);
let mut emitted = BTreeSet::new();
report
.sccs
.iter()
.filter(|&scc| scc.cross_file)
.filter(|&scc| scc.style_paths.iter().any(|path| path == target_style_path))
.filter(|scc| {
scc.edge_kinds
.iter()
.any(|edge_kind| edge_kind.starts_with("composes"))
})
.cloned()
.filter_map(|scc| {
if !emitted.insert(scc.scc_id.clone()) {
return None;
}
let style_path_count = scc.style_paths.len();
let edge_kinds = scc.edge_kinds.join(", ");
let cycle_paths = scc.style_paths.join(" -> ");
Some(OmenaQueryStyleDiagnosticV0 {
code: "crossFileStyleCycle",
severity: "warning",
provenance: omena_query_evidence_graph_provenance![
"omena-query.unified-cross-file-scc-report",
"omena-query.unified-cross-file-hypergraph",
"omena-query.cross-file-summary",
],
range: whole_file_range,
message: format!(
"Cross-file style dependency cycle across {style_path_count} files via {edge_kinds}: {cycle_paths}"
),
tags: Vec::new(),
create_custom_property: None,
cascade_narrowing: None,
cascade_confidence: None,
polynomial_provenance: None,
cross_file_scc: Some(scc),
})
})
.collect()
}
#[cfg(not(feature = "hypergraph-monotone-fact-propagation"))]
pub(super) fn summarize_omena_query_unified_cross_file_scc_diagnostics_for_workspace(
_target: OmenaQueryCrossFileSccDiagnosticTargetV0<'_>,
_style_sources: &[OmenaQueryStyleSourceInputV0],
_source_documents: &[OmenaQuerySourceDocumentInputV0],
_package_manifests: &[OmenaQueryStylePackageManifestV0],
_resolution_inputs: &OmenaQueryStyleResolutionInputsV0,
_substrate: &OmenaQueryWorkspaceDiagnosticsSubstrateV0,
_resolver_identity_index: Option<&OmenaResolverStyleModuleConfirmationIdentityIndexV0>,
) -> Vec<OmenaQueryStyleDiagnosticV0> {
Vec::new()
}