diff options
Diffstat (limited to 'cli/lsp/tsc.rs')
-rw-r--r-- | cli/lsp/tsc.rs | 70 |
1 files changed, 57 insertions, 13 deletions
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index d62744e03..48ca7355a 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -28,6 +28,7 @@ use crate::lsp::documents::Documents; use crate::lsp::logging::lsp_warn; use crate::tsc; use crate::tsc::ResolveArgs; +use crate::tsc::MISSING_DEPENDENCY_SPECIFIER; use crate::util::path::relative_specifier; use crate::util::path::specifier_to_file_path; use crate::util::path::to_percent_decoded_str; @@ -4008,7 +4009,7 @@ fn op_load<'s>( .mark_with_args("tsc.op.op_load", specifier); let specifier = state.specifier_map.normalize(specifier)?; let maybe_load_response = - if specifier.as_str() == "internal:///missing_dependency.d.ts" { + if specifier.as_str() == MISSING_DEPENDENCY_SPECIFIER { None } else { let asset_or_document = state.get_asset_or_document(&specifier); @@ -4026,11 +4027,11 @@ fn op_load<'s>( } #[op2] -fn op_resolve<'s>( - scope: &'s mut v8::HandleScope, +#[serde] +fn op_resolve( state: &mut OpState, #[serde] args: ResolveArgs, -) -> Result<v8::Local<'s, v8::Value>, AnyError> { +) -> Result<Vec<Option<(String, String)>>, AnyError> { let state = state.borrow_mut::<State>(); let mark = state.performance.mark_with_args("tsc.op.op_resolve", &args); let referrer = state.specifier_map.normalize(&args.base)?; @@ -4043,13 +4044,17 @@ fn op_resolve<'s>( ); resolved .into_iter() - .map(|o| { - o.map(|(s, mt)| { - ( - state.specifier_map.denormalize(&s), - mt.as_ts_extension().to_string(), - ) - }) + // Resolved `node:` specifier means the user doesn't have @types/node, + // resolve to stub. + .map(|o| match o.filter(|(s, _)| s.scheme() != "node") { + Some((s, mt)) => Some(( + state.specifier_map.denormalize(&s), + mt.as_ts_extension().to_string(), + )), + None => Some(( + MISSING_DEPENDENCY_SPECIFIER.to_string(), + MediaType::Dts.as_ts_extension().to_string(), + )), }) .collect() } @@ -4062,9 +4067,8 @@ fn op_resolve<'s>( } }; - let response = serde_v8::to_v8(scope, specifiers)?; state.performance.measure(mark); - Ok(response) + Ok(specifiers) } #[op2] @@ -4750,6 +4754,14 @@ mod tests { (ts_server, snapshot, cache) } + fn setup_op_state(state_snapshot: Arc<StateSnapshot>) -> OpState { + let state = + State::new(state_snapshot, Default::default(), Default::default()); + let mut op_state = OpState::new(None); + op_state.put(state); + op_state + } + #[test] fn test_replace_links() { let actual = replace_links(r"test {@link http://deno.land/x/mod.ts} test"); @@ -5552,4 +5564,36 @@ mod tests { Some(false) ); } + + #[tokio::test] + async fn resolve_unknown_dependency_to_stub_module() { + let temp_dir = TempDir::new(); + let (_, snapshot, _) = setup( + &temp_dir, + json!({ + "target": "esnext", + "module": "esnext", + "lib": ["deno.ns", "deno.window"], + "noEmit": true, + }), + &[("file:///a.ts", "", 1, LanguageId::TypeScript)], + ) + .await; + let mut state = setup_op_state(snapshot); + let resolved = op_resolve::call( + &mut state, + ResolveArgs { + base: "file:///a.ts".to_string(), + specifiers: vec!["./b.ts".to_string()], + }, + ) + .unwrap(); + assert_eq!( + resolved, + vec![Some(( + MISSING_DEPENDENCY_SPECIFIER.to_string(), + MediaType::Dts.as_ts_extension().to_string() + ))] + ); + } } |