summaryrefslogtreecommitdiff
path: root/cli/lsp/tsc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp/tsc.rs')
-rw-r--r--cli/lsp/tsc.rs70
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()
+ ))]
+ );
+ }
}