mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 02:48:24 +00:00
fix(check): move module not found errors to typescript diagnostics (#27533)
Instead of hard erroring, we now surface module not found errors as TypeScript diagnostics (we have yet to show the source code of the error, but something we can improve over time).
This commit is contained in:
parent
18b813b93f
commit
89c92b84fa
37 changed files with 684 additions and 358 deletions
|
@ -129,6 +129,7 @@ fn get_asset_texts_from_new_runtime() -> Result<Vec<AssetText>, AnyError> {
|
|||
op_emit,
|
||||
op_is_node_file,
|
||||
op_load,
|
||||
op_remap_specifier,
|
||||
op_resolve,
|
||||
op_respond,
|
||||
]
|
||||
|
@ -275,30 +276,6 @@ fn hash_url(specifier: &ModuleSpecifier, media_type: MediaType) -> String {
|
|||
)
|
||||
}
|
||||
|
||||
/// If the provided URLs derivable tsc media type doesn't match the media type,
|
||||
/// we will add an extension to the output. This is to avoid issues with
|
||||
/// specifiers that don't have extensions, that tsc refuses to emit because they
|
||||
/// think a `.js` version exists, when it doesn't.
|
||||
fn maybe_remap_specifier(
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
) -> Option<String> {
|
||||
let path = if specifier.scheme() == "file" {
|
||||
if let Ok(path) = specifier.to_file_path() {
|
||||
path
|
||||
} else {
|
||||
PathBuf::from(specifier.path())
|
||||
}
|
||||
} else {
|
||||
PathBuf::from(specifier.path())
|
||||
};
|
||||
if path.extension().is_none() {
|
||||
Some(format!("{}{}", specifier, media_type.as_ts_extension()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Eq, PartialEq)]
|
||||
pub struct EmittedFile {
|
||||
pub data: String,
|
||||
|
@ -316,7 +293,7 @@ pub fn into_specifier_and_media_type(
|
|||
(specifier, media_type)
|
||||
}
|
||||
None => (
|
||||
Url::parse("internal:///missing_dependency.d.ts").unwrap(),
|
||||
Url::parse(MISSING_DEPENDENCY_SPECIFIER).unwrap(),
|
||||
MediaType::Dts,
|
||||
),
|
||||
}
|
||||
|
@ -422,6 +399,8 @@ struct State {
|
|||
maybe_tsbuildinfo: Option<String>,
|
||||
maybe_response: Option<RespondArgs>,
|
||||
maybe_npm: Option<RequestNpmState>,
|
||||
// todo(dsherret): it looks like the remapped_specifiers and
|
||||
// root_map could be combined... what is the point of the separation?
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
current_dir: PathBuf,
|
||||
|
@ -463,6 +442,16 @@ impl State {
|
|||
current_dir,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_remapped_specifier(
|
||||
&self,
|
||||
specifier: &str,
|
||||
) -> Option<&ModuleSpecifier> {
|
||||
self
|
||||
.remapped_specifiers
|
||||
.get(specifier)
|
||||
.or_else(|| self.root_map.get(specifier))
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_specifier(
|
||||
|
@ -607,10 +596,7 @@ fn op_load_inner(
|
|||
maybe_source.map(Cow::Borrowed)
|
||||
} else {
|
||||
let specifier = if let Some(remapped_specifier) =
|
||||
state.remapped_specifiers.get(load_specifier)
|
||||
{
|
||||
remapped_specifier
|
||||
} else if let Some(remapped_specifier) = state.root_map.get(load_specifier)
|
||||
state.maybe_remapped_specifier(load_specifier)
|
||||
{
|
||||
remapped_specifier
|
||||
} else {
|
||||
|
@ -713,6 +699,18 @@ pub struct ResolveArgs {
|
|||
pub specifiers: Vec<(bool, String)>,
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[string]
|
||||
fn op_remap_specifier(
|
||||
state: &mut OpState,
|
||||
#[string] specifier: &str,
|
||||
) -> Option<String> {
|
||||
let state = state.borrow::<State>();
|
||||
state
|
||||
.maybe_remapped_specifier(specifier)
|
||||
.map(|url| url.to_string())
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
fn op_resolve(
|
||||
|
@ -732,11 +730,9 @@ fn op_resolve_inner(
|
|||
let mut resolved: Vec<(String, &'static str)> =
|
||||
Vec::with_capacity(args.specifiers.len());
|
||||
let referrer = if let Some(remapped_specifier) =
|
||||
state.remapped_specifiers.get(&args.base)
|
||||
state.maybe_remapped_specifier(&args.base)
|
||||
{
|
||||
remapped_specifier.clone()
|
||||
} else if let Some(remapped_base) = state.root_map.get(&args.base) {
|
||||
remapped_base.clone()
|
||||
} else {
|
||||
normalize_specifier(&args.base, &state.current_dir).context(
|
||||
"Error converting a string module specifier for \"op_resolve\".",
|
||||
|
@ -759,8 +755,12 @@ fn op_resolve_inner(
|
|||
}
|
||||
|
||||
let resolved_dep = referrer_module
|
||||
.and_then(|m| m.js())
|
||||
.and_then(|m| m.dependencies_prefer_fast_check().get(&specifier))
|
||||
.and_then(|m| match m {
|
||||
Module::Js(m) => m.dependencies_prefer_fast_check().get(&specifier),
|
||||
Module::Json(_) => None,
|
||||
Module::Wasm(m) => m.dependencies.get(&specifier),
|
||||
Module::Npm(_) | Module::Node(_) | Module::External(_) => None,
|
||||
})
|
||||
.and_then(|d| d.maybe_type.ok().or_else(|| d.maybe_code.ok()));
|
||||
let resolution_mode = if is_cjs {
|
||||
ResolutionMode::Require
|
||||
|
@ -816,7 +816,7 @@ fn op_resolve_inner(
|
|||
}
|
||||
_ => {
|
||||
if let Some(specifier_str) =
|
||||
maybe_remap_specifier(&specifier, media_type)
|
||||
mapped_specifier_for_tsc(&specifier, media_type)
|
||||
{
|
||||
state
|
||||
.remapped_specifiers
|
||||
|
@ -840,7 +840,7 @@ fn op_resolve_inner(
|
|||
MediaType::Dts.as_ts_extension(),
|
||||
),
|
||||
};
|
||||
log::debug!("Resolved {} to {:?}", specifier, result);
|
||||
log::debug!("Resolved {} from {} to {:?}", specifier, referrer, result);
|
||||
resolved.push(result);
|
||||
}
|
||||
|
||||
|
@ -1072,6 +1072,7 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
|
|||
op_emit,
|
||||
op_is_node_file,
|
||||
op_load,
|
||||
op_remap_specifier,
|
||||
op_resolve,
|
||||
op_respond,
|
||||
],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue