next_swc_napi/next_api/
analyze.rs

1use std::{iter::once, sync::Arc};
2
3use anyhow::Result;
4use next_api::{
5    analyze::{AnalyzeDataOutputAsset, ModulesDataOutputAsset},
6    project::ProjectContainer,
7};
8use turbo_tasks::{Effects, ReadRef, ResolvedVc, TryJoinIterExt, Vc};
9use turbopack_core::{diagnostics::PlainDiagnostic, issue::PlainIssue, output::OutputAssets};
10
11use crate::next_api::utils::strongly_consistent_catch_collectables;
12
13#[turbo_tasks::value(serialization = "none")]
14pub struct WriteAnalyzeResult {
15    pub issues: Arc<Vec<ReadRef<PlainIssue>>>,
16    pub diagnostics: Arc<Vec<ReadRef<PlainDiagnostic>>>,
17    pub effects: Arc<Effects>,
18}
19
20#[turbo_tasks::function(operation)]
21pub async fn write_analyze_data_with_issues_operation(
22    project: ResolvedVc<ProjectContainer>,
23    app_dir_only: bool,
24) -> Result<Vc<WriteAnalyzeResult>> {
25    let analyze_data_op = write_analyze_data_with_issues_operation_inner(project, app_dir_only);
26
27    let (_analyze_data, issues, diagnostics, effects) =
28        strongly_consistent_catch_collectables(analyze_data_op).await?;
29
30    Ok(WriteAnalyzeResult {
31        issues,
32        diagnostics,
33        effects,
34    }
35    .cell())
36}
37
38#[turbo_tasks::function(operation)]
39async fn write_analyze_data_with_issues_operation_inner(
40    project: ResolvedVc<ProjectContainer>,
41    app_dir_only: bool,
42) -> Result<()> {
43    let analyze_data_op = get_analyze_data_operation(project, app_dir_only);
44
45    project
46        .project()
47        .emit_all_output_assets(analyze_data_op)
48        .as_side_effect()
49        .await?;
50
51    Ok(())
52}
53
54#[turbo_tasks::function(operation)]
55async fn get_analyze_data_operation(
56    container: ResolvedVc<ProjectContainer>,
57    app_dir_only: bool,
58) -> Result<Vc<OutputAssets>> {
59    let project = container.project();
60    let project = project.with_next_config(project.next_config().with_analyze_config());
61
62    let analyze_output_root = project
63        .node_root()
64        .owned()
65        .await?
66        .join("diagnostics/analyze/data")?;
67    let whole_app_module_graphs = project.whole_app_module_graphs();
68    let analyze_output_root = &analyze_output_root;
69    let analyze_data = project
70        .get_all_endpoint_groups(app_dir_only)
71        .await?
72        .iter()
73        .map(|(key, endpoint_group)| async move {
74            let output_assets = endpoint_group.output_assets();
75            let analyze_data = AnalyzeDataOutputAsset::new(
76                analyze_output_root
77                    .join(&key.to_string())?
78                    .join("analyze.data")?,
79                output_assets,
80            )
81            .to_resolved()
82            .await?;
83
84            Ok(ResolvedVc::upcast(analyze_data))
85        })
86        .try_join()
87        .await?;
88
89    whole_app_module_graphs.as_side_effect().await?;
90
91    let modules_data = ResolvedVc::upcast(
92        ModulesDataOutputAsset::new(
93            analyze_output_root.join("modules.data")?,
94            Vc::cell(vec![whole_app_module_graphs.await?.full]),
95        )
96        .to_resolved()
97        .await?,
98    );
99
100    Ok(Vc::cell(
101        analyze_data
102            .iter()
103            .cloned()
104            .chain(once(modules_data))
105            .collect(),
106    ))
107}