turbopack_core/issue/
resolve.rs1use std::fmt::Write;
2
3use anyhow::Result;
4use turbo_rcstr::RcStr;
5use turbo_tasks::{ReadRef, ResolvedVc, ValueToString, Vc};
6use turbo_tasks_fs::FileSystemPath;
7
8use super::{Issue, IssueSource, IssueStage, OptionIssueSource, OptionStyledString, StyledString};
9use crate::{
10 error::PrettyPrintError,
11 issue::IssueSeverity,
12 resolve::{
13 options::{ImportMap, ImportMapResult, ResolveOptions},
14 parse::Request,
15 },
16};
17
18#[turbo_tasks::value(shared)]
19pub struct ResolvingIssue {
20 pub severity: ResolvedVc<IssueSeverity>,
21 pub request_type: String,
22 pub request: ResolvedVc<Request>,
23 pub file_path: ResolvedVc<FileSystemPath>,
24 pub resolve_options: ResolvedVc<ResolveOptions>,
25 pub error_message: Option<String>,
26 pub source: Option<IssueSource>,
27}
28
29#[turbo_tasks::value_impl]
30impl Issue for ResolvingIssue {
31 #[turbo_tasks::function]
32 fn severity(&self) -> Vc<IssueSeverity> {
33 *self.severity
34 }
35
36 #[turbo_tasks::function]
37 async fn title(&self) -> Result<Vc<StyledString>> {
38 let request = self.request.request_pattern().to_string().owned().await?;
39 Ok(StyledString::Line(vec![
40 StyledString::Strong("Module not found".into()),
41 StyledString::Text(": Can't resolve ".into()),
42 StyledString::Code(request),
43 ])
44 .cell())
45 }
46
47 #[turbo_tasks::function]
48 fn stage(&self) -> Vc<IssueStage> {
49 IssueStage::Resolve.cell()
50 }
51
52 #[turbo_tasks::function]
53 fn file_path(&self) -> Vc<FileSystemPath> {
54 *self.file_path
55 }
56
57 #[turbo_tasks::function]
58 async fn description(&self) -> Result<Vc<OptionStyledString>> {
59 let mut description = String::new();
60 if let Some(error_message) = &self.error_message {
61 writeln!(description, "{error_message}")?;
62 }
63 let request_value = self.request.await?;
64 let request_parts = match &*request_value {
65 Request::Alternatives { requests } => requests.as_slice(),
66 _ => &[self.request],
67 };
68
69 if let Some(import_map) = &self.resolve_options.await?.import_map {
70 for request in request_parts {
71 match lookup_import_map(**import_map, *self.file_path, **request).await {
72 Ok(None) => {}
73 Ok(Some(str)) => writeln!(description, "Import map: {str}")?,
74 Err(err) => {
75 writeln!(
76 description,
77 "Error while looking up import map: {}",
78 PrettyPrintError(&err)
79 )?;
80 }
81 }
82 }
83 }
84 Ok(Vc::cell(Some(
85 StyledString::Text(description.into()).resolved_cell(),
86 )))
87 }
88
89 #[turbo_tasks::function]
90 async fn detail(&self) -> Result<Vc<OptionStyledString>> {
91 let mut detail = String::new();
92
93 if self.error_message.is_some() {
94 writeln!(detail, "An error happened during resolving.")?;
95 } else {
96 writeln!(detail, "It was not possible to find the requested file.")?;
97 }
98 writeln!(
99 detail,
100 "Parsed request as written in source code: {request}",
101 request = self.request.to_string().await?
102 )?;
103 writeln!(
104 detail,
105 "Path where resolving has started: {context}",
106 context = self.file_path.to_string().await?
107 )?;
108 writeln!(
109 detail,
110 "Type of request: {request_type}",
111 request_type = self.request_type,
112 )?;
113 Ok(Vc::cell(Some(
114 StyledString::Text(detail.into()).resolved_cell(),
115 )))
116 }
117
118 #[turbo_tasks::function]
119 async fn source(&self) -> Result<Vc<OptionIssueSource>> {
120 Ok(Vc::cell(match &self.source {
121 Some(source) => Some(source.resolve_source_map().await?.into_owned()),
122 None => None,
123 }))
124 }
125
126 }
129
130async fn lookup_import_map(
131 import_map: Vc<ImportMap>,
132 file_path: Vc<FileSystemPath>,
133 request: Vc<Request>,
134) -> Result<Option<ReadRef<RcStr>>> {
135 let result = import_map.await?.lookup(file_path, request).await?;
136
137 if matches!(result, ImportMapResult::NoEntry) {
138 return Ok(None);
139 }
140 Ok(Some(result.cell().to_string().await?))
141}