From c888f22cd06005a3422c54826650290ccf714f26 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Fri, 10 Jan 2025 19:56:57 -0500 Subject: [PATCH] fix(check): ignore errors on ambient modules --- cli/graph_util.rs | 50 ++++++++++++++++++++++++++++++++++--- cli/tools/check.rs | 3 +++ cli/tsc/99_main_compiler.js | 3 +++ cli/tsc/mod.rs | 11 +++++--- 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/cli/graph_util.rs b/cli/graph_util.rs index 84beee027e..aca61582e3 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -146,6 +146,51 @@ pub fn graph_walk_errors<'a>( roots: &'a [ModuleSpecifier], options: GraphWalkErrorsOptions, ) -> impl Iterator + 'a { + fn should_ignore_resolution_error_for_types(err: &ResolutionError) -> bool { + match err { + ResolutionError::InvalidSpecifier { .. } => true, + ResolutionError::ResolverError { error, .. } => match error.as_ref() { + ResolveError::Specifier(_) => true, + ResolveError::ImportMap(err) => match err.as_kind() { + import_map::ImportMapErrorKind::UnmappedBareSpecifier(_, _) => true, + import_map::ImportMapErrorKind::JsonParse(_) + | import_map::ImportMapErrorKind::ImportMapNotObject + | import_map::ImportMapErrorKind::ImportsFieldNotObject + | import_map::ImportMapErrorKind::ScopesFieldNotObject + | import_map::ImportMapErrorKind::ScopePrefixNotObject(_) + | import_map::ImportMapErrorKind::BlockedByNullEntry(_) + | import_map::ImportMapErrorKind::SpecifierResolutionFailure { + .. + } + | import_map::ImportMapErrorKind::SpecifierBacktracksAbovePrefix { + .. + } => false, + }, + ResolveError::Other(_) => false, + }, + ResolutionError::InvalidDowngrade { .. } + | ResolutionError::InvalidJsrHttpsTypesImport { .. } + | ResolutionError::InvalidLocalImport { .. } => false, + } + } + + fn should_ignore_module_graph_error_for_types( + err: &ModuleGraphError, + ) -> bool { + match err { + ModuleGraphError::ResolutionError(err) => { + should_ignore_resolution_error_for_types(err) + } + ModuleGraphError::TypesResolutionError(err) => { + should_ignore_resolution_error_for_types(err) + } + ModuleGraphError::ModuleError(module_error) => match module_error { + ModuleError::Missing { .. } => true, + _ => false, + }, + } + } + graph .walk( roots.iter(), @@ -187,10 +232,7 @@ pub fn graph_walk_errors<'a>( if graph.graph_kind().include_types() && (message.contains(RUN_WITH_SLOPPY_IMPORTS_MSG) - || matches!( - error, - ModuleGraphError::ModuleError(ModuleError::Missing(..)) - )) + || should_ignore_module_graph_error_for_types(&error)) { // ignore and let typescript surface this as a diagnostic instead log::debug!("Ignoring: {}", message); diff --git a/cli/tools/check.rs b/cli/tools/check.rs index 53fd5c5db9..9a5eef1985 100644 --- a/cli/tools/check.rs +++ b/cli/tools/check.rs @@ -295,6 +295,9 @@ impl TypeChecker { check_mode: type_check_mode, })?; + eprintln!("Ambient modules: {:?}", response.ambient_modules); + panic!("STOP"); // prevent saving the type checker cache + let response_diagnostics = response.diagnostics.filter(filter_remote_diagnostics); diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js index 25813c3f9d..e1f773c9ed 100644 --- a/cli/tsc/99_main_compiler.js +++ b/cli/tsc/99_main_compiler.js @@ -410,6 +410,7 @@ delete Object.prototype.__proto__; } if (start !== undefined && length !== undefined && file) { let startPos = file.getLineAndCharacterOfPosition(start); + /** @type {string | undefined} */ let sourceLine = file.getFullText().split("\n")[startPos.line]; const originalFileName = file.fileName; const fileName = ops.op_remap_specifier @@ -1104,8 +1105,10 @@ delete Object.prototype.__proto__; performanceProgram({ program }); + const checker = program.getProgram().getTypeChecker(); ops.op_respond({ diagnostics: fromTypeScriptDiagnostics(diagnostics), + ambientModules: checker.getAmbientModules().map((symbol) => symbol.name), stats: performanceEnd(), }); debug("<<< exec stop"); diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index 1473b8a8d9..aec75dadd2 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -384,6 +384,7 @@ pub struct Response { pub diagnostics: Diagnostics, /// If there was any build info associated with the exec request. pub maybe_tsbuildinfo: Option, + pub ambient_modules: Vec, /// Statistics from the check. pub stats: Stats, } @@ -1047,8 +1048,10 @@ fn op_is_node_file(state: &mut OpState, #[string] path: &str) -> bool { } #[derive(Debug, Deserialize, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] struct RespondArgs { pub diagnostics: Diagnostics, + pub ambient_modules: Vec, pub stats: Stats, } @@ -1163,14 +1166,13 @@ pub fn exec(request: Request) -> Result { let state = op_state.take::(); if let Some(response) = state.maybe_response { - let diagnostics = response.diagnostics; let maybe_tsbuildinfo = state.maybe_tsbuildinfo; - let stats = response.stats; Ok(Response { - diagnostics, + diagnostics: response.diagnostics, + ambient_modules: response.ambient_modules, maybe_tsbuildinfo, - stats, + stats: response.stats, }) } else { Err(ExecError::ResponseNotSet) @@ -1500,6 +1502,7 @@ mod tests { reports_unnecessary: None, other: Default::default(), }]), + ambient_modules: vec![], stats: Stats(vec![("a".to_string(), 12)]) }) );