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.rs103
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,