diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-03-11 11:43:45 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-11 11:43:45 -0500 |
commit | 8db853514caae431a0ce91360d854c1b7f3c405f (patch) | |
tree | 4173976ce6c836b715af22c9aeb9f336debb8544 /cli/lsp/tsc.rs | |
parent | e4430400ced48529730a8752c547b613a23c76ce (diff) |
fix(check): regression where config "types" entries caused type checking errors (#18124)
Closes #18117
Closes #18121 (this is just over 10ms faster in a directory one up from
the root folder)
cc @nayeemrmn
Diffstat (limited to 'cli/lsp/tsc.rs')
-rw-r--r-- | cli/lsp/tsc.rs | 103 |
1 files changed, 38 insertions, 65 deletions
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 9a0c0dabe..79c1817e2 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -109,8 +109,7 @@ impl TsServer { while let Some((req, state_snapshot, tx, token)) = rx.recv().await { if !started { // TODO(@kitsonk) need to reflect the debug state of the lsp here - start(&mut ts_runtime, false, &state_snapshot) - .expect("could not start tsc"); + start(&mut ts_runtime, false).unwrap(); started = true; } let value = request(&mut ts_runtime, state_snapshot, req, token); @@ -2660,24 +2659,6 @@ struct SpecifierArgs { } #[op] -fn op_exists(state: &mut OpState, args: SpecifierArgs) -> bool { - let state = state.borrow_mut::<State>(); - // we don't measure the performance of op_exists anymore because as of TS 4.5 - // it is noisy with all the checking for custom libs, that we can't see the - // forrest for the trees as well as it compounds any lsp performance - // challenges, opening a single document in the editor causes some 3k worth - // of op_exists requests... :omg: - let specifier = match state.normalize_specifier(&args.specifier) { - Ok(url) => url, - // sometimes tsc tries to query invalid specifiers, especially when - // something else isn't quite right, so instead of bubbling up the error - // back to tsc, we simply swallow it and say the file doesn't exist - Err(_) => return false, - }; - state.state_snapshot.documents.exists(&specifier) -} - -#[op] fn op_is_cancelled(state: &mut OpState) -> bool { let state = state.borrow_mut::<State>(); state.token.is_cancelled() @@ -2768,15 +2749,45 @@ fn op_script_names(state: &mut OpState) -> Vec<String> { let state = state.borrow_mut::<State>(); let documents = &state.state_snapshot.documents; let open_docs = documents.documents(true, true); - - let mut result = Vec::with_capacity(open_docs.len() + 1); + let mut result = Vec::new(); + let mut seen = HashSet::new(); if documents.has_injected_types_node_package() { // ensure this is first so it resolves the node types first - result.push("asset:///node_types.d.ts".to_string()); + let specifier = "asset:///node_types.d.ts"; + result.push(specifier.to_string()); + seen.insert(specifier); + } + + // inject these next because they're global + for import in documents.module_graph_imports() { + if seen.insert(import.as_str()) { + result.push(import.to_string()); + } + } + + // finally include the documents and all their dependencies + for doc in &open_docs { + let specifier = doc.specifier(); + if seen.insert(specifier.as_str()) { + result.push(specifier.to_string()); + } + } + + // and then all their dependencies (do this after to avoid exists calls) + for doc in &open_docs { + for dep in doc.dependencies().values() { + if let Some(specifier) = dep.get_type().or_else(|| dep.get_code()) { + if seen.insert(specifier.as_str()) { + // only include dependencies we know to exist otherwise typescript will error + if documents.exists(specifier) { + result.push(specifier.to_string()); + } + } + } + } } - result.extend(open_docs.into_iter().map(|d| d.specifier().to_string())); result } @@ -2812,7 +2823,6 @@ fn js_runtime(performance: Arc<Performance>) -> JsRuntime { fn init_extension(performance: Arc<Performance>) -> Extension { Extension::builder("deno_tsc") .ops(vec![ - op_exists::decl(), op_is_cancelled::decl(), op_is_node_file::decl(), op_load::decl(), @@ -2832,16 +2842,8 @@ fn init_extension(performance: Arc<Performance>) -> Extension { /// Instruct a language server runtime to start the language server and provide /// it with a minimal bootstrap configuration. -fn start( - runtime: &mut JsRuntime, - debug: bool, - state_snapshot: &StateSnapshot, -) -> Result<(), AnyError> { - let root_uri = state_snapshot - .root_uri - .clone() - .unwrap_or_else(|| Url::parse("cache:///").unwrap()); - let init_config = json!({ "debug": debug, "rootUri": root_uri }); +fn start(runtime: &mut JsRuntime, debug: bool) -> Result<(), AnyError> { + let init_config = json!({ "debug": debug }); let init_src = format!("globalThis.serverInit({init_config});"); runtime.execute_script(&located_script_name!(), &init_src)?; @@ -3495,8 +3497,7 @@ mod tests { let location = temp_dir.path().join("deps"); let state_snapshot = Arc::new(mock_state_snapshot(sources, &location)); let mut runtime = js_runtime(Default::default()); - start(&mut runtime, debug, &state_snapshot) - .expect("could not start server"); + start(&mut runtime, debug).unwrap(); let ts_config = TsConfig::new(config); assert_eq!( request( @@ -4039,34 +4040,6 @@ mod tests { } #[test] - fn test_op_exists() { - let temp_dir = TempDir::new(); - let (mut rt, state_snapshot, _) = setup( - &temp_dir, - false, - json!({ - "target": "esnext", - "module": "esnext", - "lib": ["deno.ns", "deno.window"], - "noEmit": true, - }), - &[], - ); - let performance = Arc::new(Performance::default()); - let state = State::new(state_snapshot, performance); - let op_state = rt.op_state(); - let mut op_state = op_state.borrow_mut(); - op_state.put(state); - let actual = op_exists::call( - &mut op_state, - SpecifierArgs { - specifier: "/error/unknown:something/index.d.ts".to_string(), - }, - ); - assert!(!actual); - } - - #[test] fn test_completion_entry_filter_text() { let fixture = CompletionEntry { kind: ScriptElementKind::MemberVariableElement, |