From bcabe0cc9bbbc27e4bdf8664f675798c80aaaeef Mon Sep 17 00:00:00 2001 From: David Sherret Date: Sat, 4 Mar 2023 18:23:19 -0500 Subject: [PATCH 1/9] refactor(lsp): improve test client initialization --- Cargo.lock | 1 + Cargo.toml | 2 + cli/Cargo.toml | 4 +- cli/bench/lsp.rs | 9 +- cli/bench/lsp_bench_standalone.rs | 4 +- cli/tests/integration/lsp_tests.rs | 922 +++++++++--------- cli/tests/testdata/lsp/a.d.ts | 2 - cli/tests/testdata/lsp/b.d.ts | 2 - .../lsp/deno.embedded_import_map.jsonc | 5 - cli/tests/testdata/lsp/deno.fmt.exclude.jsonc | 16 - cli/tests/testdata/lsp/deno.fmt.jsonc | 11 - cli/tests/testdata/lsp/deno.lint.jsonc | 13 - .../testdata/lsp/import-map-completions.json | 7 - .../initialize_params_bad_config_option.json | 65 -- cli/tests/testdata/lsp/lib.tsconfig.json | 5 - test_util/Cargo.toml | 1 + test_util/src/builders.rs | 24 +- test_util/src/lsp.rs | 293 +++++- test_util/src/temp_dir.rs | 5 + 19 files changed, 770 insertions(+), 621 deletions(-) delete mode 100644 cli/tests/testdata/lsp/a.d.ts delete mode 100644 cli/tests/testdata/lsp/b.d.ts delete mode 100644 cli/tests/testdata/lsp/deno.embedded_import_map.jsonc delete mode 100644 cli/tests/testdata/lsp/deno.fmt.exclude.jsonc delete mode 100644 cli/tests/testdata/lsp/deno.fmt.jsonc delete mode 100644 cli/tests/testdata/lsp/deno.lint.jsonc delete mode 100644 cli/tests/testdata/lsp/import-map-completions.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_bad_config_option.json delete mode 100644 cli/tests/testdata/lsp/lib.tsconfig.json diff --git a/Cargo.lock b/Cargo.lock index 180f4afb884528..c80eca765c2625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4925,6 +4925,7 @@ dependencies = [ "futures", "hyper", "lazy_static", + "lsp-types", "once_cell", "os_pipe", "parking_lot 0.12.1", diff --git a/Cargo.toml b/Cargo.toml index b4131c636449d6..66d6d5adc50382 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,7 @@ hyper = "0.14.18" indexmap = { version = "1.9.2", features = ["serde"] } libc = "0.2.126" log = "=0.4.17" +lsp-types = "=0.93.2" # used by tower-lsp and "proposed" feature is unstable in patch releases lzzzz = "1.0" notify = "=5.0.0" once_cell = "=1.16.0" @@ -117,6 +118,7 @@ tokio = { version = "=1.25.0", features = ["full"] } tokio-rustls = "0.23.3" tokio-tungstenite = "0.16.1" tokio-util = "0.7.4" +tower-lsp = { version = "=0.17.0", features = ["proposed"] } url = { version = "2.3.1", features = ["serde", "expose_internals"] } uuid = { version = "1.3.0", features = ["v4"] } zstd = "=0.11.2" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 0ad4896f32f9d9..45c2f44e566826 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -79,7 +79,7 @@ indexmap.workspace = true jsonc-parser = { version = "=0.21.0", features = ["serde"] } libc.workspace = true log = { workspace = true, features = ["serde"] } -lsp-types = "=0.93.2" # used by tower-lsp and "proposed" feature is unstable in patch releases +lsp-types.workspace = true lzzzz = '1.0' mitata = "=0.0.7" monch = "=0.4.1" @@ -103,7 +103,7 @@ text_lines = "=0.6.0" thiserror = "=1.0.38" tokio.workspace = true tokio-util.workspace = true -tower-lsp = { version = "=0.17.0", features = ["proposed"] } +tower-lsp.workspace = true twox-hash = "=1.6.3" typed-arena = "=2.0.1" uuid = { workspace = true, features = ["serde"] } diff --git a/cli/bench/lsp.rs b/cli/bench/lsp.rs index 722a87b69bf9aa..12d37941199b6f 100644 --- a/cli/bench/lsp.rs +++ b/cli/bench/lsp.rs @@ -10,6 +10,7 @@ use std::collections::HashMap; use std::path::Path; use std::time::Duration; use test_util::lsp::LspClient; +use test_util::lsp::LspClientBuilder; use test_util::lsp::LspResponseError; use tower_lsp::lsp_types as lsp; @@ -44,7 +45,7 @@ struct FixtureMessage { /// the end of the document and does a level of hovering and gets quick fix /// code actions. fn bench_big_file_edits(deno_exe: &Path) -> Result { - let mut client = LspClient::new(deno_exe, false)?; + let mut client = LspClientBuilder::new().deno_exe(deno_exe).build(); let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON)?; let (_, response_error): (Option, Option) = @@ -125,7 +126,7 @@ fn bench_big_file_edits(deno_exe: &Path) -> Result { } fn bench_code_lens(deno_exe: &Path) -> Result { - let mut client = LspClient::new(deno_exe, false)?; + let mut client = LspClientBuilder::new().deno_exe(deno_exe).build(); let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON)?; let (_, maybe_err) = @@ -189,7 +190,7 @@ fn bench_code_lens(deno_exe: &Path) -> Result { } fn bench_find_replace(deno_exe: &Path) -> Result { - let mut client = LspClient::new(deno_exe, false)?; + let mut client = LspClientBuilder::new().deno_exe(deno_exe).build(); let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON)?; let (_, maybe_err) = @@ -285,7 +286,7 @@ fn bench_find_replace(deno_exe: &Path) -> Result { /// A test that starts up the LSP, opens a single line document, and exits. fn bench_startup_shutdown(deno_exe: &Path) -> Result { - let mut client = LspClient::new(deno_exe, false)?; + let mut client = LspClientBuilder::new().deno_exe(deno_exe).build(); let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON)?; let (_, response_error) = diff --git a/cli/bench/lsp_bench_standalone.rs b/cli/bench/lsp_bench_standalone.rs index e8dc2907309701..a6effa185581d8 100644 --- a/cli/bench/lsp_bench_standalone.rs +++ b/cli/bench/lsp_bench_standalone.rs @@ -7,12 +7,12 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use test_util::lsp::LspClient; +use test_util::lsp::LspClientBuilder; // Intended to match the benchmark in quick-lint-js // https://github.com/quick-lint/quick-lint-js/blob/35207e6616267c6c81be63f47ce97ec2452d60df/benchmark/benchmark-lsp/lsp-benchmarks.cpp#L223-L268 fn incremental_change_wait(bench: &mut Bencher) { - let deno_exe = test_util::deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); + let mut client = LspClientBuilder::new().build(); static FIXTURE_INIT_JSON: &[u8] = include_bytes!("testdata/initialize_params.json"); diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index bca327e96e71d2..e9652423bb67f3 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -13,12 +13,12 @@ use std::collections::HashSet; use std::fs; use std::process::Stdio; use test_util::deno_cmd_with_deno_dir; -use test_util::deno_exe_path; use test_util::env_vars_for_npm_tests; use test_util::http_server; use test_util::lsp::LspClient; +use test_util::lsp::LspClientBuilder; use test_util::testdata_path; -use test_util::TempDir; +use test_util::TestContextBuilder; use tower_lsp::lsp_types as lsp; fn load_fixture(path: &str) -> Value { @@ -40,8 +40,8 @@ fn load_fixture_str(path: &str) -> String { } fn init(init_path: &str) -> LspClient { - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); + let test_context = TestContextBuilder::new().build(); + let mut client = test_context.new_lsp_command().build(); client .write_request::<_, _, Value>("initialize", load_fixture(init_path)) .unwrap(); @@ -91,13 +91,6 @@ fn read_diagnostics(client: &mut LspClient) -> CollectedDiagnostics { CollectedDiagnostics(diagnostics) } -fn shutdown(client: &mut LspClient) { - client - .write_request::<_, _, Value>("shutdown", json!(null)) - .unwrap(); - client.write_notification("exit", json!(null)).unwrap(); -} - pub fn ensure_directory_specifier( mut specifier: ModuleSpecifier, ) -> ModuleSpecifier { @@ -109,6 +102,7 @@ pub fn ensure_directory_specifier( specifier } +// todo(THIS PR): get rid of this in favour of LspClient struct TestSession { client: LspClient, open_file_count: usize, @@ -163,7 +157,7 @@ impl TestSession { } pub fn shutdown_and_exit(&mut self) { - shutdown(&mut self.client); + self.client.shutdown(); } } @@ -230,32 +224,29 @@ impl CollectedDiagnostics { #[test] fn lsp_startup_shutdown() { - let mut client = init("initialize_params.json"); - shutdown(&mut client); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); + client.shutdown(); } #[test] fn lsp_init_tsconfig() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let tsconfig = - serde_json::to_vec_pretty(&load_fixture("lib.tsconfig.json")).unwrap(); - fs::write(temp_dir.path().join("lib.tsconfig.json"), tsconfig).unwrap(); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("config".to_string(), json!("./lib.tsconfig.json")); - params.initialization_options = Some(Value::Object(map)); + temp_dir.write( + "lib.tsconfig.json", + r#"{ + "compilerOptions": { + "lib": ["deno.ns", "deno.unstable", "dom"] } +}"#, + ); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); - - client.write_notification("initialized", json!({})).unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("lib.tsconfig.json"); + }); let diagnostics = did_open( &mut client, @@ -272,33 +263,36 @@ fn lsp_init_tsconfig() { let diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics); assert_eq!(diagnostics.count(), 0); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_tsconfig_types() { - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let temp_dir = TempDir::new(); - let tsconfig = - serde_json::to_vec_pretty(&load_fixture("types.tsconfig.json")).unwrap(); - fs::write(temp_dir.path().join("types.tsconfig.json"), tsconfig).unwrap(); - let a_dts = load_fixture_str("a.d.ts"); - fs::write(temp_dir.path().join("a.d.ts"), a_dts).unwrap(); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("config".to_string(), json!("./types.tsconfig.json")); - params.initialization_options = Some(Value::Object(map)); + temp_dir.write( + "types.tsconfig.json", + r#"{ + "compilerOptions": { + "types": [ + "./a.d.ts" + ] + }, + "lint": { + "rules": { + "tags": [] + } } +}"#, + ); + let a_dts = "// deno-lint-ignore-file no-var\ndeclare var a: string;"; + temp_dir.write("a.d.ts", a_dts); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); - - client.write_notification("initialized", json!({})).unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("types.tsconfig.json"); + }); let diagnostics = did_open( &mut client, @@ -315,12 +309,17 @@ fn lsp_tsconfig_types() { let diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics); assert_eq!(diagnostics.count(), 0); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_tsconfig_bad_config_path() { - let mut client = init("initialize_params_bad_config_option.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize(|builder| { + builder + .set_config("bad_tsconfig.json") + .set_maybe_root_uri(None); + }); let (method, maybe_params) = client.read_notification().unwrap(); assert_eq!(method, "window/showMessage"); assert_eq!(maybe_params, Some(lsp::ShowMessageParams { @@ -344,27 +343,18 @@ fn lsp_tsconfig_bad_config_path() { #[test] fn lsp_triple_slash_types() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let a_dts = load_fixture_str("a.d.ts"); - fs::write(temp_dir.path().join("a.d.ts"), a_dts).unwrap(); - - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); - - client.write_notification("initialized", json!({})).unwrap(); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); + let a_dts = "// deno-lint-ignore-file no-var\ndeclare var a: string;"; + temp_dir.write("a.d.ts", a_dts); + let mut client = context.new_lsp_command().build(); + client.initialize_default(); let diagnostics = did_open( &mut client, json!({ "textDocument": { - "uri": Url::from_file_path(temp_dir.path().join("test.ts")).unwrap(), + "uri": temp_dir.uri().join("test.ts").unwrap(), "languageId": "typescript", "version": 1, "text": "/// \n\nconsole.log(a);\n" @@ -375,37 +365,27 @@ fn lsp_triple_slash_types() { let diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics); assert_eq!(diagnostics.count(), 0); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_import_map() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let import_map = - serde_json::to_vec_pretty(&load_fixture("import-map.json")).unwrap(); - fs::write(temp_dir.path().join("import-map.json"), import_map).unwrap(); - fs::create_dir(temp_dir.path().join("lib")).unwrap(); - fs::write( - temp_dir.path().join("lib").join("b.ts"), - r#"export const b = "b";"#, - ) - .unwrap(); - - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("importMap".to_string(), json!("import-map.json")); - params.initialization_options = Some(Value::Object(map)); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); + let import_map = r#"{ + "imports": { + "/~/": "./lib/" } +}"#; + temp_dir.write("import-map.json", import_map); + temp_dir.create_dir_all("lib"); + temp_dir.write("lib/b.ts", r#"export const b = "b";"#); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_import_map("import-map.json"); + }); - client.write_notification("initialized", json!({})).unwrap(); let uri = Url::from_file_path(temp_dir.path().join("a.ts")).unwrap(); let diagnostics = did_open( @@ -460,12 +440,16 @@ fn lsp_import_map() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_import_map_data_url() { - let mut client = init("initialize_params_import_map.json"); + let context = TestContextBuilder::new().build(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_import_map("data:application/json;utf8,{\"imports\": { \"example\": \"https://deno.land/x/example/mod.ts\" }}"); + }); let diagnostics = did_open( &mut client, json!({ @@ -479,49 +463,42 @@ fn lsp_import_map_data_url() { ); let mut diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics); - // This indicates that the import map from initialize_params_import_map.json - // is applied correctly. + // This indicates that the import map is applied correctly. assert!(diagnostics.any(|diagnostic| diagnostic.code == Some(lsp::NumberOrString::String("no-cache".to_string())) && diagnostic .message .contains("https://deno.land/x/example/mod.ts"))); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_import_map_config_file() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - - let deno_import_map_jsonc = - serde_json::to_vec_pretty(&load_fixture("deno.import_map.jsonc")).unwrap(); - fs::write( - temp_dir.path().join("deno.import_map.jsonc"), - deno_import_map_jsonc, - ) - .unwrap(); - - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("config".to_string(), json!("./deno.import_map.jsonc")); - params.initialization_options = Some(Value::Object(map)); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); + temp_dir.write( + "deno.import_map.jsonc", + r#"{ + "importMap": "import-map.json" +}"#, + ); + temp_dir.write( + "import-map.json", + r#"{ + "imports": { + "/~/": "./lib/" } - let import_map_text = - serde_json::to_string_pretty(&load_fixture("import-map.json")).unwrap(); - temp_dir.write("import-map.json", import_map_text); +}"#, + ); temp_dir.create_dir_all("lib"); temp_dir.write("lib/b.ts", r#"export const b = "b";"#); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("./deno.import_map.jsonc"); + }); - client.write_notification("initialized", json!({})).unwrap(); - let uri = Url::from_file_path(temp_dir.path().join("a.ts")).unwrap(); + let uri = temp_dir.uri().join("a.ts").unwrap(); let diagnostics = did_open( &mut client, @@ -575,40 +552,30 @@ fn lsp_import_map_config_file() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_import_map_embedded_in_config_file() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - - let deno_import_map_jsonc = serde_json::to_string_pretty(&load_fixture( + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); + temp_dir.write( "deno.embedded_import_map.jsonc", - )) - .unwrap(); - temp_dir.write("deno.embedded_import_map.jsonc", deno_import_map_jsonc); - - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert( - "config".to_string(), - json!("./deno.embedded_import_map.jsonc"), - ); - params.initialization_options = Some(Value::Object(map)); + r#"{ + "imports": { + "/~/": "./lib/" } - fs::create_dir(temp_dir.path().join("lib")).unwrap(); +}"#, + ); + temp_dir.create_dir_all("lib"); temp_dir.write("lib/b.ts", r#"export const b = "b";"#); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("./deno.embedded_import_map.jsonc"); + }); - client.write_notification("initialized", json!({})).unwrap(); - let uri = Url::from_file_path(temp_dir.path().join("a.ts")).unwrap(); + let uri = temp_dir.uri().join("a.ts").unwrap(); let diagnostics = did_open( &mut client, @@ -662,33 +629,27 @@ fn lsp_import_map_embedded_in_config_file() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_deno_task() { - let temp_dir = TempDir::new(); - let workspace_root = temp_dir.path().canonicalize().unwrap(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - fs::write( - workspace_root.join("deno.jsonc"), + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); + temp_dir.write( + "deno.jsonc", r#"{ "tasks": { "build": "deno test", "some:test": "deno bundle mod.ts" } }"#, - ) - .unwrap(); - - params.root_uri = Some(Url::from_file_path(workspace_root).unwrap()); + ); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("./deno.jsonc"); + }); let (maybe_res, maybe_err) = client .write_request::<_, _, Value>("deno/task", json!(null)) @@ -712,7 +673,12 @@ fn lsp_deno_task() { #[test] fn lsp_import_assertions() { - let mut client = init("initialize_params_import_map.json"); + let context = TestContextBuilder::new().build(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_import_map("data:application/json;utf8,{\"imports\": { \"example\": \"https://deno.land/x/example/mod.ts\" }}"); + }); + client .write_notification( "textDocument/didOpen", @@ -785,39 +751,32 @@ fn lsp_import_assertions() { maybe_res, Some(load_fixture("code_action_response_import_assertion.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_import_map_import_completions() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let import_map = - serde_json::to_vec_pretty(&load_fixture("import-map-completions.json")) - .unwrap(); - fs::write(temp_dir.path().join("import-map.json"), import_map).unwrap(); - fs::create_dir(temp_dir.path().join("lib")).unwrap(); - fs::write( - temp_dir.path().join("lib").join("b.ts"), - r#"export const b = "b";"#, - ) - .unwrap(); - - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("importMap".to_string(), json!("import-map.json")); - params.initialization_options = Some(Value::Object(map)); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); + temp_dir.write( + "import-map.json", + r#"{ + "imports": { + "/~/": "./lib/", + "fs": "https://example.com/fs/index.js", + "std/": "https://example.com/std@0.123.0/" } +}"#, + ); + temp_dir.create_dir_all("lib"); + temp_dir.write("lib/b.ts", r#"export const b = "b";"#); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_import_map("import-map.json"); + }); - client.write_notification("initialized", json!({})).unwrap(); - let uri = Url::from_file_path(temp_dir.path().join("a.ts")).unwrap(); + let uri = temp_dir.uri().join("a.ts").unwrap(); did_open( &mut client, @@ -981,12 +940,13 @@ fn lsp_import_map_import_completions() { })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_hover() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -1036,12 +996,13 @@ fn lsp_hover() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_hover_asset() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -1116,7 +1077,7 @@ fn lsp_hover_asset() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -1154,7 +1115,7 @@ fn lsp_hover_disabled() { .unwrap(); assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(json!(null))); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -1309,7 +1270,8 @@ fn lsp_inlay_hints() { #[test] fn lsp_inlay_hints_not_enabled() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -1366,31 +1328,25 @@ fn lsp_inlay_hints_not_enabled() { #[test] fn lsp_workspace_enable_paths() { - let mut params: lsp::InitializeParams = serde_json::from_value(load_fixture( - "initialize_params_workspace_enable_paths.json", - )) - .unwrap(); + let context = TestContextBuilder::new().build(); // we aren't actually writing anything to the tempdir in this test, but we // just need a legitimate file path on the host system so that logic that // tries to convert to and from the fs paths works on all env - let temp_dir = TempDir::new(); - - let root_specifier = - ensure_directory_specifier(Url::from_file_path(temp_dir.path()).unwrap()); - - params.root_uri = Some(root_specifier.clone()); - params.workspace_folders = Some(vec![lsp::WorkspaceFolder { - uri: root_specifier.clone(), - name: "project".to_string(), - }]); - - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); - - client.write_notification("initialized", json!({})).unwrap(); + let temp_dir = context.deno_dir(); + + let root_specifier = temp_dir.uri(); + + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder + .set_enable_paths(vec!["./worker".to_string()]) + .set_root_uri(root_specifier.clone()) + .set_workspace_folders(vec![lsp::WorkspaceFolder { + uri: root_specifier.clone(), + name: "project".to_string(), + }]) + .set_deno_enable(false); + }); handle_configuration_request( &mut client, @@ -1560,12 +1516,13 @@ fn lsp_workspace_enable_paths() { })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_hover_unstable_disabled() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -1613,7 +1570,7 @@ fn lsp_hover_unstable_disabled() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -1668,12 +1625,13 @@ fn lsp_hover_unstable_enabled() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_hover_change_mbc() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -1756,24 +1714,22 @@ fn lsp_hover_change_mbc() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_hover_closed_document() { - let temp_dir_guard = TempDir::new(); - let temp_dir = temp_dir_guard.path(); - let a_path = temp_dir.join("a.ts"); - fs::write(a_path, r#"export const a = "a";"#).unwrap(); - let b_path = temp_dir.join("b.ts"); - fs::write(&b_path, r#"export * from "./a.ts";"#).unwrap(); - let b_specifier = Url::from_file_path(b_path).unwrap(); - let c_path = temp_dir.join("c.ts"); - fs::write(&c_path, "import { a } from \"./b.ts\";\nconsole.log(a);\n") - .unwrap(); - let c_specifier = Url::from_file_path(c_path).unwrap(); - - let mut client = init("initialize_params.json"); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); + temp_dir.write("a.ts", r#"export const a = "a";"#); + temp_dir.write("b.ts", r#"export * from "./a.ts";"#); + temp_dir.write("c.ts", "import { a } from \"./b.ts\";\nconsole.log(a);\n"); + + let b_specifier = temp_dir.uri().join("b.ts").unwrap(); + let c_specifier = temp_dir.uri().join("c.ts").unwrap(); + + let mut client = context.new_lsp_command().build(); + client.initialize_default(); client .write_notification( "textDocument/didOpen", @@ -1902,13 +1858,14 @@ fn lsp_hover_closed_document() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_hover_dependency() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2113,7 +2070,8 @@ fn lsp_hover_dependency() { // unable to resolve dependencies when there was an invalid syntax in the module #[test] fn lsp_hover_deps_preserved_when_invalid_parse() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2236,13 +2194,14 @@ fn lsp_hover_deps_preserved_when_invalid_parse() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_hover_typescript_types() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2306,12 +2265,13 @@ fn lsp_hover_typescript_types() { } }) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_hover_jsdoc_symbol_link() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2371,12 +2331,13 @@ fn lsp_hover_jsdoc_symbol_link() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_goto_type_definition() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2431,12 +2392,13 @@ fn lsp_goto_type_definition() { } ])) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_call_hierarchy() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2489,12 +2451,13 @@ fn lsp_call_hierarchy() { maybe_res, Some(load_fixture("outgoing_calls_response.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_large_doc_changes() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open(&mut client, load_fixture("did_open_params_large.json")); client .write_notification( @@ -2622,14 +2585,15 @@ fn lsp_large_doc_changes() { .unwrap(); assert!(maybe_res.is_some()); assert!(maybe_err.is_none()); - shutdown(&mut client); + client.shutdown(); assert!(client.duration().as_millis() <= 15000); } #[test] fn lsp_document_symbol() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open(&mut client, load_fixture("did_open_params_doc_symbol.json")); let (maybe_res, maybe_err) = client .write_request( @@ -2646,12 +2610,13 @@ fn lsp_document_symbol() { maybe_res, Some(load_fixture("document_symbol_response.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_folding_range() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2701,12 +2666,13 @@ fn lsp_folding_range() { } ])) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_rename() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2736,12 +2702,13 @@ fn lsp_rename() { .unwrap(); assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(load_fixture("rename_response.json"))); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_selection_range() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2774,12 +2741,13 @@ fn lsp_selection_range() { maybe_res, Some(load_fixture("selection_range_response.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_semantic_tokens() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, load_fixture("did_open_params_semantic_tokens.json"), @@ -2838,12 +2806,13 @@ fn lsp_semantic_tokens() { ] })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_code_lens() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2893,12 +2862,13 @@ fn lsp_code_lens() { maybe_res, Some(load_fixture("code_lens_resolve_response.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_code_lens_impl() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -2992,7 +2962,7 @@ fn lsp_code_lens_impl() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -3017,7 +2987,7 @@ fn lsp_code_lens_test() { maybe_res, Some(load_fixture("code_lens_response_test.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -3062,12 +3032,13 @@ fn lsp_code_lens_test_disabled() { .unwrap(); assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(json!([]))); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_code_lens_non_doc_nav_tree() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -3147,12 +3118,13 @@ fn lsp_code_lens_non_doc_nav_tree() { .unwrap(); assert!(maybe_err.is_none()); assert!(maybe_res.is_some()); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_nav_tree_updates() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -3220,12 +3192,13 @@ fn lsp_nav_tree_updates() { maybe_res, Some(load_fixture("code_lens_response_changed.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_signature_help() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -3362,12 +3335,13 @@ fn lsp_signature_help() { "activeParameter": 1 })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_code_actions() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -3398,7 +3372,7 @@ fn lsp_code_actions() { maybe_res, Some(load_fixture("code_action_resolve_response.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -3542,7 +3516,8 @@ export class DuckConfig { #[test] fn lsp_code_actions_refactor() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -3576,7 +3551,7 @@ fn lsp_code_actions_refactor() { maybe_res, Some(load_fixture("code_action_resolve_response_refactor.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -3624,12 +3599,13 @@ fn lsp_code_actions_refactor_no_disabled_support() { maybe_res, Some(load_fixture("code_action_response_no_disabled.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_code_actions_deadlock() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); client .write_notification( "textDocument/didOpen", @@ -3763,12 +3739,13 @@ fn lsp_code_actions_deadlock() { read_diagnostics(&mut client); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_completions() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -3816,12 +3793,13 @@ fn lsp_completions() { maybe_res, Some(load_fixture("completion_resolve_response.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_completions_private_fields() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -3859,12 +3837,13 @@ fn lsp_completions_private_fields() { } else { panic!("unexpected response"); } - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_completions_optional() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -3929,12 +3908,13 @@ fn lsp_completions_optional() { "insertText": "b" })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_completions_auto_import() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -4046,7 +4026,8 @@ fn lsp_completions_auto_import() { #[test] fn lsp_completions_snippet() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -4226,7 +4207,8 @@ fn lsp_completions_no_snippet() { #[test] fn lsp_completions_npm() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -4383,13 +4365,14 @@ fn lsp_completions_npm() { panic!("unexpected response"); } - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_npm_specifier_unopened_file() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); // create other.ts, which re-exports an npm specifier client.deno_dir().write( @@ -4493,7 +4476,8 @@ fn lsp_npm_specifier_unopened_file() { #[test] fn lsp_completions_node_specifier() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); let diagnostics = CollectedDiagnostics(did_open( &mut client, json!({ @@ -4737,7 +4721,7 @@ fn lsp_completions_node_specifier() { panic!("unexpected response"); } - shutdown(&mut client); + client.shutdown(); } #[test] @@ -4791,7 +4775,7 @@ fn lsp_completions_registry() { maybe_res, Some(load_fixture("completion_resolve_response_registry.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -4832,13 +4816,14 @@ fn lsp_completions_registry_empty() { maybe_res, Some(load_fixture("completion_request_response_empty.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_auto_discover_registry() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -4879,13 +4864,15 @@ fn lsp_auto_discover_registry() { "suggestions": true, })) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_cache_location() { - let _g = http_server(); - let temp_dir = TempDir::new(); + let context = TestContextBuilder::new().use_http_server().build(); + let temp_dir = context.deno_dir(); + + // todo(THIS PR): update this let mut params: lsp::InitializeParams = serde_json::from_value(load_fixture("initialize_params_registry.json")) .unwrap(); @@ -4896,8 +4883,7 @@ fn lsp_cache_location() { params.initialization_options = Some(Value::Object(map)); } - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); + let mut client = context.new_lsp_command().build(); client .write_request::<_, _, Value>("initialize", params) .unwrap(); @@ -5017,8 +5003,7 @@ fn lsp_tls_cert() { params.root_uri = Some(Url::from_file_path(testdata_path()).unwrap()); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); + let mut client = LspClientBuilder::new().build(); client .write_request::<_, _, Value>("initialize", params) .unwrap(); @@ -5127,7 +5112,8 @@ fn lsp_tls_cert() { #[test] fn lsp_diagnostics_warn_redirect() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -5201,13 +5187,14 @@ fn lsp_diagnostics_warn_redirect() { version: Some(1), } ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_redirect_quick_fix() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -5270,12 +5257,13 @@ fn lsp_redirect_quick_fix() { maybe_res, Some(load_fixture("code_action_redirect_response.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_diagnostics_deprecated() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); let diagnostics = did_open( &mut client, json!({ @@ -5328,12 +5316,13 @@ fn lsp_diagnostics_deprecated() { } ]) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_diagnostics_deno_types() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); client .write_notification( "textDocument/didOpen", @@ -5359,7 +5348,7 @@ fn lsp_diagnostics_deno_types() { assert!(maybe_err.is_none()); let diagnostics = read_diagnostics(&mut client); assert_eq!(diagnostics.viewed().len(), 5); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -5466,7 +5455,8 @@ struct PerformanceAverages { #[test] fn lsp_performance() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -5503,12 +5493,13 @@ fn lsp_performance() { } else { panic!("unexpected result"); } - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_format_no_changes() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -5537,12 +5528,13 @@ fn lsp_format_no_changes() { assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(json!(null))); client.assert_no_notification("window/showMessage"); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_format_error() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -5570,12 +5562,13 @@ fn lsp_format_error() { .unwrap(); assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(json!(null))); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_format_mbc() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -5606,34 +5599,40 @@ fn lsp_format_mbc() { maybe_res, Some(json!(load_fixture("formatting_mbc_response.json"))) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_format_exclude_with_config() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let deno_fmt_jsonc = - serde_json::to_vec_pretty(&load_fixture("deno.fmt.exclude.jsonc")).unwrap(); - fs::write(temp_dir.path().join("deno.fmt.jsonc"), deno_fmt_jsonc).unwrap(); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("config".to_string(), json!("./deno.fmt.jsonc")); - params.initialization_options = Some(Value::Object(map)); - } + temp_dir.write( + "deno.fmt.jsonc", + r#"{ + "fmt": { + "files": { + "exclude": [ + "ignored.ts" + ] + }, + "options": { + "useTabs": true, + "lineWidth": 40, + "indentWidth": 8, + "singleQuote": true, + "proseWrap": "always" + } + } + }"#, + ); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("./deno.fmt.jsonc"); + }); - let file_uri = - ModuleSpecifier::from_file_path(temp_dir.path().join("ignored.ts")) - .unwrap() - .to_string(); + let file_uri = temp_dir.uri().join("ignored.ts").unwrap(); did_open( &mut client, json!({ @@ -5661,31 +5660,40 @@ fn lsp_format_exclude_with_config() { .unwrap(); assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(json!(null))); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_format_exclude_default_config() { - let temp_dir = TempDir::new(); - let workspace_root = temp_dir.path().canonicalize().unwrap(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let deno_jsonc = - serde_json::to_vec_pretty(&load_fixture("deno.fmt.exclude.jsonc")).unwrap(); - fs::write(workspace_root.join("deno.jsonc"), deno_jsonc).unwrap(); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); - params.root_uri = Some(Url::from_file_path(workspace_root.clone()).unwrap()); + temp_dir.write( + "deno.fmt.jsonc", + r#"{ + "fmt": { + "files": { + "exclude": [ + "ignored.ts" + ] + }, + "options": { + "useTabs": true, + "lineWidth": 40, + "indentWidth": 8, + "singleQuote": true, + "proseWrap": "always" + } + } + }"#, + ); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("./deno.fmt.jsonc"); + }); - let file_uri = - ModuleSpecifier::from_file_path(workspace_root.join("ignored.ts")) - .unwrap() - .to_string(); + let file_uri = temp_dir.uri().join("ignored.ts").unwrap(); did_open( &mut client, json!({ @@ -5713,12 +5721,13 @@ fn lsp_format_exclude_default_config() { .unwrap(); assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(json!(null))); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_format_json() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); client .write_notification( "textDocument/didOpen", @@ -5783,12 +5792,13 @@ fn lsp_format_json() { } ])) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_json_no_diagnostics() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); client .write_notification( "textDocument/didOpen", @@ -5833,12 +5843,13 @@ fn lsp_json_no_diagnostics() { assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(json!(null))); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_format_markdown() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); client .write_notification( "textDocument/didOpen", @@ -5888,29 +5899,33 @@ fn lsp_format_markdown() { } ])) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_format_with_config() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let deno_fmt_jsonc = - serde_json::to_vec_pretty(&load_fixture("deno.fmt.jsonc")).unwrap(); - fs::write(temp_dir.path().join("deno.fmt.jsonc"), deno_fmt_jsonc).unwrap(); - - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("config".to_string(), json!("./deno.fmt.jsonc")); - params.initialization_options = Some(Value::Object(map)); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); + temp_dir.write( + "deno.fmt.jsonc", + r#"{ + "fmt": { + "options": { + "useTabs": true, + "lineWidth": 40, + "indentWidth": 8, + "singleQuote": true, + "proseWrap": "always" + } + } } + "#, + ); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("./deno.fmt.jsonc"); + }); client .write_notification( @@ -6051,12 +6066,13 @@ fn lsp_format_with_config() { }] )) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_markdown_no_diagnostics() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); client .write_notification( "textDocument/didOpen", @@ -6101,7 +6117,7 @@ fn lsp_markdown_no_diagnostics() { assert!(maybe_err.is_none()); assert_eq!(maybe_res, Some(json!(null))); - shutdown(&mut client); + client.shutdown(); } #[test] @@ -6191,12 +6207,13 @@ fn lsp_configuration_did_change() { maybe_res, Some(load_fixture("completion_resolve_response_registry.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_workspace_symbol() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -6305,12 +6322,13 @@ fn lsp_workspace_symbol() { } ])) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_code_actions_ignore_lint() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -6333,13 +6351,14 @@ fn lsp_code_actions_ignore_lint() { maybe_res, Some(load_fixture("code_action_ignore_lint_response.json")) ); - shutdown(&mut client); + client.shutdown(); } /// This test exercises updating an existing deno-lint-ignore-file comment. #[test] fn lsp_code_actions_update_ignore_lint() { - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -6367,29 +6386,37 @@ console.log(snake_case); maybe_res, Some(load_fixture("code_action_update_ignore_lint_response.json")) ); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_lint_with_config() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let deno_lint_jsonc = - serde_json::to_vec_pretty(&load_fixture("deno.lint.jsonc")).unwrap(); - fs::write(temp_dir.path().join("deno.lint.jsonc"), deno_lint_jsonc).unwrap(); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("config".to_string(), json!("./deno.lint.jsonc")); - params.initialization_options = Some(Value::Object(map)); + temp_dir.write( + "deno.lint.jsonc", + r#"{ + "lint": { + "rules": { + "exclude": [ + "camelcase" + ], + "include": [ + "ban-untagged-todo" + ], + "tags": [] + } + } } + "#, + ); + + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("./deno.lint.jsonc"); + }); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); let mut session = TestSession::from_client(client); let diagnostics = session.did_open(load_fixture("did_open_lint.json")); @@ -6404,25 +6431,35 @@ fn lsp_lint_with_config() { #[test] fn lsp_lint_exclude_with_config() { - let temp_dir = TempDir::new(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let deno_lint_jsonc = - serde_json::to_vec_pretty(&load_fixture("deno.lint.exclude.jsonc")) - .unwrap(); - fs::write(temp_dir.path().join("deno.lint.jsonc"), deno_lint_jsonc).unwrap(); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("config".to_string(), json!("./deno.lint.jsonc")); - params.initialization_options = Some(Value::Object(map)); - } + temp_dir.write( + "deno.lint.jsonc", + r#"{ + "lint": { + "files": { + "exclude": [ + "ignored.ts" + ] + }, + "rules": { + "exclude": [ + "camelcase" + ], + "include": [ + "ban-untagged-todo" + ], + "tags": [] + } + } + }"#, + ); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_config("./deno.lint.jsonc"); + }); let diagnostics = did_open( &mut client, @@ -6440,13 +6477,14 @@ fn lsp_lint_exclude_with_config() { .flat_map(|x| x.diagnostics) .collect::>(); assert_eq!(diagnostics, Vec::new()); - shutdown(&mut client); + client.shutdown(); } #[test] fn lsp_jsx_import_source_pragma() { let _g = http_server(); - let mut client = init("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); did_open( &mut client, json!({ @@ -6519,7 +6557,7 @@ export function B() { } })) ); - shutdown(&mut client); + client.shutdown(); } #[derive(Debug, Clone, Deserialize, PartialEq)] @@ -6562,15 +6600,9 @@ struct TestRunResponseParams { #[test] fn lsp_testing_api() { - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); - let temp_dir = TempDir::new(); - - let root_specifier = - ensure_directory_specifier(Url::from_file_path(temp_dir.path()).unwrap()); + let context = TestContextBuilder::new().build(); + let temp_dir = context.deno_dir(); - let module_path = temp_dir.path().join("./test.ts"); - let specifier = ModuleSpecifier::from_file_path(&module_path).unwrap(); let contents = r#" Deno.test({ name: "test a", @@ -6579,18 +6611,12 @@ Deno.test({ } }); "#; - fs::write(&module_path, contents).unwrap(); - fs::write(temp_dir.path().join("./deno.jsonc"), r#"{}"#).unwrap(); - - params.root_uri = Some(root_specifier); + temp_dir.write("./test.ts", &contents); + temp_dir.write("./deno.jsonc", "{}"); + let specifier = temp_dir.uri().join("test.ts").unwrap(); - let deno_exe = deno_exe_path(); - let mut client = LspClient::new(&deno_exe, false).unwrap(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); - - client.write_notification("initialized", json!({})).unwrap(); + let mut client = context.new_lsp_command().build(); + client.initialize_default(); client .write_notification( @@ -6763,5 +6789,5 @@ Deno.test({ _ => panic!("unexpected message {}", json!(notification)), } - shutdown(&mut client); + client.shutdown(); } diff --git a/cli/tests/testdata/lsp/a.d.ts b/cli/tests/testdata/lsp/a.d.ts deleted file mode 100644 index 536a6d0a69c963..00000000000000 --- a/cli/tests/testdata/lsp/a.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -// deno-lint-ignore-file no-var -declare var a: string; diff --git a/cli/tests/testdata/lsp/b.d.ts b/cli/tests/testdata/lsp/b.d.ts deleted file mode 100644 index 2fd56623b591ff..00000000000000 --- a/cli/tests/testdata/lsp/b.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -// deno-lint-ignore-file no-var -declare var b: string; diff --git a/cli/tests/testdata/lsp/deno.embedded_import_map.jsonc b/cli/tests/testdata/lsp/deno.embedded_import_map.jsonc deleted file mode 100644 index 75d5d08491836f..00000000000000 --- a/cli/tests/testdata/lsp/deno.embedded_import_map.jsonc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "imports": { - "/~/": "./lib/" - } -} diff --git a/cli/tests/testdata/lsp/deno.fmt.exclude.jsonc b/cli/tests/testdata/lsp/deno.fmt.exclude.jsonc deleted file mode 100644 index 246a403168d58f..00000000000000 --- a/cli/tests/testdata/lsp/deno.fmt.exclude.jsonc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "fmt": { - "files": { - "exclude": [ - "ignored.ts" - ] - }, - "options": { - "useTabs": true, - "lineWidth": 40, - "indentWidth": 8, - "singleQuote": true, - "proseWrap": "always" - } - } -} diff --git a/cli/tests/testdata/lsp/deno.fmt.jsonc b/cli/tests/testdata/lsp/deno.fmt.jsonc deleted file mode 100644 index a0a8517318b7d2..00000000000000 --- a/cli/tests/testdata/lsp/deno.fmt.jsonc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "fmt": { - "options": { - "useTabs": true, - "lineWidth": 40, - "indentWidth": 8, - "singleQuote": true, - "proseWrap": "always" - } - } -} diff --git a/cli/tests/testdata/lsp/deno.lint.jsonc b/cli/tests/testdata/lsp/deno.lint.jsonc deleted file mode 100644 index 03308ab5f9acbd..00000000000000 --- a/cli/tests/testdata/lsp/deno.lint.jsonc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "lint": { - "rules": { - "exclude": [ - "camelcase" - ], - "include": [ - "ban-untagged-todo" - ], - "tags": [] - } - } -} diff --git a/cli/tests/testdata/lsp/import-map-completions.json b/cli/tests/testdata/lsp/import-map-completions.json deleted file mode 100644 index f2275222af61d1..00000000000000 --- a/cli/tests/testdata/lsp/import-map-completions.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "imports": { - "/~/": "./lib/", - "fs": "https://example.com/fs/index.js", - "std/": "https://example.com/std@0.123.0/" - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_bad_config_option.json b/cli/tests/testdata/lsp/initialize_params_bad_config_option.json deleted file mode 100644 index 053cb70f39bb55..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_bad_config_option.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "codeLens": { - "implementations": true, - "references": true, - "test": true - }, - "config": "bad_tsconfig.json", - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/cli/tests/testdata/lsp/lib.tsconfig.json b/cli/tests/testdata/lsp/lib.tsconfig.json deleted file mode 100644 index 8d2ae8a8b3da02..00000000000000 --- a/cli/tests/testdata/lsp/lib.tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "lib": ["deno.ns", "deno.unstable", "dom"] - } -} diff --git a/test_util/Cargo.toml b/test_util/Cargo.toml index 93bad8594b85ce..705ccda408dc86 100644 --- a/test_util/Cargo.toml +++ b/test_util/Cargo.toml @@ -23,6 +23,7 @@ flate2.workspace = true futures.workspace = true hyper = { workspace = true, features = ["server", "http1", "http2", "runtime"] } lazy_static = "1.4.0" +lsp-types.workspace = true once_cell.workspace = true os_pipe.workspace = true parking_lot.workspace = true diff --git a/test_util/src/builders.rs b/test_util/src/builders.rs index 6ccb45f50f7631..3b85d1701aad37 100644 --- a/test_util/src/builders.rs +++ b/test_util/src/builders.rs @@ -18,6 +18,7 @@ use crate::copy_dir_recursive; use crate::deno_exe_path; use crate::env_vars_for_npm_tests_no_sync_download; use crate::http_server; +use crate::lsp::LspClientBuilder; use crate::new_deno_dir; use crate::strip_ansi_codes; use crate::testdata_path; @@ -35,6 +36,7 @@ pub struct TestContextBuilder { copy_temp_dir: Option, cwd: Option, envs: HashMap, + deno_exe: Option, } impl TestContextBuilder { @@ -110,7 +112,7 @@ impl TestContextBuilder { testdata_path() }; - let deno_exe = deno_exe_path(); + let deno_exe = self.deno_exe.clone().unwrap_or_else(|| deno_exe_path()); println!("deno_exe path {}", deno_exe.display()); let http_server_guard = if self.use_http_server { @@ -121,6 +123,7 @@ impl TestContextBuilder { TestContext { cwd: self.cwd.clone(), + deno_exe, envs: self.envs.clone(), use_temp_cwd: self.use_temp_cwd, _http_server_guard: http_server_guard, @@ -132,6 +135,7 @@ impl TestContextBuilder { #[derive(Clone)] pub struct TestContext { + deno_exe: PathBuf, envs: HashMap, use_temp_cwd: bool, cwd: Option, @@ -161,7 +165,7 @@ impl TestContext { pub fn new_command(&self) -> TestCommandBuilder { TestCommandBuilder { - command_name: Default::default(), + command_name: self.deno_exe.to_string_lossy().to_string(), args: Default::default(), args_vec: Default::default(), stdin: Default::default(), @@ -171,10 +175,16 @@ impl TestContext { context: self.clone(), } } + + pub fn new_lsp_command(&self) -> LspClientBuilder { + let mut builder = LspClientBuilder::new(); + builder.deno_exe(&self.deno_exe).set_test_context(&self); + builder + } } pub struct TestCommandBuilder { - command_name: Option, + command_name: String, args: String, args_vec: Vec, stdin: Option, @@ -186,7 +196,7 @@ pub struct TestCommandBuilder { impl TestCommandBuilder { pub fn command_name(&mut self, name: impl AsRef) -> &mut Self { - self.command_name = Some(name.as_ref().to_string()); + self.command_name = name.as_ref().to_string(); self } @@ -257,11 +267,7 @@ impl TestCommandBuilder { }) .collect::>(); let (mut reader, writer) = pipe().unwrap(); - let command_name = self - .command_name - .as_ref() - .cloned() - .unwrap_or("deno".to_string()); + let command_name = &self.command_name; let mut command = if command_name == "deno" { Command::new(deno_exe_path()) } else { diff --git a/test_util/src/lsp.rs b/test_util/src/lsp.rs index c4a81c63c621fe..31c1c8fb5f6e6f 100644 --- a/test_util/src/lsp.rs +++ b/test_util/src/lsp.rs @@ -1,12 +1,29 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use crate::deno_exe_path; use crate::npm_registry_url; +use crate::TestContext; +use crate::TestContextBuilder; use super::new_deno_dir; use super::TempDir; use anyhow::Result; use lazy_static::lazy_static; +use lsp_types::ClientCapabilities; +use lsp_types::ClientInfo; +use lsp_types::CodeActionCapabilityResolveSupport; +use lsp_types::CodeActionClientCapabilities; +use lsp_types::CodeActionKindLiteralSupport; +use lsp_types::CodeActionLiteralSupport; +use lsp_types::CompletionClientCapabilities; +use lsp_types::CompletionItemCapability; +use lsp_types::FoldingRangeClientCapabilities; +use lsp_types::InitializeParams; +use lsp_types::TextDocumentClientCapabilities; +use lsp_types::TextDocumentSyncClientCapabilities; +use lsp_types::Url; +use lsp_types::WorkspaceClientCapabilities; use parking_lot::Condvar; use parking_lot::Mutex; use regex::Regex; @@ -19,6 +36,7 @@ use serde_json::Value; use std::io; use std::io::Write; use std::path::Path; +use std::path::PathBuf; use std::process::Child; use std::process::ChildStdin; use std::process::ChildStdout; @@ -153,6 +171,226 @@ impl LspStdoutReader { } } +pub struct InitializeParamsBuilder { + params: InitializeParams, +} + +impl InitializeParamsBuilder { + pub fn new() -> Self { + Self { + params: InitializeParams { + process_id: None, + client_info: Some(ClientInfo { + name: "test-harness".to_string(), + version: Some("1.0.0".to_string()), + }), + root_uri: None, + initialization_options: Some(json!({ + "enable": true, + "cache": null, + "certificateStores": null, + "codeLens": { + "implementations": true, + "references": true, + "test": true + }, + "config": null, + "importMap": null, + "lint": true, + "suggest": { + "autoImports": true, + "completeFunctionCalls": false, + "names": true, + "paths": true, + "imports": { + "hosts": {} + } + }, + "testing": { + "args": [ + "--allow-all" + ], + "enable": true + }, + "tlsCertificate": null, + "unsafelyIgnoreCertificateErrors": null, + "unstable": false + })), + capabilities: ClientCapabilities { + text_document: Some(TextDocumentClientCapabilities { + code_action: Some(CodeActionClientCapabilities { + code_action_literal_support: Some(CodeActionLiteralSupport { + code_action_kind: CodeActionKindLiteralSupport { + value_set: vec![ + "quickfix".to_string(), + "refactor".to_string(), + ], + }, + }), + is_preferred_support: Some(true), + data_support: Some(true), + disabled_support: Some(true), + resolve_support: Some(CodeActionCapabilityResolveSupport { + properties: vec!["edit".to_string()], + }), + ..Default::default() + }), + completion: Some(CompletionClientCapabilities { + completion_item: Some(CompletionItemCapability { + snippet_support: Some(true), + ..Default::default() + }), + ..Default::default() + }), + folding_range: Some(FoldingRangeClientCapabilities { + line_folding_only: Some(true), + ..Default::default() + }), + synchronization: Some(TextDocumentSyncClientCapabilities { + dynamic_registration: Some(true), + will_save: Some(true), + will_save_wait_until: Some(true), + did_save: Some(true), + }), + ..Default::default() + }), + workspace: Some(WorkspaceClientCapabilities { + configuration: Some(true), + workspace_folders: Some(true), + ..Default::default() + }), + experimental: Some(json!({ + "testingApi": true + })), + ..Default::default() + }, + ..Default::default() + }, + } + } + + pub fn set_maybe_root_uri(&mut self, value: Option) -> &mut Self { + self.params.root_uri = value; + self + } + + pub fn set_root_uri(&mut self, value: Url) -> &mut Self { + self.set_maybe_root_uri(Some(value)) + } + + pub fn set_workspace_folders( + &mut self, + folders: Vec, + ) -> &mut Self { + self.params.workspace_folders = Some(folders); + self + } + + pub fn set_config(&mut self, value: impl AsRef) -> &mut Self { + let options = self.initialization_options_mut(); + options.insert("config".to_string(), value.as_ref().to_string().into()); + self + } + + pub fn set_enable_paths(&mut self, value: Vec) -> &mut Self { + let options = self.initialization_options_mut(); + options.insert("enablePaths".to_string(), value.into()); + self + } + + pub fn set_deno_enable(&mut self, value: bool) -> &mut Self { + let options = self.initialization_options_mut(); + options.insert("enable".to_string(), value.into()); + self + } + + pub fn set_import_map(&mut self, value: impl AsRef) -> &mut Self { + let options = self.initialization_options_mut(); + options.insert("importMap".to_string(), value.as_ref().to_string().into()); + self + } + + fn initialization_options_mut( + &mut self, + ) -> &mut serde_json::Map { + let options = self.params.initialization_options.as_mut().unwrap(); + options.as_object_mut().unwrap() + } + + pub fn build(&self) -> InitializeParams { + self.params.clone() + } +} + +pub struct LspClientBuilder { + print_stderr: bool, + deno_exe: PathBuf, + context: Option, +} + +impl LspClientBuilder { + pub fn new() -> Self { + Self { + print_stderr: false, + deno_exe: deno_exe_path(), + context: None, + } + } + + pub fn deno_exe(&mut self, exe_path: impl AsRef) -> &mut Self { + self.deno_exe = exe_path.as_ref().to_path_buf(); + self + } + + pub fn print_stderr(&mut self) -> &mut Self { + self.print_stderr = true; + self + } + + pub fn set_test_context(&mut self, test_context: &TestContext) -> &mut Self { + self.context = Some(test_context.clone()); + self + } + + pub fn build(&self) -> LspClient { + self.build_result().unwrap() + } + + pub fn build_result(&self) -> Result { + let deno_dir = new_deno_dir(); + let mut command = Command::new(&self.deno_exe); + command + .env("DENO_DIR", deno_dir.path()) + .env("NPM_CONFIG_REGISTRY", npm_registry_url()) + .arg("lsp") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()); + if !self.print_stderr { + command.stderr(Stdio::null()); + } + let mut child = command.spawn()?; + let stdout = child.stdout.take().unwrap(); + let buf_reader = io::BufReader::new(stdout); + let reader = LspStdoutReader::new(buf_reader); + + let stdin = child.stdin.take().unwrap(); + let writer = io::BufWriter::new(stdin); + + Ok(LspClient { + child, + reader, + request_id: 1, + start: Instant::now(), + context: self + .context + .clone() + .unwrap_or_else(|| TestContextBuilder::new().build()), + writer, + deno_dir, + }) + } +} + pub struct LspClient { child: Child, reader: LspStdoutReader, @@ -160,6 +398,7 @@ pub struct LspClient { start: Instant, writer: io::BufWriter, deno_dir: TempDir, + context: TestContext, } impl Drop for LspClient { @@ -228,36 +467,6 @@ where } impl LspClient { - pub fn new(deno_exe: &Path, print_stderr: bool) -> Result { - let deno_dir = new_deno_dir(); - let mut command = Command::new(deno_exe); - command - .env("DENO_DIR", deno_dir.path()) - .env("NPM_CONFIG_REGISTRY", npm_registry_url()) - .arg("lsp") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()); - if !print_stderr { - command.stderr(Stdio::null()); - } - let mut child = command.spawn()?; - let stdout = child.stdout.take().unwrap(); - let buf_reader = io::BufReader::new(stdout); - let reader = LspStdoutReader::new(buf_reader); - - let stdin = child.stdin.take().unwrap(); - let writer = io::BufWriter::new(stdin); - - Ok(Self { - child, - reader, - request_id: 1, - start: Instant::now(), - writer, - deno_dir, - }) - } - pub fn deno_dir(&self) -> &TempDir { &self.deno_dir } @@ -274,6 +483,30 @@ impl LspClient { self.reader.pending_len() } + pub fn initialize_default(&mut self) { + self.initialize(|_| {}) + } + + pub fn initialize( + &mut self, + do_build: impl Fn(&mut InitializeParamsBuilder), + ) { + let mut builder = InitializeParamsBuilder::new(); + builder.set_root_uri(self.context.deno_dir().uri()); + do_build(&mut builder); + self + .write_request::<_, _, Value>("initialize", builder.build()) + .unwrap(); + self.write_notification("initialized", json!({})).unwrap(); + } + + pub fn shutdown(&mut self) { + self + .write_request::<_, _, Value>("shutdown", json!(null)) + .unwrap(); + self.write_notification("exit", json!(null)).unwrap(); + } + // it's flaky to assert for a notification because a notification // might arrive a little later, so only provide a method for asserting // that there is no notification diff --git a/test_util/src/temp_dir.rs b/test_util/src/temp_dir.rs index 01dce8f1ab434f..b800e425d2a4fc 100644 --- a/test_util/src/temp_dir.rs +++ b/test_util/src/temp_dir.rs @@ -9,6 +9,7 @@ use std::sync::Arc; use std::time::SystemTime; use anyhow::Context; +use lsp_types::Url; use once_cell::sync::OnceCell; static TEMP_DIR_SESSION: OnceCell = OnceCell::new(); @@ -83,6 +84,10 @@ impl TempDir { }) } + pub fn uri(&self) -> Url { + Url::from_directory_path(self.path()).unwrap() + } + pub fn path(&self) -> &Path { let inner = &self.0; inner.0.as_path() From b2cf5c8ef8e39ccaa9a6fa7bc240431c45ca876a Mon Sep 17 00:00:00 2001 From: David Sherret Date: Sat, 4 Mar 2023 19:11:34 -0500 Subject: [PATCH 2/9] More updates. --- cli/tests/integration/lsp_tests.rs | 88 ++++++++----------- .../lsp/initialize_params_disabled.json | 63 ------------- .../lsp/initialize_params_registry.json | 67 -------------- test_util/src/lsp.rs | 28 ++++++ 4 files changed, 65 insertions(+), 181 deletions(-) delete mode 100644 cli/tests/testdata/lsp/initialize_params_disabled.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_registry.json diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index e9652423bb67f3..5e7d7cee8725e1 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -91,17 +91,6 @@ fn read_diagnostics(client: &mut LspClient) -> CollectedDiagnostics { CollectedDiagnostics(diagnostics) } -pub fn ensure_directory_specifier( - mut specifier: ModuleSpecifier, -) -> ModuleSpecifier { - let path = specifier.path(); - if !path.ends_with('/') { - let new_path = format!("{path}/"); - specifier.set_path(&new_path); - } - specifier -} - // todo(THIS PR): get rid of this in favour of LspClient struct TestSession { client: LspClient, @@ -1082,7 +1071,11 @@ fn lsp_hover_asset() { #[test] fn lsp_hover_disabled() { - let mut client = init("initialize_params_disabled.json"); + let context = TestContextBuilder::new().build(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.set_deno_enable(false); + }); client .write_notification( "textDocument/didOpen", @@ -1863,8 +1856,8 @@ fn lsp_hover_closed_document() { #[test] fn lsp_hover_dependency() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); did_open( &mut client, @@ -2199,8 +2192,8 @@ fn lsp_hover_deps_preserved_when_invalid_parse() { #[test] fn lsp_hover_typescript_types() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); did_open( &mut client, @@ -4206,8 +4199,8 @@ fn lsp_completions_no_snippet() { #[test] fn lsp_completions_npm() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); did_open( &mut client, @@ -4370,8 +4363,8 @@ fn lsp_completions_npm() { #[test] fn lsp_npm_specifier_unopened_file() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); // create other.ts, which re-exports an npm specifier @@ -4475,8 +4468,8 @@ fn lsp_npm_specifier_unopened_file() { #[test] fn lsp_completions_node_specifier() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); let diagnostics = CollectedDiagnostics(did_open( &mut client, @@ -4726,8 +4719,11 @@ fn lsp_completions_node_specifier() { #[test] fn lsp_completions_registry() { - let _g = http_server(); - let mut client = init("initialize_params_registry.json"); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.add_test_server_suggestions(); + }); did_open( &mut client, json!({ @@ -4780,8 +4776,11 @@ fn lsp_completions_registry() { #[test] fn lsp_completions_registry_empty() { - let _g = http_server(); - let mut client = init("initialize_params_registry.json"); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.add_test_server_suggestions(); + }); did_open( &mut client, json!({ @@ -4821,8 +4820,8 @@ fn lsp_completions_registry_empty() { #[test] fn lsp_auto_discover_registry() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); did_open( &mut client, @@ -4871,25 +4870,12 @@ fn lsp_auto_discover_registry() { fn lsp_cache_location() { let context = TestContextBuilder::new().use_http_server().build(); let temp_dir = context.deno_dir(); - - // todo(THIS PR): update this - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params_registry.json")) - .unwrap(); - - params.root_uri = Some(Url::from_file_path(temp_dir.path()).unwrap()); - if let Some(Value::Object(mut map)) = params.initialization_options { - map.insert("cache".to_string(), json!(".cache")); - params.initialization_options = Some(Value::Object(map)); - } - let mut client = context.new_lsp_command().build(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); - client.write_notification("initialized", json!({})).unwrap(); - let mut session = TestSession::from_client(client); + client.initialize(|builder| { + builder.set_cache(".cache").add_test_server_suggestions(); + }); + let mut session = TestSession::from_client(client); session.did_open(json!({ "textDocument": { "uri": "file:///a/file_01.ts", @@ -5111,8 +5097,8 @@ fn lsp_tls_cert() { #[test] fn lsp_diagnostics_warn_redirect() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); did_open( &mut client, @@ -5192,8 +5178,8 @@ fn lsp_diagnostics_warn_redirect() { #[test] fn lsp_redirect_quick_fix() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); did_open( &mut client, @@ -6482,8 +6468,8 @@ fn lsp_lint_exclude_with_config() { #[test] fn lsp_jsx_import_source_pragma() { - let _g = http_server(); - let mut client = LspClientBuilder::new().build(); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); client.initialize_default(); did_open( &mut client, diff --git a/cli/tests/testdata/lsp/initialize_params_disabled.json b/cli/tests/testdata/lsp/initialize_params_disabled.json deleted file mode 100644 index 879b1181c8731f..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_disabled.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": false, - "cache": null, - "codeLens": { - "implementations": true, - "references": true - }, - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_registry.json b/cli/tests/testdata/lsp/initialize_params_registry.json deleted file mode 100644 index 286f6085f1e4f3..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_registry.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "codeLens": { - "implementations": true, - "references": true, - "test": true - }, - "config": "", - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": { - "http://localhost:4545/": true - } - } - }, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/test_util/src/lsp.rs b/test_util/src/lsp.rs index 31c1c8fb5f6e6f..7b74968bef147c 100644 --- a/test_util/src/lsp.rs +++ b/test_util/src/lsp.rs @@ -286,6 +286,12 @@ impl InitializeParamsBuilder { self } + pub fn set_cache(&mut self, value: impl AsRef) -> &mut Self { + let options = self.initialization_options_mut(); + options.insert("cache".to_string(), value.as_ref().to_string().into()); + self + } + pub fn set_config(&mut self, value: impl AsRef) -> &mut Self { let options = self.initialization_options_mut(); options.insert("config".to_string(), value.as_ref().to_string().into()); @@ -310,6 +316,28 @@ impl InitializeParamsBuilder { self } + pub fn add_test_server_suggestions(&mut self) -> &mut Self { + self.set_suggest_imports_hosts(vec![( + "http://localhost:4545/".to_string(), + true, + )]) + } + + pub fn set_suggest_imports_hosts( + &mut self, + values: Vec<(String, bool)>, + ) -> &mut Self { + let options = self.initialization_options_mut(); + let suggest = options.get_mut("suggest").unwrap().as_object_mut().unwrap(); + let imports = suggest.get_mut("imports").unwrap().as_object_mut().unwrap(); + let hosts = imports.get_mut("hosts").unwrap().as_object_mut().unwrap(); + hosts.clear(); + for (key, value) in values { + hosts.insert(key.into(), value.into()); + } + self + } + fn initialization_options_mut( &mut self, ) -> &mut serde_json::Map { From 2cc232a69617e737ec2d1513f68c1b9a0efdc87f Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 8 Mar 2023 16:01:45 -0500 Subject: [PATCH 3/9] More progress --- cli/tests/integration/lsp_tests.rs | 46 +++++--- ...ialize_params_code_lens_test_disabled.json | 64 ----------- .../testdata/lsp/initialize_params_hints.json | 102 ------------------ .../lsp/initialize_params_tls_cert.json | 71 ------------ .../lsp/initialize_params_unstable.json | 63 ----------- test_util/src/lsp.rs | 71 ++++++++++++ 6 files changed, 102 insertions(+), 315 deletions(-) delete mode 100644 cli/tests/testdata/lsp/initialize_params_code_lens_test_disabled.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_hints.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_tls_cert.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_unstable.json diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index da7f739211db3d..036745b6939e65 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -1113,7 +1113,11 @@ fn lsp_hover_disabled() { #[test] fn lsp_inlay_hints() { - let mut client = init("initialize_params_hints.json"); + let context = TestContextBuilder::new().build(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder.enable_inlay_hints(); + }); did_open( &mut client, json!({ @@ -1568,7 +1572,10 @@ fn lsp_hover_unstable_disabled() { #[test] fn lsp_hover_unstable_enabled() { - let mut client = init("initialize_params_unstable.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize(|builder| { + builder.set_unstable(true); + }); did_open( &mut client, json!({ @@ -2960,7 +2967,10 @@ fn lsp_code_lens_impl() { #[test] fn lsp_code_lens_test() { - let mut client = init("initialize_params_code_lens_test.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize(|builder| { + builder.disable_testing_api().set_code_lens(None); + }); did_open( &mut client, load_fixture("did_open_params_test_code_lens.json"), @@ -2985,7 +2995,14 @@ fn lsp_code_lens_test() { #[test] fn lsp_code_lens_test_disabled() { - let mut client = init("initialize_params_code_lens_test_disabled.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize(|builder| { + builder.disable_testing_api().set_code_lens(Some(json!({ + "implementations": true, + "references": true, + "test": false + }))); + }); client .write_notification( "textDocument/didOpen", @@ -4982,18 +4999,17 @@ fn lsp_cache_location() { /// and cache files. #[test] fn lsp_tls_cert() { - let _g = http_server(); - let mut params: lsp::InitializeParams = - serde_json::from_value(load_fixture("initialize_params_tls_cert.json")) - .unwrap(); - - params.root_uri = Some(Url::from_file_path(testdata_path()).unwrap()); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); + client.initialize(|builder| { + builder + .set_suggest_imports_hosts(vec![ + ("http://localhost:4545/".to_string(), true), + ("https://localhost:5545/".to_string(), true), + ]) + .set_tls_certificate(""); + }); - let mut client = LspClientBuilder::new().build(); - client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); - client.write_notification("initialized", json!({})).unwrap(); let mut session = TestSession::from_client(client); session.did_open(json!({ diff --git a/cli/tests/testdata/lsp/initialize_params_code_lens_test_disabled.json b/cli/tests/testdata/lsp/initialize_params_code_lens_test_disabled.json deleted file mode 100644 index 1d18934ae86d74..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_code_lens_test_disabled.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "codeLens": { - "implementations": true, - "references": true, - "test": false - }, - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_hints.json b/cli/tests/testdata/lsp/initialize_params_hints.json deleted file mode 100644 index 1bab6e86d8b518..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_hints.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "certificateStores": null, - "codeLens": { - "implementations": true, - "references": true, - "test": true - }, - "config": null, - "importMap": null, - "inlayHints": { - "parameterNames": { - "enabled": "all" - }, - "parameterTypes": { - "enabled": true - }, - "variableTypes": { - "enabled": true - }, - "propertyDeclarationTypes": { - "enabled": true - }, - "functionLikeReturnTypes": { - "enabled": true - }, - "enumMemberValues": { - "enabled": true - } - }, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "testing": { - "args": [ - "--allow-all" - ], - "enable": true - }, - "tlsCertificate": null, - "unsafelyIgnoreCertificateErrors": null, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "completion": { - "completionItem": { - "snippetSupport": true - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - }, - "experimental": { - "testingApi": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_tls_cert.json b/cli/tests/testdata/lsp/initialize_params_tls_cert.json deleted file mode 100644 index e231bf25faf766..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_tls_cert.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "certificateStores": null, - "codeLens": { - "implementations": true, - "references": true, - "test": true - }, - "config": "", - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": { - "https://localhost:5545": true, - "http://localhost:4545": true - } - } - }, - "tlsCertificate": "tls/RootCA.pem", - "unsafelyIgnoreCertificateErrors": null, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_unstable.json b/cli/tests/testdata/lsp/initialize_params_unstable.json deleted file mode 100644 index 104db16f24b946..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_unstable.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "codeLens": { - "implementations": true, - "references": true - }, - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "unstable": true - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/test_util/src/lsp.rs b/test_util/src/lsp.rs index 7b74968bef147c..283e81d27fbda5 100644 --- a/test_util/src/lsp.rs +++ b/test_util/src/lsp.rs @@ -286,12 +286,68 @@ impl InitializeParamsBuilder { self } + pub fn enable_inlay_hints(&mut self) -> &mut Self { + let options = self.initialization_options_mut(); + options.insert( + "inlayHints".to_string(), + json!({ + "parameterNames": { + "enabled": "all" + }, + "parameterTypes": { + "enabled": true + }, + "variableTypes": { + "enabled": true + }, + "propertyDeclarationTypes": { + "enabled": true + }, + "functionLikeReturnTypes": { + "enabled": true + }, + "enumMemberValues": { + "enabled": true + } + }), + ); + self + } + + pub fn disable_testing_api(&mut self) -> &mut Self { + let obj = self + .params + .capabilities + .experimental + .as_mut() + .unwrap() + .as_object_mut() + .unwrap(); + obj.insert("testingApi".to_string(), false.into()); + let options = self.initialization_options_mut(); + options.remove("testing"); + self + } + pub fn set_cache(&mut self, value: impl AsRef) -> &mut Self { let options = self.initialization_options_mut(); options.insert("cache".to_string(), value.as_ref().to_string().into()); self } + pub fn set_code_lens( + &mut self, + value: Option, + ) -> &mut Self { + let options = self.initialization_options_mut(); + if let Some(value) = value { + options.insert("codeLens".to_string(), value); + } else { + options.remove("codeLens"); + } + self + } + pub fn set_config(&mut self, value: impl AsRef) -> &mut Self { let options = self.initialization_options_mut(); options.insert("config".to_string(), value.as_ref().to_string().into()); @@ -316,6 +372,21 @@ impl InitializeParamsBuilder { self } + pub fn set_tls_certificate(&mut self, value: impl AsRef) -> &mut Self { + let options = self.initialization_options_mut(); + options.insert( + "tlsCertificate".to_string(), + value.as_ref().to_string().into(), + ); + self + } + + pub fn set_unstable(&mut self, value: bool) -> &mut Self { + let options = self.initialization_options_mut(); + options.insert("unstable".to_string(), value.into()); + self + } + pub fn add_test_server_suggestions(&mut self) -> &mut Self { self.set_suggest_imports_hosts(vec![( "http://localhost:4545/".to_string(), From 3a6c0a56afdb115d05358d69e5459b81df4c1605 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 8 Mar 2023 16:16:28 -0500 Subject: [PATCH 4/9] Remove `init` --- cli/bench/lsp.rs | 33 +------- cli/bench/lsp_bench_standalone.rs | 11 +-- cli/tests/integration/lsp_tests.rs | 53 ++++++------ cli/tests/testdata/lsp/initialize_params.json | 82 ------------------- .../lsp/initialize_params_ca_no_disabled.json | 64 --------------- .../lsp/initialize_params_code_lens_test.json | 59 ------------- .../initialize_params_did_config_change.json | 65 --------------- .../lsp/initialize_params_import_map.json | 62 -------------- .../lsp/initialize_params_no_snippet.json | 77 ----------------- ...tialize_params_workspace_enable_paths.json | 77 ----------------- test_util/src/lsp.rs | 8 ++ 11 files changed, 43 insertions(+), 548 deletions(-) delete mode 100644 cli/tests/testdata/lsp/initialize_params.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_ca_no_disabled.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_code_lens_test.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_did_config_change.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_import_map.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_no_snippet.json delete mode 100644 cli/tests/testdata/lsp/initialize_params_workspace_enable_paths.json diff --git a/cli/bench/lsp.rs b/cli/bench/lsp.rs index 12d37941199b6f..b0682e2e924978 100644 --- a/cli/bench/lsp.rs +++ b/cli/bench/lsp.rs @@ -9,7 +9,6 @@ use deno_core::url::Url; use std::collections::HashMap; use std::path::Path; use std::time::Duration; -use test_util::lsp::LspClient; use test_util::lsp::LspClientBuilder; use test_util::lsp::LspResponseError; use tower_lsp::lsp_types as lsp; @@ -17,8 +16,6 @@ use tower_lsp::lsp_types as lsp; static FIXTURE_CODE_LENS_TS: &str = include_str!("testdata/code_lens.ts"); static FIXTURE_DB_TS: &str = include_str!("testdata/db.ts"); static FIXTURE_DB_MESSAGES: &[u8] = include_bytes!("testdata/db_messages.json"); -static FIXTURE_INIT_JSON: &[u8] = - include_bytes!("testdata/initialize_params.json"); #[derive(Debug, Deserialize)] enum FixtureType { @@ -46,13 +43,7 @@ struct FixtureMessage { /// code actions. fn bench_big_file_edits(deno_exe: &Path) -> Result { let mut client = LspClientBuilder::new().deno_exe(deno_exe).build(); - - let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON)?; - let (_, response_error): (Option, Option) = - client.write_request("initialize", params)?; - assert!(response_error.is_none()); - - client.write_notification("initialized", json!({}))?; + client.initialize_default(); client.write_notification( "textDocument/didOpen", @@ -127,12 +118,7 @@ fn bench_big_file_edits(deno_exe: &Path) -> Result { fn bench_code_lens(deno_exe: &Path) -> Result { let mut client = LspClientBuilder::new().deno_exe(deno_exe).build(); - - let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON)?; - let (_, maybe_err) = - client.write_request::<_, _, Value>("initialize", params)?; - assert!(maybe_err.is_none()); - client.write_notification("initialized", json!({}))?; + client.initialize_default(); client.write_notification( "textDocument/didOpen", @@ -191,12 +177,7 @@ fn bench_code_lens(deno_exe: &Path) -> Result { fn bench_find_replace(deno_exe: &Path) -> Result { let mut client = LspClientBuilder::new().deno_exe(deno_exe).build(); - - let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON)?; - let (_, maybe_err) = - client.write_request::<_, _, Value>("initialize", params)?; - assert!(maybe_err.is_none()); - client.write_notification("initialized", json!({}))?; + client.initialize_default(); for i in 0..10 { client.write_notification( @@ -287,13 +268,7 @@ fn bench_find_replace(deno_exe: &Path) -> Result { /// A test that starts up the LSP, opens a single line document, and exits. fn bench_startup_shutdown(deno_exe: &Path) -> Result { let mut client = LspClientBuilder::new().deno_exe(deno_exe).build(); - - let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON)?; - let (_, response_error) = - client.write_request::<_, _, Value>("initialize", params)?; - assert!(response_error.is_none()); - - client.write_notification("initialized", json!({}))?; + client.initialize_default(); client.write_notification( "textDocument/didOpen", diff --git a/cli/bench/lsp_bench_standalone.rs b/cli/bench/lsp_bench_standalone.rs index a6effa185581d8..888d959ace210a 100644 --- a/cli/bench/lsp_bench_standalone.rs +++ b/cli/bench/lsp_bench_standalone.rs @@ -3,7 +3,6 @@ use deno_bench_util::bencher::benchmark_group; use deno_bench_util::bencher::benchmark_main; use deno_bench_util::bencher::Bencher; -use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use test_util::lsp::LspClient; @@ -13,15 +12,7 @@ use test_util::lsp::LspClientBuilder; // https://github.com/quick-lint/quick-lint-js/blob/35207e6616267c6c81be63f47ce97ec2452d60df/benchmark/benchmark-lsp/lsp-benchmarks.cpp#L223-L268 fn incremental_change_wait(bench: &mut Bencher) { let mut client = LspClientBuilder::new().build(); - - static FIXTURE_INIT_JSON: &[u8] = - include_bytes!("testdata/initialize_params.json"); - let params: Value = serde_json::from_slice(FIXTURE_INIT_JSON).unwrap(); - let (_, maybe_err) = client - .write_request::<_, _, Value>("initialize", params) - .unwrap(); - assert!(maybe_err.is_none()); - client.write_notification("initialized", json!({})).unwrap(); + client.initialize_default(); client .write_notification( diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 036745b6939e65..8d019502e4276f 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -14,7 +14,6 @@ use std::fs; use std::process::Stdio; use test_util::deno_cmd_with_deno_dir; use test_util::env_vars_for_npm_tests; -use test_util::http_server; use test_util::lsp::LspClient; use test_util::lsp::LspClientBuilder; use test_util::testdata_path; @@ -39,16 +38,6 @@ fn load_fixture_str(path: &str) -> String { fs::read_to_string(path).unwrap() } -fn init(init_path: &str) -> LspClient { - let test_context = TestContextBuilder::new().build(); - let mut client = test_context.new_lsp_command().build(); - client - .write_request::<_, _, Value>("initialize", load_fixture(init_path)) - .unwrap(); - client.write_notification("initialized", json!({})).unwrap(); - client -} - fn did_open( client: &mut LspClient, params: V, @@ -98,10 +87,6 @@ struct TestSession { } impl TestSession { - pub fn from_file(init_path: &str) -> Self { - Self::from_client(init(init_path)) - } - pub fn from_client(client: LspClient) -> Self { Self { client, @@ -3387,7 +3372,9 @@ fn lsp_code_actions() { #[test] fn lsp_code_actions_deno_cache() { - let mut session = TestSession::from_file("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); + let mut session = TestSession::from_client(client); let diagnostics = session.did_open(json!({ "textDocument": { "uri": "file:///a/file.ts", @@ -3418,7 +3405,9 @@ fn lsp_code_actions_deno_cache() { #[test] fn lsp_code_actions_deno_cache_npm() { - let mut session = TestSession::from_file("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); + let mut session = TestSession::from_client(client); let diagnostics = session.did_open(json!({ "textDocument": { "uri": "file:///a/file.ts", @@ -3449,7 +3438,9 @@ fn lsp_code_actions_deno_cache_npm() { #[test] fn lsp_code_actions_imports() { - let mut session = TestSession::from_file("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); + let mut session = TestSession::from_client(client); session.did_open(json!({ "textDocument": { "uri": "file:///a/file00.ts", @@ -3566,7 +3557,14 @@ fn lsp_code_actions_refactor() { #[test] fn lsp_code_actions_refactor_no_disabled_support() { - let mut client = init("initialize_params_ca_no_disabled.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize(|builder| { + builder.with_capabilities(|c| { + let doc = c.text_document.as_mut().unwrap(); + let code_action = doc.code_action.as_mut().unwrap(); + code_action.disabled_support = Some(false); + }); + }); did_open( &mut client, json!({ @@ -4150,7 +4148,13 @@ fn lsp_completions_snippet() { #[test] fn lsp_completions_no_snippet() { - let mut client = init("initialize_params_no_snippet.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize(|builder| { + builder.with_capabilities(|c| { + let doc = c.text_document.as_mut().unwrap(); + doc.completion = None; + }); + }); did_open( &mut client, json!({ @@ -5355,7 +5359,9 @@ fn lsp_diagnostics_deno_types() { #[test] fn lsp_diagnostics_refresh_dependents() { - let mut session = TestSession::from_file("initialize_params.json"); + let mut client = LspClientBuilder::new().build(); + client.initialize_default(); + let mut session = TestSession::from_client(client); session.did_open(json!({ "textDocument": { "uri": "file:///a/file_00.ts", @@ -6124,8 +6130,9 @@ fn lsp_markdown_no_diagnostics() { #[test] fn lsp_configuration_did_change() { - let _g = http_server(); - let mut client = init("initialize_params_did_config_change.json"); + let context = TestContextBuilder::new().use_http_server().build(); + let mut client = context.new_lsp_command().build(); + client.initialize_default(); did_open( &mut client, json!({ diff --git a/cli/tests/testdata/lsp/initialize_params.json b/cli/tests/testdata/lsp/initialize_params.json deleted file mode 100644 index 68735b06dee000..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "certificateStores": null, - "codeLens": { - "implementations": true, - "references": true, - "test": true - }, - "config": null, - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "testing": { - "args": [ - "--allow-all" - ], - "enable": true - }, - "tlsCertificate": null, - "unsafelyIgnoreCertificateErrors": null, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "completion": { - "completionItem": { - "snippetSupport": true - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - }, - "experimental": { - "testingApi": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_ca_no_disabled.json b/cli/tests/testdata/lsp/initialize_params_ca_no_disabled.json deleted file mode 100644 index 3df87aded3da9d..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_ca_no_disabled.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "codeLens": { - "implementations": true, - "references": true, - "test": true - }, - "config": "", - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_code_lens_test.json b/cli/tests/testdata/lsp/initialize_params_code_lens_test.json deleted file mode 100644 index bdd01bfca7902e..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_code_lens_test.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_did_config_change.json b/cli/tests/testdata/lsp/initialize_params_did_config_change.json deleted file mode 100644 index 870ad6e0f1a239..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_did_config_change.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "codeLens": { - "implementations": true, - "references": true - }, - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": { - "http://localhost:4545/": false - } - } - }, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_import_map.json b/cli/tests/testdata/lsp/initialize_params_import_map.json deleted file mode 100644 index 2ba7d28b05a457..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_import_map.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "codeLens": { - "implementations": true, - "references": true - }, - "importMap": "data:application/json;utf8,{\"imports\": { \"example\": \"https://deno.land/x/example/mod.ts\" }}", - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": { - "http://localhost:4545/": false - } - } - }, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_no_snippet.json b/cli/tests/testdata/lsp/initialize_params_no_snippet.json deleted file mode 100644 index b076f3b1759802..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_no_snippet.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": null, - "initializationOptions": { - "enable": true, - "cache": null, - "certificateStores": null, - "codeLens": { - "implementations": true, - "references": true, - "test": true - }, - "config": null, - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "testing": { - "args": [ - "--allow-all" - ], - "enable": true - }, - "tlsCertificate": null, - "unsafelyIgnoreCertificateErrors": null, - "unstable": false - }, - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - }, - "experimental": { - "testingApi": true - } - } -} diff --git a/cli/tests/testdata/lsp/initialize_params_workspace_enable_paths.json b/cli/tests/testdata/lsp/initialize_params_workspace_enable_paths.json deleted file mode 100644 index 87581ebd7d0480..00000000000000 --- a/cli/tests/testdata/lsp/initialize_params_workspace_enable_paths.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "processId": 0, - "clientInfo": { - "name": "test-harness", - "version": "1.0.0" - }, - "rootUri": "file:///project/", - "initializationOptions": { - "enable": false, - "enablePaths": [ - "./worker" - ], - "cache": null, - "certificateStores": null, - "codeLens": { - "implementations": true, - "references": true, - "test": true - }, - "config": "", - "importMap": null, - "lint": true, - "suggest": { - "autoImports": true, - "completeFunctionCalls": false, - "names": true, - "paths": true, - "imports": { - "hosts": {} - } - }, - "tlsCertificate": null, - "unsafelyIgnoreCertificateErrors": null, - "unstable": false - }, - "workspaceFolders": [ - { - "uri": "file:///project/", - "name": "project" - } - ], - "capabilities": { - "textDocument": { - "codeAction": { - "codeActionLiteralSupport": { - "codeActionKind": { - "valueSet": [ - "quickfix", - "refactor" - ] - } - }, - "isPreferredSupport": true, - "dataSupport": true, - "disabledSupport": true, - "resolveSupport": { - "properties": [ - "edit" - ] - } - }, - "foldingRange": { - "lineFoldingOnly": true - }, - "synchronization": { - "dynamicRegistration": true, - "willSave": true, - "willSaveWaitUntil": true, - "didSave": true - } - }, - "workspace": { - "configuration": true, - "workspaceFolders": true - } - } -} diff --git a/test_util/src/lsp.rs b/test_util/src/lsp.rs index 283e81d27fbda5..77d8966991a0a1 100644 --- a/test_util/src/lsp.rs +++ b/test_util/src/lsp.rs @@ -409,6 +409,14 @@ impl InitializeParamsBuilder { self } + pub fn with_capabilities( + &mut self, + mut action: impl FnMut(&mut ClientCapabilities), + ) -> &mut Self { + action(&mut self.params.capabilities); + self + } + fn initialization_options_mut( &mut self, ) -> &mut serde_json::Map { From 8949db55a6c7e2da9b85d95a5ee3b7d9ccbc3709 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 8 Mar 2023 16:49:31 -0500 Subject: [PATCH 5/9] More --- cli/tests/integration/lsp_tests.rs | 1805 +++++++++-------- .../code_action_params_import_assertion.json | 38 - .../lsp/code_action_redirect_response.json | 47 - ...code_action_response_import_assertion.json | 43 - .../lsp/code_lens_resolve_response.json | 51 - .../testdata/lsp/code_lens_response.json | 34 - .../completion_request_response_empty.json | 51 - .../completion_resolve_params_optional.json | 15 - .../completion_resolve_params_registry.json | 20 - .../completion_resolve_response_registry.json | 20 - .../lsp/completions/npm/resolve_params.json | 14 - .../lsp/completions/npm/resolve_response.json | 14 - cli/tests/testdata/lsp/did_open_lint.json | 8 - .../lsp/did_open_params_deno_types.json | 8 - .../lsp/did_open_params_doc_symbol.json | 8 - .../lsp/did_open_params_import_hover.json | 8 - .../lsp/did_open_params_semantic_tokens.json | 8 - .../lsp/did_open_params_tls_cert.json | 8 - .../lsp/document_symbol_response.json | 371 ---- .../testdata/lsp/incoming_calls_params.json | 28 - .../testdata/lsp/incoming_calls_response.json | 42 - .../testdata/lsp/outgoing_calls_params.json | 28 - .../lsp/prepare_call_hierarchy_response.json | 28 - cli/tests/testdata/lsp/rename_response.json | 38 - .../lsp/selection_range_response.json | 98 - 25 files changed, 913 insertions(+), 1920 deletions(-) delete mode 100644 cli/tests/testdata/lsp/code_action_params_import_assertion.json delete mode 100644 cli/tests/testdata/lsp/code_action_response_import_assertion.json delete mode 100644 cli/tests/testdata/lsp/code_lens_resolve_response.json delete mode 100644 cli/tests/testdata/lsp/code_lens_response.json delete mode 100644 cli/tests/testdata/lsp/completion_request_response_empty.json delete mode 100644 cli/tests/testdata/lsp/completion_resolve_params_optional.json delete mode 100644 cli/tests/testdata/lsp/completion_resolve_params_registry.json delete mode 100644 cli/tests/testdata/lsp/completion_resolve_response_registry.json delete mode 100644 cli/tests/testdata/lsp/completions/npm/resolve_params.json delete mode 100644 cli/tests/testdata/lsp/completions/npm/resolve_response.json delete mode 100644 cli/tests/testdata/lsp/did_open_lint.json delete mode 100644 cli/tests/testdata/lsp/did_open_params_deno_types.json delete mode 100644 cli/tests/testdata/lsp/did_open_params_doc_symbol.json delete mode 100644 cli/tests/testdata/lsp/did_open_params_import_hover.json delete mode 100644 cli/tests/testdata/lsp/did_open_params_semantic_tokens.json delete mode 100644 cli/tests/testdata/lsp/did_open_params_tls_cert.json delete mode 100644 cli/tests/testdata/lsp/document_symbol_response.json delete mode 100644 cli/tests/testdata/lsp/incoming_calls_params.json delete mode 100644 cli/tests/testdata/lsp/incoming_calls_response.json delete mode 100644 cli/tests/testdata/lsp/outgoing_calls_params.json delete mode 100644 cli/tests/testdata/lsp/prepare_call_hierarchy_response.json delete mode 100644 cli/tests/testdata/lsp/rename_response.json delete mode 100644 cli/tests/testdata/lsp/selection_range_response.json diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 8d019502e4276f..3e6f5fd954f53c 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -384,10 +384,7 @@ fn lsp_import_map() { "textDocument": { "uri": uri }, - "position": { - "line": 2, - "character": 12 - } + "position": { "line": 2, "character": 12 } }), ) .unwrap(); @@ -403,14 +400,8 @@ fn lsp_import_map() { "" ], "range": { - "start": { - "line": 2, - "character": 12 - }, - "end": { - "line": 2, - "character": 13 - } + "start": { "line": 2, "character": 12 }, + "end": { "line": 2, "character": 13 } } })) ); @@ -496,10 +487,7 @@ fn lsp_import_map_config_file() { "textDocument": { "uri": uri }, - "position": { - "line": 2, - "character": 12 - } + "position": { "line": 2, "character": 12 } }), ) .unwrap(); @@ -515,14 +503,8 @@ fn lsp_import_map_config_file() { "" ], "range": { - "start": { - "line": 2, - "character": 12 - }, - "end": { - "line": 2, - "character": 13 - } + "start": { "line": 2, "character": 12 }, + "end": { "line": 2, "character": 13 } } })) ); @@ -573,10 +555,7 @@ fn lsp_import_map_embedded_in_config_file() { "textDocument": { "uri": uri }, - "position": { - "line": 2, - "character": 12 - } + "position": { "line": 2, "character": 12 } }), ) .unwrap(); @@ -592,14 +571,8 @@ fn lsp_import_map_embedded_in_config_file() { "" ], "range": { - "start": { - "line": 2, - "character": 12 - }, - "end": { - "line": 2, - "character": 13 - } + "start": { "line": 2, "character": 12 }, + "end": { "line": 2, "character": 13 } } })) ); @@ -697,14 +670,8 @@ fn lsp_import_assertions() { json!([ { "range": { - "start": { - "line": 0, - "character": 14 - }, - "end": { - "line": 0, - "character": 27 - } + "start": { "line": 0, "character": 14 }, + "end": { "line": 0, "character": 27 } }, "severity": 1, "code": "no-assert-type", @@ -717,13 +684,66 @@ fn lsp_import_assertions() { let (maybe_res, maybe_err) = client .write_request( "textDocument/codeAction", - load_fixture("code_action_params_import_assertion.json"), + json!({ + "textDocument": { + "uri": "file:///a/a.ts" + }, + "range": { + "start": { "line": 0, "character": 14 }, + "end": { "line": 0, "character": 27 } + }, + "context": { + "diagnostics": [ + { + "range": { + "start": { "line": 0, "character": 14 }, + "end": { "line": 0, "character": 27 } + }, + "severity": 1, + "code": "no-assert-type", + "source": "deno", + "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement." + } + ], + "only": [ + "quickfix" + ] + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_response_import_assertion.json")) + Some(json!([{ + "title": "Insert import assertion.", + "kind": "quickfix", + "diagnostics": [ + { + "range": { + "start": { "line": 0, "character": 14 }, + "end": { "line": 0, "character": 27 } + }, + "severity": 1, + "code": "no-assert-type", + "source": "deno", + "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement." + } + ], + "edit": { + "changes": { + "file:///a/a.ts": [ + { + "range": { + "start": { "line": 0, "character": 27 }, + "end": { "line": 0, "character": 27 } + }, + "newText": " assert { type: \"json\" }" + } + ] + } + } + }])) ); client.shutdown(); } @@ -771,10 +791,7 @@ fn lsp_import_map_import_completions() { "textDocument": { "uri": uri }, - "position": { - "line": 1, - "character": 20 - }, + "position": { "line": 1, "character": 20 }, "context": { "triggerKind": 2, "triggerCharacter": "\"" @@ -843,14 +860,8 @@ fn lsp_import_map_import_completions() { "contentChanges": [ { "range": { - "start": { - "line": 1, - "character": 20 - }, - "end": { - "line": 1, - "character": 20 - } + "start": { "line": 1, "character": 20 }, + "end": { "line": 1, "character": 20 } }, "text": "/~/" } @@ -872,10 +883,7 @@ fn lsp_import_map_import_completions() { "textDocument": { "uri": uri }, - "position": { - "line": 1, - "character": 23 - }, + "position": { "line": 1, "character": 23 }, "context": { "triggerKind": 2, "triggerCharacter": "/" @@ -897,14 +905,8 @@ fn lsp_import_map_import_completions() { "filterText": "/~/b.ts", "textEdit": { "range": { - "start": { - "line": 1, - "character": 20 - }, - "end": { - "line": 1, - "character": 23 - } + "start": { "line": 1, "character": 20 }, + "end": { "line": 1, "character": 23 } }, "newText": "/~/b.ts" }, @@ -939,10 +941,7 @@ fn lsp_hover() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -959,14 +958,8 @@ fn lsp_hover() { "\n\n*@category* - Runtime Environment", ], "range": { - "start": { - "line": 0, - "character": 17 - }, - "end": { - "line": 0, - "character": 21 - } + "start": { "line": 0, "character": 17 }, + "end": { "line": 0, "character": 21 } } })) ); @@ -995,10 +988,7 @@ fn lsp_hover_asset() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 14 - } + "position": { "line": 0, "character": 14 } }), ) .unwrap(); @@ -1021,10 +1011,7 @@ fn lsp_hover_asset() { "textDocument": { "uri": "deno:/asset/lib.es2015.symbol.wellknown.d.ts" }, - "position": { - "line": 109, - "character": 13 - } + "position": { "line": 109, "character": 13 } }), ) .unwrap(); @@ -1040,14 +1027,8 @@ fn lsp_hover_asset() { "Enables basic storage and retrieval of dates and times." ], "range": { - "start": { - "line": 109, - "character": 10, - }, - "end": { - "line": 109, - "character": 14, - } + "start": { "line": 109, "character": 10, }, + "end": { "line": 109, "character": 14, } } })) ); @@ -1084,10 +1065,7 @@ fn lsp_hover_disabled() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -1141,14 +1119,8 @@ fn lsp_inlay_hints() { "uri": "file:///a/file.ts", }, "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 19, - "character": 0, - } + "start": { "line": 0, "character": 0 }, + "end": { "line": 19, "character": 0, } } }), ) @@ -1158,90 +1130,60 @@ fn lsp_inlay_hints() { json!(maybe_res), json!([ { - "position": { - "line": 0, - "character": 21 - }, + "position": { "line": 0, "character": 21 }, "label": ": string", "kind": 1, "paddingLeft": true }, { - "position": { - "line": 4, - "character": 10 - }, + "position": { "line": 4, "character": 10 }, "label": "b:", "kind": 2, "paddingRight": true }, { - "position": { - "line": 7, - "character": 11 - }, + "position": { "line": 7, "character": 11 }, "label": "= 0", "paddingLeft": true }, { - "position": { - "line": 10, - "character": 17 - }, + "position": { "line": 10, "character": 17 }, "label": "string:", "kind": 2, "paddingRight": true }, { - "position": { - "line": 10, - "character": 24 - }, + "position": { "line": 10, "character": 24 }, "label": "radix:", "kind": 2, "paddingRight": true }, { - "position": { - "line": 12, - "character": 15 - }, + "position": { "line": 12, "character": 15 }, "label": ": number", "kind": 1, "paddingLeft": true }, { - "position": { - "line": 15, - "character": 11 - }, + "position": { "line": 15, "character": 11 }, "label": ": number", "kind": 1, "paddingLeft": true }, { - "position": { - "line": 18, - "character": 18 - }, + "position": { "line": 18, "character": 18 }, "label": "callbackfn:", "kind": 2, "paddingRight": true }, { - "position": { - "line": 18, - "character": 20 - }, + "position": { "line": 18, "character": 20 }, "label": ": string", "kind": 1, "paddingLeft": true }, { - "position": { - "line": 18, - "character": 21 - }, + "position": { "line": 18, "character": 21 }, "label": ": string", "kind": 1, "paddingLeft": true @@ -1292,14 +1234,8 @@ fn lsp_inlay_hints_not_enabled() { "uri": "file:///a/file.ts", }, "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 19, - "character": 0, - } + "start": { "line": 0, "character": 0 }, + "end": { "line": 19, "character": 0, } } }), ) @@ -1395,10 +1331,7 @@ fn lsp_workspace_enable_paths() { "textDocument": { "uri": root_specifier.join("./file.ts").unwrap(), }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -1412,10 +1345,7 @@ fn lsp_workspace_enable_paths() { "textDocument": { "uri": root_specifier.join("./other/file.ts").unwrap(), }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -1429,10 +1359,7 @@ fn lsp_workspace_enable_paths() { "textDocument": { "uri": root_specifier.join("./worker/file.ts").unwrap(), }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -1448,14 +1375,8 @@ fn lsp_workspace_enable_paths() { "Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC)." ], "range": { - "start": { - "line": 0, - "character": 17, - }, - "end": { - "line": 0, - "character": 20, - } + "start": { "line": 0, "character": 17, }, + "end": { "line": 0, "character": 20, } } })) ); @@ -1467,10 +1388,7 @@ fn lsp_workspace_enable_paths() { "textDocument": { "uri": root_specifier.join("./worker/subdir/file.ts").unwrap(), }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -1486,14 +1404,8 @@ fn lsp_workspace_enable_paths() { "Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC)." ], "range": { - "start": { - "line": 0, - "character": 17, - }, - "end": { - "line": 0, - "character": 20, - } + "start": { "line": 0, "character": 17, }, + "end": { "line": 0, "character": 20, } } })) ); @@ -1523,10 +1435,7 @@ fn lsp_hover_unstable_disabled() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -1541,14 +1450,8 @@ fn lsp_hover_unstable_disabled() { } ], "range": { - "start": { - "line": 0, - "character": 17 - }, - "end": { - "line": 0, - "character": 23 - } + "start": { "line": 0, "character": 17 }, + "end": { "line": 0, "character": 23 } } })) ); @@ -1579,10 +1482,7 @@ fn lsp_hover_unstable_enabled() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -1599,14 +1499,8 @@ fn lsp_hover_unstable_enabled() { "\n\n*@category* - Runtime Environment", ], "range":{ - "start":{ - "line":0, - "character":17 - }, - "end":{ - "line":0, - "character":21 - } + "start":{ "line":0, "character":17 }, + "end":{ "line":0, "character":21 } } })) ); @@ -1639,10 +1533,7 @@ fn lsp_hover_change_mbc() { "contentChanges": [ { "range": { - "start": { - "line": 1, - "character": 11 - }, + "start": { "line": 1, "character": 11 }, "end": { "line": 1, // the LSP uses utf16 encoded characters indexes, so @@ -1669,10 +1560,7 @@ fn lsp_hover_change_mbc() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 2, - "character": 15 - } + "position": { "line": 2, "character": 15 } }), ) .unwrap(); @@ -1688,14 +1576,8 @@ fn lsp_hover_change_mbc() { "", ], "range": { - "start": { - "line": 2, - "character": 15, - }, - "end": { - "line": 2, - "character": 16, - }, + "start": { "line": 2, "character": 15, }, + "end": { "line": 2, "character": 16, }, } })) ); @@ -1766,10 +1648,7 @@ fn lsp_hover_closed_document() { "textDocument": { "uri": c_specifier, }, - "position": { - "line": 0, - "character": 10 - } + "position": { "line": 0, "character": 10 } }), ) .unwrap(); @@ -1785,14 +1664,8 @@ fn lsp_hover_closed_document() { "" ], "range": { - "start": { - "line": 0, - "character": 9 - }, - "end": { - "line": 0, - "character": 10 - } + "start": { "line": 0, "character": 9 }, + "end": { "line": 0, "character": 10 } } })) ); @@ -1813,10 +1686,7 @@ fn lsp_hover_closed_document() { "textDocument": { "uri": c_specifier, }, - "position": { - "line": 0, - "character": 10 - } + "position": { "line": 0, "character": 10 } }), ) .unwrap(); @@ -1832,14 +1702,8 @@ fn lsp_hover_closed_document() { "" ], "range": { - "start": { - "line": 0, - "character": 9 - }, - "end": { - "line": 0, - "character": 10 - } + "start": { "line": 0, "character": 9 }, + "end": { "line": 0, "character": 10 } } })) ); @@ -1864,7 +1728,14 @@ fn lsp_hover_dependency() { ); did_open( &mut client, - load_fixture("did_open_params_import_hover.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "import * as a from \"http://127.0.0.1:4545/xTypeScriptTypes.js\";\n// @deno-types=\"http://127.0.0.1:4545/type_definitions/foo.d.ts\"\nimport * as b from \"http://127.0.0.1:4545/type_definitions/foo.js\";\nimport * as c from \"http://127.0.0.1:4545/subdir/type_reference.js\";\nimport * as d from \"http://127.0.0.1:4545/subdir/mod1.ts\";\nimport * as e from \"data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=\";\nimport * as f from \"./file_01.ts\";\nimport * as g from \"http://localhost:4545/x/a/mod.ts\";\n\nconsole.log(a, b, c, d, e, f, g);\n" + } + }), ); let (maybe_res, maybe_err) = client .write_request::<_, _, Value>( @@ -1886,10 +1757,7 @@ fn lsp_hover_dependency() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 0, - "character": 28 - } + "position": { "line": 0, "character": 28 } }), ) .unwrap(); @@ -1902,14 +1770,8 @@ fn lsp_hover_dependency() { "value": "**Resolved Dependency**\n\n**Code**: http​://127.0.0.1:4545/xTypeScriptTypes.js\n\n**Types**: http​://127.0.0.1:4545/xTypeScriptTypes.d.ts\n" }, "range": { - "start": { - "line": 0, - "character": 19 - }, - "end":{ - "line": 0, - "character": 62 - } + "start": { "line": 0, "character": 19 }, + "end":{ "line": 0, "character": 62 } } })) ); @@ -1920,10 +1782,7 @@ fn lsp_hover_dependency() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 3, - "character": 28 - } + "position": { "line": 3, "character": 28 } }), ) .unwrap(); @@ -1936,14 +1795,8 @@ fn lsp_hover_dependency() { "value": "**Resolved Dependency**\n\n**Code**: http​://127.0.0.1:4545/subdir/type_reference.js\n\n**Types**: http​://127.0.0.1:4545/subdir/type_reference.d.ts\n" }, "range": { - "start": { - "line": 3, - "character": 19 - }, - "end":{ - "line": 3, - "character": 67 - } + "start": { "line": 3, "character": 19 }, + "end":{ "line": 3, "character": 67 } } })) ); @@ -1954,10 +1807,7 @@ fn lsp_hover_dependency() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 4, - "character": 28 - } + "position": { "line": 4, "character": 28 } }), ) .unwrap(); @@ -1970,14 +1820,8 @@ fn lsp_hover_dependency() { "value": "**Resolved Dependency**\n\n**Code**: http​://127.0.0.1:4545/subdir/mod1.ts\n" }, "range": { - "start": { - "line": 4, - "character": 19 - }, - "end":{ - "line": 4, - "character": 57 - } + "start": { "line": 4, "character": 19 }, + "end":{ "line": 4, "character": 57 } } })) ); @@ -1988,10 +1832,7 @@ fn lsp_hover_dependency() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 5, - "character": 28 - } + "position": { "line": 5, "character": 28 } }), ) .unwrap(); @@ -2004,14 +1845,8 @@ fn lsp_hover_dependency() { "value": "**Resolved Dependency**\n\n**Code**: _(a data url)_\n" }, "range": { - "start": { - "line": 5, - "character": 19 - }, - "end":{ - "line": 5, - "character": 132 - } + "start": { "line": 5, "character": 19 }, + "end":{ "line": 5, "character": 132 } } })) ); @@ -2022,10 +1857,7 @@ fn lsp_hover_dependency() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 6, - "character": 28 - } + "position": { "line": 6, "character": 28 } }), ) .unwrap(); @@ -2038,14 +1870,8 @@ fn lsp_hover_dependency() { "value": "**Resolved Dependency**\n\n**Code**: file​:///a/file_01.ts\n" }, "range": { - "start": { - "line": 6, - "character": 19 - }, - "end":{ - "line": 6, - "character": 33 - } + "start": { "line": 6, "character": 19 }, + "end":{ "line": 6, "character": 33 } } })) ); @@ -2086,10 +1912,7 @@ fn lsp_hover_deps_preserved_when_invalid_parse() { "textDocument": { "uri": "file:///a/file2.ts" }, - "position": { - "line": 0, - "character": 56 - } + "position": { "line": 0, "character": 56 } }), ) .unwrap(); @@ -2105,14 +1928,8 @@ fn lsp_hover_deps_preserved_when_invalid_parse() { "" ], "range": { - "start": { - "line": 0, - "character": 56, - }, - "end": { - "line": 0, - "character": 57, - } + "start": { "line": 0, "character": 56, }, + "end": { "line": 0, "character": 57, } } })) ); @@ -2127,14 +1944,8 @@ fn lsp_hover_deps_preserved_when_invalid_parse() { "contentChanges": [ { "range": { - "start": { - "line": 0, - "character": 57 - }, - "end": { - "line": 0, - "character": 58 - } + "start": { "line": 0, "character": 57 }, + "end": { "line": 0, "character": 58 } }, "text": "." } @@ -2149,10 +1960,7 @@ fn lsp_hover_deps_preserved_when_invalid_parse() { "textDocument": { "uri": "file:///a/file2.ts" }, - "position": { - "line": 0, - "character": 56 - } + "position": { "line": 0, "character": 56 } }), ) .unwrap(); @@ -2168,14 +1976,8 @@ fn lsp_hover_deps_preserved_when_invalid_parse() { "" ], "range": { - "start": { - "line": 0, - "character": 56, - }, - "end": { - "line": 0, - "character": 57, - } + "start": { "line": 0, "character": 56, }, + "end": { "line": 0, "character": 57, } } })) ); @@ -2222,10 +2024,7 @@ fn lsp_hover_typescript_types() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 24 - } + "position": { "line": 0, "character": 24 } }), ) .unwrap(); @@ -2239,14 +2038,8 @@ fn lsp_hover_typescript_types() { "value": "**Resolved Dependency**\n\n**Code**: http​://127.0.0.1:4545/xTypeScriptTypes.js\n\n**Types**: http​://127.0.0.1:4545/xTypeScriptTypes.d.ts\n" }, "range": { - "start": { - "line": 0, - "character": 19 - }, - "end": { - "line": 0, - "character": 62 - } + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 62 } } }) ); @@ -2286,10 +2079,7 @@ fn lsp_hover_jsdoc_symbol_link() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 7, - "character": 10 - } + "position": { "line": 7, "character": 10 } }), ) .unwrap(); @@ -2305,14 +2095,8 @@ fn lsp_hover_jsdoc_symbol_link() { "JSDoc [hello](file:///a/file.ts#L1,10) and [`b`](file:///a/file.ts#L5,7)" ], "range": { - "start": { - "line": 7, - "character": 9 - }, - "end": { - "line": 7, - "character": 10 - } + "start": { "line": 7, "character": 9 }, + "end": { "line": 7, "character": 10 } } })) ); @@ -2341,10 +2125,7 @@ fn lsp_goto_type_definition() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 12, - "character": 1 - } + "position": { "line": 12, "character": 1 } }), ) .unwrap(); @@ -2355,24 +2136,12 @@ fn lsp_goto_type_definition() { { "targetUri": "file:///a/file.ts", "targetRange": { - "start": { - "line": 4, - "character": 0 - }, - "end": { - "line": 9, - "character": 1 - } + "start": { "line": 4, "character": 0 }, + "end": { "line": 9, "character": 1 } }, "targetSelectionRange": { - "start": { - "line": 4, - "character": 13 - }, - "end": { - "line": 4, - "character": 14 - } + "start": { "line": 4, "character": 13 }, + "end": { "line": 4, "character": 14 } } } ])) @@ -2402,39 +2171,119 @@ fn lsp_call_hierarchy() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 5, - "character": 3 - } + "position": { "line": 5, "character": 3 } }), ) .unwrap(); assert!(maybe_error.is_none()); assert_eq!( maybe_res, - Some(load_fixture("prepare_call_hierarchy_response.json")) + Some(json!([{ + "name": "baz", + "kind": 6, + "detail": "Bar", + "uri": "file:///a/file.ts", + "range": { + "start": { "line": 5, "character": 2 }, + "end": { "line": 7, "character": 3 } + }, + "selectionRange": { + "start": { "line": 5, "character": 2 }, + "end": { "line": 5, "character": 5 } + } + }])) ); let (maybe_res, maybe_error) = client .write_request( "callHierarchy/incomingCalls", - load_fixture("incoming_calls_params.json"), + json!({ + "item": { + "name": "baz", + "kind": 6, + "detail": "Bar", + "uri": "file:///a/file.ts", + "range": { + "start": { "line": 5, "character": 2 }, + "end": { "line": 7, "character": 3 } + }, + "selectionRange": { + "start": { "line": 5, "character": 2 }, + "end": { "line": 5, "character": 5 } + } + } + }), ) .unwrap(); assert!(maybe_error.is_none()); assert_eq!( maybe_res, - Some(load_fixture("incoming_calls_response.json")) + Some(json!([{ + "from": { + "name": "main", + "kind": 12, + "detail": "", + "uri": "file:///a/file.ts", + "range": { + "start": { "line": 10, "character": 0 }, + "end": { "line": 13, "character": 1 } + }, + "selectionRange": { + "start": { "line": 10, "character": 9 }, + "end": { "line": 10, "character": 13 } + } + }, + "fromRanges": [ + { + "start": { "line": 12, "character": 6 }, + "end": { "line": 12, "character": 9 } + } + ] + }])) ); let (maybe_res, maybe_error) = client .write_request( "callHierarchy/outgoingCalls", - load_fixture("outgoing_calls_params.json"), + json!({ + "item": { + "name": "baz", + "kind": 6, + "detail": "Bar", + "uri": "file:///a/file.ts", + "range": { + "start": { "line": 5, "character": 2 }, + "end": { "line": 7, "character": 3 } + }, + "selectionRange": { + "start": { "line": 5, "character": 2 }, + "end": { "line": 5, "character": 5 } + } + } + }), ) .unwrap(); assert!(maybe_error.is_none()); assert_eq!( maybe_res, - Some(load_fixture("outgoing_calls_response.json")) + Some(json!([{ + "to": { + "name": "foo", + "kind": 12, + "detail": "", + "uri": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 2, "character": 1 } + }, + "selectionRange": { + "start": { "line": 0, "character": 9 }, + "end": { "line": 0, "character": 12 } + } + }, + "fromRanges": [{ + "start": { "line": 6, "character": 11 }, + "end": { "line": 6, "character": 14 } + }] + }])) ); client.shutdown(); } @@ -2455,14 +2304,8 @@ fn lsp_large_doc_changes() { "contentChanges": [ { "range": { - "start": { - "line": 444, - "character": 11 - }, - "end": { - "line": 444, - "character": 14 - } + "start": { "line": 444, "character": 11 }, + "end": { "line": 444, "character": 14 } }, "text": "+++" } @@ -2481,14 +2324,8 @@ fn lsp_large_doc_changes() { "contentChanges": [ { "range": { - "start": { - "line": 445, - "character": 4 - }, - "end": { - "line": 445, - "character": 4 - } + "start": { "line": 445, "character": 4 }, + "end": { "line": 445, "character": 4 } }, "text": "// " } @@ -2507,14 +2344,8 @@ fn lsp_large_doc_changes() { "contentChanges": [ { "range": { - "start": { - "line": 477, - "character": 4 - }, - "end": { - "line": 477, - "character": 9 - } + "start": { "line": 477, "character": 4 }, + "end": { "line": 477, "character": 9 } }, "text": "error" } @@ -2529,10 +2360,7 @@ fn lsp_large_doc_changes() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 421, - "character": 30 - } + "position": { "line": 421, "character": 30 } }), ) .unwrap(); @@ -2545,10 +2373,7 @@ fn lsp_large_doc_changes() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 444, - "character": 6 - } + "position": { "line": 444, "character": 6 } }), ) .unwrap(); @@ -2561,10 +2386,7 @@ fn lsp_large_doc_changes() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 461, - "character": 34 - } + "position": { "line": 461, "character": 34 } }), ) .unwrap(); @@ -2579,7 +2401,17 @@ fn lsp_large_doc_changes() { fn lsp_document_symbol() { let mut client = LspClientBuilder::new().build(); client.initialize_default(); - did_open(&mut client, load_fixture("did_open_params_doc_symbol.json")); + did_open( + &mut client, + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "interface IFoo {\n foo(): boolean;\n}\n\nclass Bar implements IFoo {\n constructor(public x: number) { }\n foo() { return true; }\n /** @deprecated */\n baz() { return false; }\n get value(): number { return 0; }\n set value(newVavlue: number) { return; }\n static staticBar = new Bar(0);\n private static getStaticBar() { return Bar.staticBar; }\n}\n\nenum Values { value1, value2 }\n\nvar bar: IFoo = new Bar(3);" + } + }), + ); let (maybe_res, maybe_err) = client .write_request( "textDocument/documentSymbol", @@ -2593,7 +2425,179 @@ fn lsp_document_symbol() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("document_symbol_response.json")) + Some(json!([{ + "name": "bar", + "kind": 13, + "range": { + "start": { "line": 17, "character": 4 }, + "end": { "line": 17, "character": 26 } + }, + "selectionRange": { + "start": { "line": 17, "character": 4 }, + "end": { "line": 17, "character": 7 } + } + }, { + "name": "Bar", + "kind": 5, + "range": { + "start": { "line": 4, "character": 0 }, + "end": { "line": 13, "character": 1 } + }, + "selectionRange": { + "start": { "line": 4, "character": 6 }, + "end": { "line": 4, "character": 9 } + }, + "children": [{ + "name": "constructor", + "kind": 9, + "range": { + "start": { "line": 5, "character": 2 }, + "end": { "line": 5, "character": 35 } + }, + "selectionRange": { + "start": { "line": 5, "character": 2 }, + "end": { "line": 5, "character": 35 } + } + }, { + "name": "baz", + "kind": 6, + "tags": [ + 1 + ], + "range": { + "start": { "line": 8, "character": 2 }, + "end": { "line": 8, "character": 25 } + }, + "selectionRange": { + "start": { "line": 8, "character": 2 }, + "end": { "line": 8, "character": 5 } + } + }, { + "name": "foo", + "kind": 6, + "range": { + "start": { "line": 6, "character": 2 }, + "end": { "line": 6, "character": 24 } + }, + "selectionRange": { + "start": { "line": 6, "character": 2 }, + "end": { "line": 6, "character": 5 } + } + }, { + "name": "getStaticBar", + "kind": 6, + "range": { + "start": { "line": 12, "character": 2 }, + "end": { "line": 12, "character": 57 } + }, + "selectionRange": { + "start": { "line": 12, "character": 17 }, + "end": { "line": 12, "character": 29 } + } + }, { + "name": "staticBar", + "kind": 8, + "range": { + "start": { "line": 11, "character": 2 }, + "end": { "line": 11, "character": 32 } + }, + "selectionRange": { + "start": { "line": 11, "character": 9 }, + "end": { "line": 11, "character": 18 } + } + }, { + "name": "(get) value", + "kind": 8, + "range": { + "start": { "line": 9, "character": 2 }, + "end": { "line": 9, "character": 35 } + }, + "selectionRange": { + "start": { "line": 9, "character": 6 }, + "end": { "line": 9, "character": 11 } + } + }, { + "name": "(set) value", + "kind": 8, + "range": { + "start": { "line": 10, "character": 2 }, + "end": { "line": 10, "character": 42 } + }, + "selectionRange": { + "start": { "line": 10, "character": 6 }, + "end": { "line": 10, "character": 11 } + } + }, { + "name": "x", + "kind": 8, + "range": { + "start": { "line": 5, "character": 14 }, + "end": { "line": 5, "character": 30 } + }, + "selectionRange": { + "start": { "line": 5, "character": 21 }, + "end": { "line": 5, "character": 22 } + } + }] + }, { + "name": "IFoo", + "kind": 11, + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 2, "character": 1 } + }, + "selectionRange": { + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 14 } + }, + "children": [{ + "name": "foo", + "kind": 6, + "range": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 17 } + }, + "selectionRange": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 5 } + } + }] + }, { + "name": "Values", + "kind": 10, + "range": { + "start": { "line": 15, "character": 0 }, + "end": { "line": 15, "character": 30 } + }, + "selectionRange": { + "start": { "line": 15, "character": 5 }, + "end": { "line": 15, "character": 11 } + }, + "children": [{ + "name": "value1", + "kind": 22, + "range": { + "start": { "line": 15, "character": 14 }, + "end": { "line": 15, "character": 20 } + }, + "selectionRange": { + "start": { "line": 15, "character": 14 }, + "end": { "line": 15, "character": 20 } + } + }, { + "name": "value2", + "kind": 22, + "range": { + "start": { "line": 15, "character": 22 }, + "end": { "line": 15, "character": 28 } + }, + "selectionRange": { + "start": { "line": 15, "character": 22 }, + "end": { "line": 15, "character": 28 } + } + }] + }] + )) ); client.shutdown(); } @@ -2626,30 +2630,24 @@ fn lsp_folding_range() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(json!([ - { - "startLine": 0, - "endLine": 12, - "kind": "region" - }, - { - "startLine": 1, - "endLine": 3, - "kind": "comment" - }, - { - "startLine": 4, - "endLine": 10 - }, - { - "startLine": 5, - "endLine": 9 - }, - { - "startLine": 6, - "endLine": 7 - } - ])) + Some(json!([{ + "startLine": 0, + "endLine": 12, + "kind": "region" + }, { + "startLine": 1, + "endLine": 3, + "kind": "comment" + }, { + "startLine": 4, + "endLine": 10 + }, { + "startLine": 5, + "endLine": 9 + }, { + "startLine": 6, + "endLine": 7 + }])) ); client.shutdown(); } @@ -2677,16 +2675,36 @@ fn lsp_rename() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 4 - }, + "position": { "line": 0, "character": 4 }, "newName": "variable_modified" }), ) .unwrap(); assert!(maybe_err.is_none()); - assert_eq!(maybe_res, Some(load_fixture("rename_response.json"))); + assert_eq!( + maybe_res, + Some(json!({ + "documentChanges": [{ + "textDocument": { + "uri": "file:///a/file.ts", + "version": 1 + }, + "edits": [{ + "range": { + "start": { "line": 0, "character": 4 }, + "end": { "line": 0, "character": 12 } + }, + "newText": "variable_modified" + }, { + "range": { + "start": { "line": 1, "character": 12 }, + "end": { "line": 1, "character": 20 } + }, + "newText": "variable_modified" + }] + }] + })) + ); client.shutdown(); } @@ -2712,19 +2730,61 @@ fn lsp_selection_range() { "textDocument": { "uri": "file:///a/file.ts" }, - "positions": [ - { - "line": 2, - "character": 8 - } - ] + "positions": [{ "line": 2, "character": 8 }] }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("selection_range_response.json")) + Some(json!([{ + "range": { + "start": { "line": 2, "character": 8 }, + "end": { "line": 2, "character": 9 } + }, + "parent": { + "range": { + "start": { "line": 2, "character": 8 }, + "end": { "line": 2, "character": 15 } + }, + "parent": { + "range": { + "start": { "line": 2, "character": 4 }, + "end": { "line": 4, "character": 5 } + }, + "parent": { + "range": { + "start": { "line": 1, "character": 13 }, + "end": { "line": 6, "character": 2 } + }, + "parent": { + "range": { + "start": { "line": 1, "character": 12 }, + "end": { "line": 6, "character": 3 } + }, + "parent": { + "range": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 6, "character": 3 } + }, + "parent": { + "range": { + "start": { "line": 0, "character": 11 }, + "end": { "line": 7, "character": 0 } + }, + "parent": { + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 7, "character": 1 } + } + } + } + } + } + } + } + } + }])) ); client.shutdown(); } @@ -2735,7 +2795,14 @@ fn lsp_semantic_tokens() { client.initialize_default(); did_open( &mut client, - load_fixture("did_open_params_semantic_tokens.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "enum Values { value1, value2 }\n\nasync function baz(s: string): Promise {\n const r = s.slice(0);\n return r;\n}\n\ninterface IFoo {\n readonly x: number;\n foo(): boolean;\n}\n\nclass Bar implements IFoo {\n constructor(public readonly x: number) { }\n foo() { return true; }\n static staticBar = new Bar(0);\n private static getStaticBar() { return Bar.staticBar; }\n}\n" + } + }), ); let (maybe_res, maybe_err) = client .write_request( @@ -2768,14 +2835,8 @@ fn lsp_semantic_tokens() { "uri": "file:///a/file.ts" }, "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 6, - "character": 0 - } + "start": { "line": 0, "character": 0 }, + "end": { "line": 6, "character": 0 } } }), ) @@ -2820,20 +2881,35 @@ fn lsp_code_lens() { ) .unwrap(); assert!(maybe_err.is_none()); - assert_eq!(maybe_res, Some(load_fixture("code_lens_response.json"))); + assert_eq!( + maybe_res, + Some(json!([{ + "range": { + "start": { "line": 0, "character": 6 }, + "end": { "line": 0, "character": 7 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }, { + "range": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 3 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }])) + ); let (maybe_res, maybe_err) = client .write_request( "codeLens/resolve", json!({ "range": { - "start": { - "line": 0, - "character": 6 - }, - "end": { - "line": 0, - "character": 7 - } + "start": { "line": 0, "character": 6 }, + "end": { "line": 0, "character": 7 } }, "data": { "specifier": "file:///a/file.ts", @@ -2845,7 +2921,33 @@ fn lsp_code_lens() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_lens_resolve_response.json")) + Some(json!({ + "range": { + "start": { "line": 0, "character": 6 }, + "end": { "line": 0, "character": 7 } + }, + "command": { + "title": "2 references", + "command": "deno.showReferences", + "arguments": [ + "file:///a/file.ts", + { "line": 0, "character": 6 }, + [{ + "uri": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 6 }, + "end": { "line": 0, "character": 7 } + } + }, { + "uri": "file:///a/file.ts", + "range": { + "start": { "line": 12, "character": 14 }, + "end": { "line": 12, "character": 15 } + } + }] + ] + } + })) ); client.shutdown(); } @@ -2885,14 +2987,8 @@ fn lsp_code_lens_impl() { "codeLens/resolve", json!({ "range": { - "start": { - "line": 0, - "character": 10 - }, - "end": { - "line": 0, - "character": 11 - } + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 11 } }, "data": { "specifier": "file:///a/file.ts", @@ -2911,14 +3007,8 @@ fn lsp_code_lens_impl() { "codeLens/resolve", json!({ "range": { - "start": { - "line": 10, - "character": 10 - }, - "end": { - "line": 10, - "character": 11 - } + "start": { "line": 10, "character": 10 }, + "end": { "line": 10, "character": 11 } }, "data": { "specifier": "file:///a/file.ts", @@ -2932,14 +3022,8 @@ fn lsp_code_lens_impl() { maybe_res, Some(json!({ "range": { - "start": { - "line": 10, - "character": 10 - }, - "end": { - "line": 10, - "character": 11 - } + "start": { "line": 10, "character": 10 }, + "end": { "line": 10, "character": 11 } }, "command": { "title": "0 implementations", @@ -3052,10 +3136,7 @@ fn lsp_code_lens_non_doc_nav_tree() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 3 - }, + "position": { "line": 0, "character": 3 }, "context": { "includeDeclaration": true } @@ -3095,14 +3176,8 @@ fn lsp_code_lens_non_doc_nav_tree() { "codeLens/resolve", json!({ "range": { - "start": { - "line": 416, - "character": 12 - }, - "end": { - "line": 416, - "character": 19 - } + "start": { "line": 416, "character": 12 }, + "end": { "line": 416, "character": 19 } }, "data": { "specifier": "asset:///lib.deno.shared_globals.d.ts", @@ -3157,14 +3232,8 @@ fn lsp_nav_tree_updates() { "contentChanges": [ { "range": { - "start": { - "line": 10, - "character": 0 - }, - "end": { - "line": 13, - "character": 0 - } + "start": { "line": 10, "character": 0 }, + "end": { "line": 13, "character": 0 } }, "text": "" } @@ -3212,10 +3281,7 @@ fn lsp_signature_help() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "character": 4, - "line": 9 - }, + "position": { "character": 4, "line": 9 }, "context": { "triggerKind": 2, "triggerCharacter": "(", @@ -3268,14 +3334,8 @@ fn lsp_signature_help() { "contentChanges": [ { "range": { - "start": { - "line": 9, - "character": 4 - }, - "end": { - "line": 9, - "character": 4 - } + "start": { "line": 9, "character": 4 }, + "end": { "line": 9, "character": 4 } }, "text": "123, " } @@ -3290,10 +3350,7 @@ fn lsp_signature_help() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "character": 8, - "line": 9 - } + "position": { "character": 8, "line": 9 } }), ) .unwrap(); @@ -3584,14 +3641,8 @@ fn lsp_code_actions_refactor_no_disabled_support() { "uri": "file:///a/file.ts" }, "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 14, - "character": 0 - } + "start": { "line": 0, "character": 0 }, + "end": { "line": 14, "character": 0 } }, "context": { "diagnostics": [], @@ -3649,14 +3700,8 @@ fn lsp_code_actions_deadlock() { "contentChanges": [ { "range": { - "start": { - "line": 444, - "character": 11 - }, - "end": { - "line": 444, - "character": 14 - } + "start": { "line": 444, "character": 11 }, + "end": { "line": 444, "character": 14 } }, "text": "+++" } @@ -3675,14 +3720,8 @@ fn lsp_code_actions_deadlock() { "contentChanges": [ { "range": { - "start": { - "line": 445, - "character": 4 - }, - "end": { - "line": 445, - "character": 4 - } + "start": { "line": 445, "character": 4 }, + "end": { "line": 445, "character": 4 } }, "text": "// " } @@ -3701,14 +3740,8 @@ fn lsp_code_actions_deadlock() { "contentChanges": [ { "range": { - "start": { - "line": 477, - "character": 4 - }, - "end": { - "line": 477, - "character": 9 - } + "start": { "line": 477, "character": 4 }, + "end": { "line": 477, "character": 9 } }, "text": "error" } @@ -3727,10 +3760,7 @@ fn lsp_code_actions_deadlock() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 609, - "character": 33, - } + "position": { "line": 609, "character": 33, } }), ) .unwrap(); @@ -3772,10 +3802,7 @@ fn lsp_completions() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 5 - }, + "position": { "line": 0, "character": 5 }, "context": { "triggerKind": 2, "triggerCharacter": "." @@ -3826,10 +3853,7 @@ fn lsp_completions_private_fields() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 57 - }, + "position": { "line": 0, "character": 57 }, "context": { "triggerKind": 1 } @@ -3897,7 +3921,21 @@ fn lsp_completions_optional() { let (maybe_res, maybe_err) = client .write_request( "completionItem/resolve", - load_fixture("completion_resolve_params_optional.json"), + json!({ + "label": "b?", + "kind": 5, + "sortText": "1", + "filterText": "b", + "insertText": "b", + "data": { + "tsc": { + "specifier": "file:///a/file.ts", + "position": 79, + "name": "b", + "useCodeSnippet": false + } + } + }), ) .unwrap(); assert!(maybe_err.is_none()); @@ -3952,10 +3990,7 @@ fn lsp_completions_auto_import() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 2, - "character": 0, - }, + "position": { "line": 2, "character": 0, }, "context": { "triggerKind": 1, } @@ -4016,14 +4051,8 @@ fn lsp_completions_auto_import() { "additionalTextEdits": [ { "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 0, - "character": 0 - } + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } }, "newText": "import { foo } from \"./b.ts\";\n\n" } @@ -4054,10 +4083,7 @@ fn lsp_completions_snippet() { "textDocument": { "uri": "file:///a/a.tsx" }, - "position": { - "line": 5, - "character": 13, - }, + "position": { "line": 5, "character": 13, }, "context": { "triggerKind": 1, } @@ -4173,10 +4199,7 @@ fn lsp_completions_no_snippet() { "textDocument": { "uri": "file:///a/a.tsx" }, - "position": { - "line": 5, - "character": 13, - }, + "position": { "line": 5, "character": 13, }, "context": { "triggerKind": 1, } @@ -4267,14 +4290,8 @@ fn lsp_completions_npm() { "contentChanges": [ { "range": { - "start": { - "line": 2, - "character": 0 - }, - "end": { - "line": 2, - "character": 0 - } + "start": { "line": 2, "character": 0 }, + "end": { "line": 2, "character": 0 } }, "text": "cjsDefault." } @@ -4291,10 +4308,7 @@ fn lsp_completions_npm() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 2, - "character": 11 - }, + "position": { "line": 2, "character": 11 }, "context": { "triggerKind": 2, "triggerCharacter": "." @@ -4314,13 +4328,39 @@ fn lsp_completions_npm() { let (maybe_res, maybe_err) = client .write_request( "completionItem/resolve", - load_fixture("completions/npm/resolve_params.json"), + json!({ + "label": "MyClass", + "kind": 6, + "sortText": "1", + "insertTextFormat": 1, + "data": { + "tsc": { + "specifier": "file:///a/file.ts", + "position": 69, + "name": "MyClass", + "useCodeSnippet": false + } + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("completions/npm/resolve_response.json")) + Some(json!({ + "label": "MyClass", + "kind": 6, + "sortText": "1", + "insertTextFormat": 1, + "data": { + "tsc": { + "specifier": "file:///a/file.ts", + "position": 69, + "name": "MyClass", + "useCodeSnippet": false + } + } + })) ); // now check chalk, which is esm @@ -4335,14 +4375,8 @@ fn lsp_completions_npm() { "contentChanges": [ { "range": { - "start": { - "line": 2, - "character": 0 - }, - "end": { - "line": 2, - "character": 11 - } + "start": { "line": 2, "character": 0 }, + "end": { "line": 2, "character": 11 } }, "text": "chalk." } @@ -4359,10 +4393,7 @@ fn lsp_completions_npm() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 2, - "character": 6 - }, + "position": { "line": 2, "character": 6 }, "context": { "triggerKind": 2, "triggerCharacter": "." @@ -4441,14 +4472,8 @@ fn lsp_npm_specifier_unopened_file() { "contentChanges": [ { "range": { - "start": { - "line": 2, - "character": 0 - }, - "end": { - "line": 2, - "character": 0 - } + "start": { "line": 2, "character": 0 }, + "end": { "line": 2, "character": 0 } }, "text": "chalk." } @@ -4466,10 +4491,7 @@ fn lsp_npm_specifier_unopened_file() { "textDocument": { "uri": main_url }, - "position": { - "line": 2, - "character": 6 - }, + "position": { "line": 2, "character": 6 }, "context": { "triggerKind": 2, "triggerCharacter": "." @@ -4763,10 +4785,7 @@ fn lsp_completions_registry() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 46 - }, + "position": { "line": 0, "character": 46 }, "context": { "triggerKind": 2, "triggerCharacter": "@" @@ -4784,13 +4803,39 @@ fn lsp_completions_registry() { let (maybe_res, maybe_err) = client .write_request( "completionItem/resolve", - load_fixture("completion_resolve_params_registry.json"), + json!({ + "label": "v2.0.0", + "kind": 19, + "detail": "(version)", + "sortText": "0000000003", + "filterText": "http://localhost:4545/x/a@v2.0.0", + "textEdit": { + "range": { + "start": { "line": 0, "character": 20 }, + "end": { "line": 0, "character": 46 } + }, + "newText": "http://localhost:4545/x/a@v2.0.0" + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("completion_resolve_response_registry.json")) + Some(json!({ + "label": "v2.0.0", + "kind": 19, + "detail": "(version)", + "sortText": "0000000003", + "filterText": "http://localhost:4545/x/a@v2.0.0", + "textEdit": { + "range": { + "start": { "line": 0, "character": 20 }, + "end": { "line": 0, "character": 46 } + }, + "newText": "http://localhost:4545/x/a@v2.0.0" + } + })) ); client.shutdown(); } @@ -4820,10 +4865,7 @@ fn lsp_completions_registry_empty() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 20 - }, + "position": { "line": 0, "character": 20 }, "context": { "triggerKind": 2, "triggerCharacter": "\"" @@ -4834,7 +4876,37 @@ fn lsp_completions_registry_empty() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("completion_request_response_empty.json")) + Some(json!({ + "isIncomplete": false, + "items": [{ + "label": ".", + "kind": 19, + "detail": "(local)", + "sortText": "1", + "insertText": ".", + "commitCharacters": ["\"", "'"] + }, { + "label": "..", + "kind": 19, + "detail": "(local)", + "sortText": "1", + "insertText": "..", + "commitCharacters": ["\"", "'" ] + }, { + "label": "http://localhost:4545", + "kind": 19, + "detail": "(registry)", + "sortText": "2", + "textEdit": { + "range": { + "start": { "line": 0, "character": 20 }, + "end": { "line": 0, "character": 20 } + }, + "newText": "http://localhost:4545" + }, + "commitCharacters": ["\"", "'", "/"] + }] + })) ); client.shutdown(); } @@ -4862,10 +4934,7 @@ fn lsp_auto_discover_registry() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 46 - }, + "position": { "line": 0, "character": 46 }, "context": { "triggerKind": 2, "triggerCharacter": "@" @@ -4906,7 +4975,14 @@ fn lsp_cache_location() { } })); let diagnostics = - session.did_open(load_fixture("did_open_params_import_hover.json")); + session.did_open(json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "import * as a from \"http://127.0.0.1:4545/xTypeScriptTypes.js\";\n// @deno-types=\"http://127.0.0.1:4545/type_definitions/foo.d.ts\"\nimport * as b from \"http://127.0.0.1:4545/type_definitions/foo.js\";\nimport * as c from \"http://127.0.0.1:4545/subdir/type_reference.js\";\nimport * as d from \"http://127.0.0.1:4545/subdir/mod1.ts\";\nimport * as e from \"data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=\";\nimport * as f from \"./file_01.ts\";\nimport * as g from \"http://localhost:4545/x/a/mod.ts\";\n\nconsole.log(a, b, c, d, e, f, g);\n" + } + })); assert_eq!(diagnostics.viewed().len(), 7); let (maybe_res, maybe_err) = session .client @@ -4930,10 +5006,7 @@ fn lsp_cache_location() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 0, - "character": 28 - } + "position": { "line": 0, "character": 28 } }), ) .unwrap(); @@ -4946,14 +5019,8 @@ fn lsp_cache_location() { "value": "**Resolved Dependency**\n\n**Code**: http​://127.0.0.1:4545/xTypeScriptTypes.js\n\n**Types**: http​://127.0.0.1:4545/xTypeScriptTypes.d.ts\n" }, "range": { - "start": { - "line": 0, - "character": 19 - }, - "end":{ - "line": 0, - "character": 62 - } + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 62 } } })) ); @@ -4965,10 +5032,7 @@ fn lsp_cache_location() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 7, - "character": 28 - } + "position": { "line": 7, "character": 28 } }), ) .unwrap(); @@ -4981,14 +5045,8 @@ fn lsp_cache_location() { "value": "**Resolved Dependency**\n\n**Code**: http​://localhost:4545/x/a/mod.ts\n\n\n---\n\n**a**\n\nmod.ts" }, "range": { - "start": { - "line": 7, - "character": 19 - }, - "end": { - "line": 7, - "character": 53 - } + "start": { "line": 7, "character": 19 }, + "end": { "line": 7, "character": 53 } } })) ); @@ -5024,8 +5082,14 @@ fn lsp_tls_cert() { "text": "export const a = \"a\";\n", } })); - let diagnostics = - session.did_open(load_fixture("did_open_params_tls_cert.json")); + let diagnostics = session.did_open(json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "import * as a from \"https://localhost:5545/xTypeScriptTypes.js\";\n// @deno-types=\"https://localhost:5545/type_definitions/foo.d.ts\"\nimport * as b from \"https://localhost:5545/type_definitions/foo.js\";\nimport * as c from \"https://localhost:5545/subdir/type_reference.js\";\nimport * as d from \"https://localhost:5545/subdir/mod1.ts\";\nimport * as e from \"data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=\";\nimport * as f from \"./file_01.ts\";\nimport * as g from \"http://localhost:4545/x/a/mod.ts\";\n\nconsole.log(a, b, c, d, e, f, g);\n" + } + })); let diagnostics = diagnostics.viewed(); assert_eq!(diagnostics.len(), 7); let (maybe_res, maybe_err) = session @@ -5050,10 +5114,7 @@ fn lsp_tls_cert() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 0, - "character": 28 - } + "position": { "line": 0, "character": 28 } }), ) .unwrap(); @@ -5066,14 +5127,8 @@ fn lsp_tls_cert() { "value": "**Resolved Dependency**\n\n**Code**: https​://localhost:5545/xTypeScriptTypes.js\n" }, "range": { - "start": { - "line": 0, - "character": 19 - }, - "end":{ - "line": 0, - "character": 63 - } + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 63 } } })) ); @@ -5085,10 +5140,7 @@ fn lsp_tls_cert() { "textDocument": { "uri": "file:///a/file.ts", }, - "position": { - "line": 7, - "character": 28 - } + "position": { "line": 7, "character": 28 } }), ) .unwrap(); @@ -5101,14 +5153,8 @@ fn lsp_tls_cert() { "value": "**Resolved Dependency**\n\n**Code**: http​://localhost:4545/x/a/mod.ts\n\n\n---\n\n**a**\n\nmod.ts" }, "range": { - "start": { - "line": 7, - "character": 19 - }, - "end": { - "line": 7, - "character": 53 - } + "start": { "line": 7, "character": 19 }, + "end": { "line": 7, "character": 53 } } })) ); @@ -5240,14 +5286,8 @@ fn lsp_redirect_quick_fix() { "uri": "file:///a/file.ts" }, "range": { - "start": { - "line": 0, - "character": 19 - }, - "end": { - "line": 0, - "character": 60 - } + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 60 } }, "context": { "diagnostics": diagnostics, @@ -5261,7 +5301,39 @@ fn lsp_redirect_quick_fix() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_redirect_response.json")) + Some(json!([{ + "title": "Update specifier to its redirected specifier.", + "kind": "quickfix", + "diagnostics": [ + { + "range": { + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 60 } + }, + "severity": 3, + "code": "redirect", + "source": "deno", + "message": "The import of \"http://127.0.0.1:4545/x_deno_warning.js\" was redirected to \"http://127.0.0.1:4545/lsp/x_deno_warning_redirect.js\".", + "data": { + "specifier": "http://127.0.0.1:4545/x_deno_warning.js", + "redirect": "http://127.0.0.1:4545/lsp/x_deno_warning_redirect.js" + } + } + ], + "edit": { + "changes": { + "file:///a/file.ts": [ + { + "range": { + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 60 } + }, + "newText": "\"http://127.0.0.1:4545/lsp/x_deno_warning_redirect.js\"" + } + ] + } + } + }])) ); client.shutdown(); } @@ -5299,14 +5371,8 @@ fn lsp_diagnostics_deprecated() { "diagnostics": [ { "range": { - "start": { - "line": 3, - "character": 0 - }, - "end": { - "line": 3, - "character": 1 - } + "start": { "line": 3, "character": 0 }, + "end": { "line": 3, "character": 1 } }, "severity": 4, "code": 6385, @@ -5332,7 +5398,14 @@ fn lsp_diagnostics_deno_types() { client .write_notification( "textDocument/didOpen", - load_fixture("did_open_params_deno_types.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "/// \n/// ().unwrap(); @@ -5393,14 +5466,8 @@ fn lsp_diagnostics_refresh_dependents() { "diagnostics": [ { "range": { - "start": { - "line": 0, - "character": 12 - }, - "end": { - "line": 0, - "character": 13 - } + "start": { "line": 0, "character": 12 }, + "end": { "line": 0, "character": 13 } }, "severity": 1, "code": 2305, @@ -5425,14 +5492,8 @@ fn lsp_diagnostics_refresh_dependents() { "contentChanges": [ { "range": { - "start": { - "line": 1, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } + "start": { "line": 1, "character": 0 }, + "end": { "line": 1, "character": 0 } }, "text": "export const b = \"b\";\n" } @@ -5483,10 +5544,7 @@ fn lsp_performance() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 19 - } + "position": { "line": 0, "character": 19 } }), ) .unwrap(); @@ -5773,14 +5831,8 @@ fn lsp_format_json() { Some(json!([ { "range": { - "start": { - "line": 0, - "character": 1 - }, - "end": { - "line": 0, - "character": 1 - } + "start": { "line": 0, "character": 1 }, + "end": { "line": 0, "character": 1 } }, "newText": " " }, @@ -5841,10 +5893,7 @@ fn lsp_json_no_diagnostics() { "textDocument": { "uri": "file:///a/file.json" }, - "position": { - "line": 0, - "character": 3 - } + "position": { "line": 0, "character": 3 } }), ) .unwrap(); @@ -5970,105 +6019,57 @@ fn lsp_format_with_config() { maybe_res, Some(json!([{ "range": { - "start": { - "line": 1, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } + "start": { "line": 1, "character": 0 }, + "end": { "line": 1, "character": 0 } }, "newText": "\t" }, { "range": { - "start": { - "line": 1, - "character": 23 - }, - "end": { - "line": 1, - "character": 24 - } + "start": { "line": 1, "character": 23 }, + "end": { "line": 1, "character": 24 } }, "newText": "\n\t\t'" }, { "range": { - "start": { - "line": 1, - "character": 73 - }, - "end": { - "line": 1, - "character": 74 - } + "start": { "line": 1, "character": 73 }, + "end": { "line": 1, "character": 74 } }, "newText": "',\n\t" }, { "range": { - "start": { - "line": 2, - "character": 0 - }, - "end": { - "line": 2, - "character": 0 - } + "start": { "line": 2, "character": 0 }, + "end": { "line": 2, "character": 0 } }, "newText": "\t" }, { "range": { - "start": { - "line": 3, - "character": 0 - }, - "end": { - "line": 3, - "character": 0 - } + "start": { "line": 3, "character": 0 }, + "end": { "line": 3, "character": 0 } }, "newText": "\t" }, { "range": { - "start": { - "line": 3, - "character": 12 - }, - "end": { - "line": 3, - "character": 13 - } + "start": { "line": 3, "character": 12 }, + "end": { "line": 3, "character": 13 } }, "newText": "'" }, { "range": { - "start": { - "line": 3, - "character": 22 - }, - "end": { - "line": 3, - "character": 24 - } + "start": { "line": 3, "character": 22 }, + "end": { "line": 3, "character": 24 } }, "newText": "');" }, { "range": { - "start": { - "line": 4, - "character": 1 - }, - "end": { - "line": 4, - "character": 1 - } + "start": { "line": 4, "character": 1 }, + "end": { "line": 4, "character": 1 } }, "newText": "\n" }] @@ -6115,10 +6116,7 @@ fn lsp_markdown_no_diagnostics() { "textDocument": { "uri": "file:///a/file.md" }, - "position": { - "line": 0, - "character": 3 - } + "position": { "line": 0, "character": 3 } }), ) .unwrap(); @@ -6187,10 +6185,7 @@ fn lsp_configuration_did_change() { "textDocument": { "uri": "file:///a/file.ts" }, - "position": { - "line": 0, - "character": 46 - }, + "position": { "line": 0, "character": 46 }, "context": { "triggerKind": 2, "triggerCharacter": "@" @@ -6208,13 +6203,39 @@ fn lsp_configuration_did_change() { let (maybe_res, maybe_err) = client .write_request( "completionItem/resolve", - load_fixture("completion_resolve_params_registry.json"), + json!({ + "label": "v2.0.0", + "kind": 19, + "detail": "(version)", + "sortText": "0000000003", + "filterText": "http://localhost:4545/x/a@v2.0.0", + "textEdit": { + "range": { + "start": { "line": 0, "character": 20 }, + "end": { "line": 0, "character": 46 } + }, + "newText": "http://localhost:4545/x/a@v2.0.0" + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("completion_resolve_response_registry.json")) + Some(json!({ + "label": "v2.0.0", + "kind": 19, + "detail": "(version)", + "sortText": "0000000003", + "filterText": "http://localhost:4545/x/a@v2.0.0", + "textEdit": { + "range": { + "start": { "line": 0, "character": 20 }, + "end": { "line": 0, "character": 46 } + }, + "newText": "http://localhost:4545/x/a@v2.0.0" + } + })) ); client.shutdown(); } @@ -6263,14 +6284,8 @@ fn lsp_workspace_symbol() { "location": { "uri": "file:///a/file.ts", "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 17 - } + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 17 } } }, "containerName": "A" @@ -6281,14 +6296,8 @@ fn lsp_workspace_symbol() { "location": { "uri": "file:///a/file.ts", "range": { - "start": { - "line": 2, - "character": 2 - }, - "end": { - "line": 2, - "character": 17 - } + "start": { "line": 2, "character": 2 }, + "end": { "line": 2, "character": 17 } } }, "containerName": "A" @@ -6299,14 +6308,8 @@ fn lsp_workspace_symbol() { "location": { "uri": "file:///a/file_01.ts", "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 17 - } + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 17 } } }, "containerName": "B" @@ -6317,14 +6320,8 @@ fn lsp_workspace_symbol() { "location": { "uri": "file:///a/file_01.ts", "range": { - "start": { - "line": 2, - "character": 2 - }, - "end": { - "line": 2, - "character": 17 - } + "start": { "line": 2, "character": 2 }, + "end": { "line": 2, "character": 17 } } }, "containerName": "B" @@ -6352,7 +6349,33 @@ fn lsp_code_actions_ignore_lint() { let (maybe_res, maybe_err) = client .write_request( "textDocument/codeAction", - load_fixture("code_action_ignore_lint_params.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "range": { + "start": { "line": 1, "character": 5 }, + "end": { "line": 1, "character": 12 } + }, + "context": { + "diagnostics": [ + { + "range": { + "start": { "line": 1, "character": 5 }, + "end": { "line": 1, "character": 12 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'message' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + } + ], + "only": [ + "quickfix" + ] + } + }), ) .unwrap(); assert!(maybe_err.is_none()); @@ -6428,7 +6451,14 @@ fn lsp_lint_with_config() { let mut session = TestSession::from_client(client); - let diagnostics = session.did_open(load_fixture("did_open_lint.json")); + let diagnostics = session.did_open(json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "// TODO: fixme\nexport async function non_camel_case() {\nconsole.log(\"finished!\")\n}" + } + })); let diagnostics = diagnostics.viewed(); assert_eq!(diagnostics.len(), 1); assert_eq!( @@ -6539,10 +6569,7 @@ export function B() { "textDocument": { "uri": "file:///a/file.tsx" }, - "position": { - "line": 0, - "character": 25 - } + "position": { "line": 0, "character": 25 } }), ) .unwrap(); @@ -6555,14 +6582,8 @@ export function B() { "value": "**Resolved Dependency**\n\n**Code**: http​://localhost:4545/jsx/jsx-runtime\n", }, "range": { - "start": { - "line": 0, - "character": 21 - }, - "end": { - "line": 0, - "character": 46 - } + "start": { "line": 0, "character": 21 }, + "end": { "line": 0, "character": 46 } } })) ); diff --git a/cli/tests/testdata/lsp/code_action_params_import_assertion.json b/cli/tests/testdata/lsp/code_action_params_import_assertion.json deleted file mode 100644 index 67b822a424400e..00000000000000 --- a/cli/tests/testdata/lsp/code_action_params_import_assertion.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/a.ts" - }, - "range": { - "start": { - "line": 0, - "character": 14 - }, - "end": { - "line": 0, - "character": 27 - } - }, - "context": { - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 14 - }, - "end": { - "line": 0, - "character": 27 - } - }, - "severity": 1, - "code": "no-assert-type", - "source": "deno", - "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement." - } - ], - "only": [ - "quickfix" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_action_redirect_response.json b/cli/tests/testdata/lsp/code_action_redirect_response.json index 2351275703989d..e69de29bb2d1d6 100644 --- a/cli/tests/testdata/lsp/code_action_redirect_response.json +++ b/cli/tests/testdata/lsp/code_action_redirect_response.json @@ -1,47 +0,0 @@ -[ - { - "title": "Update specifier to its redirected specifier.", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 19 - }, - "end": { - "line": 0, - "character": 60 - } - }, - "severity": 3, - "code": "redirect", - "source": "deno", - "message": "The import of \"http://127.0.0.1:4545/x_deno_warning.js\" was redirected to \"http://127.0.0.1:4545/lsp/x_deno_warning_redirect.js\".", - "data": { - "specifier": "http://127.0.0.1:4545/x_deno_warning.js", - "redirect": "http://127.0.0.1:4545/lsp/x_deno_warning_redirect.js" - } - } - ], - "edit": { - "changes": { - "file:///a/file.ts": [ - { - "range": { - "start": { - "line": 0, - "character": 19 - }, - "end": { - "line": 0, - "character": 60 - } - }, - "newText": "\"http://127.0.0.1:4545/lsp/x_deno_warning_redirect.js\"" - } - ] - } - } - } -] diff --git a/cli/tests/testdata/lsp/code_action_response_import_assertion.json b/cli/tests/testdata/lsp/code_action_response_import_assertion.json deleted file mode 100644 index bff934b215d0a7..00000000000000 --- a/cli/tests/testdata/lsp/code_action_response_import_assertion.json +++ /dev/null @@ -1,43 +0,0 @@ -[ - { - "title": "Insert import assertion.", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 14 - }, - "end": { - "line": 0, - "character": 27 - } - }, - "severity": 1, - "code": "no-assert-type", - "source": "deno", - "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement." - } - ], - "edit": { - "changes": { - "file:///a/a.ts": [ - { - "range": { - "start": { - "line": 0, - "character": 27 - }, - "end": { - "line": 0, - "character": 27 - } - }, - "newText": " assert { type: \"json\" }" - } - ] - } - } - } -] diff --git a/cli/tests/testdata/lsp/code_lens_resolve_response.json b/cli/tests/testdata/lsp/code_lens_resolve_response.json deleted file mode 100644 index a958b4db4d00cd..00000000000000 --- a/cli/tests/testdata/lsp/code_lens_resolve_response.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "range": { - "start": { - "line": 0, - "character": 6 - }, - "end": { - "line": 0, - "character": 7 - } - }, - "command": { - "title": "2 references", - "command": "deno.showReferences", - "arguments": [ - "file:///a/file.ts", - { - "line": 0, - "character": 6 - }, - [ - { - "uri": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 6 - }, - "end": { - "line": 0, - "character": 7 - } - } - }, - { - "uri": "file:///a/file.ts", - "range": { - "start": { - "line": 12, - "character": 14 - }, - "end": { - "line": 12, - "character": 15 - } - } - } - ] - ] - } -} diff --git a/cli/tests/testdata/lsp/code_lens_response.json b/cli/tests/testdata/lsp/code_lens_response.json deleted file mode 100644 index e3a87e4be631e3..00000000000000 --- a/cli/tests/testdata/lsp/code_lens_response.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "range": { - "start": { - "line": 0, - "character": 6 - }, - "end": { - "line": 0, - "character": 7 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "references" - } - }, - { - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 3 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "references" - } - } -] diff --git a/cli/tests/testdata/lsp/completion_request_response_empty.json b/cli/tests/testdata/lsp/completion_request_response_empty.json deleted file mode 100644 index 9ece16e909606d..00000000000000 --- a/cli/tests/testdata/lsp/completion_request_response_empty.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "isIncomplete": false, - "items": [ - { - "label": ".", - "kind": 19, - "detail": "(local)", - "sortText": "1", - "insertText": ".", - "commitCharacters": [ - "\"", - "'" - ] - }, - { - "label": "..", - "kind": 19, - "detail": "(local)", - "sortText": "1", - "insertText": "..", - "commitCharacters": [ - "\"", - "'" - ] - }, - { - "label": "http://localhost:4545", - "kind": 19, - "detail": "(registry)", - "sortText": "2", - "textEdit": { - "range": { - "start": { - "line": 0, - "character": 20 - }, - "end": { - "line": 0, - "character": 20 - } - }, - "newText": "http://localhost:4545" - }, - "commitCharacters": [ - "\"", - "'", - "/" - ] - } - ] -} diff --git a/cli/tests/testdata/lsp/completion_resolve_params_optional.json b/cli/tests/testdata/lsp/completion_resolve_params_optional.json deleted file mode 100644 index cb99bf960cc030..00000000000000 --- a/cli/tests/testdata/lsp/completion_resolve_params_optional.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "label": "b?", - "kind": 5, - "sortText": "1", - "filterText": "b", - "insertText": "b", - "data": { - "tsc": { - "specifier": "file:///a/file.ts", - "position": 79, - "name": "b", - "useCodeSnippet": false - } - } -} diff --git a/cli/tests/testdata/lsp/completion_resolve_params_registry.json b/cli/tests/testdata/lsp/completion_resolve_params_registry.json deleted file mode 100644 index 99a4a048e2646e..00000000000000 --- a/cli/tests/testdata/lsp/completion_resolve_params_registry.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "label": "v2.0.0", - "kind": 19, - "detail": "(version)", - "sortText": "0000000003", - "filterText": "http://localhost:4545/x/a@v2.0.0", - "textEdit": { - "range": { - "start": { - "line": 0, - "character": 20 - }, - "end": { - "line": 0, - "character": 46 - } - }, - "newText": "http://localhost:4545/x/a@v2.0.0" - } -} diff --git a/cli/tests/testdata/lsp/completion_resolve_response_registry.json b/cli/tests/testdata/lsp/completion_resolve_response_registry.json deleted file mode 100644 index 99a4a048e2646e..00000000000000 --- a/cli/tests/testdata/lsp/completion_resolve_response_registry.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "label": "v2.0.0", - "kind": 19, - "detail": "(version)", - "sortText": "0000000003", - "filterText": "http://localhost:4545/x/a@v2.0.0", - "textEdit": { - "range": { - "start": { - "line": 0, - "character": 20 - }, - "end": { - "line": 0, - "character": 46 - } - }, - "newText": "http://localhost:4545/x/a@v2.0.0" - } -} diff --git a/cli/tests/testdata/lsp/completions/npm/resolve_params.json b/cli/tests/testdata/lsp/completions/npm/resolve_params.json deleted file mode 100644 index c83b8ce495832d..00000000000000 --- a/cli/tests/testdata/lsp/completions/npm/resolve_params.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "label": "MyClass", - "kind": 6, - "sortText": "1", - "insertTextFormat": 1, - "data": { - "tsc": { - "specifier": "file:///a/file.ts", - "position": 69, - "name": "MyClass", - "useCodeSnippet": false - } - } -} diff --git a/cli/tests/testdata/lsp/completions/npm/resolve_response.json b/cli/tests/testdata/lsp/completions/npm/resolve_response.json deleted file mode 100644 index c83b8ce495832d..00000000000000 --- a/cli/tests/testdata/lsp/completions/npm/resolve_response.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "label": "MyClass", - "kind": 6, - "sortText": "1", - "insertTextFormat": 1, - "data": { - "tsc": { - "specifier": "file:///a/file.ts", - "position": 69, - "name": "MyClass", - "useCodeSnippet": false - } - } -} diff --git a/cli/tests/testdata/lsp/did_open_lint.json b/cli/tests/testdata/lsp/did_open_lint.json deleted file mode 100644 index 51cef98077ea4a..00000000000000 --- a/cli/tests/testdata/lsp/did_open_lint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts", - "languageId": "typescript", - "version": 1, - "text": "// TODO: fixme\nexport async function non_camel_case() {\nconsole.log(\"finished!\")\n}" - } -} diff --git a/cli/tests/testdata/lsp/did_open_params_deno_types.json b/cli/tests/testdata/lsp/did_open_params_deno_types.json deleted file mode 100644 index 6f085d04549076..00000000000000 --- a/cli/tests/testdata/lsp/did_open_params_deno_types.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts", - "languageId": "typescript", - "version": 1, - "text": "/// \n/// {\n const r = s.slice(0);\n return r;\n}\n\ninterface IFoo {\n readonly x: number;\n foo(): boolean;\n}\n\nclass Bar implements IFoo {\n constructor(public readonly x: number) { }\n foo() { return true; }\n static staticBar = new Bar(0);\n private static getStaticBar() { return Bar.staticBar; }\n}\n" - } -} diff --git a/cli/tests/testdata/lsp/did_open_params_tls_cert.json b/cli/tests/testdata/lsp/did_open_params_tls_cert.json deleted file mode 100644 index 2942bfcbeb44ee..00000000000000 --- a/cli/tests/testdata/lsp/did_open_params_tls_cert.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts", - "languageId": "typescript", - "version": 1, - "text": "import * as a from \"https://localhost:5545/xTypeScriptTypes.js\";\n// @deno-types=\"https://localhost:5545/type_definitions/foo.d.ts\"\nimport * as b from \"https://localhost:5545/type_definitions/foo.js\";\nimport * as c from \"https://localhost:5545/subdir/type_reference.js\";\nimport * as d from \"https://localhost:5545/subdir/mod1.ts\";\nimport * as e from \"data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=\";\nimport * as f from \"./file_01.ts\";\nimport * as g from \"http://localhost:4545/x/a/mod.ts\";\n\nconsole.log(a, b, c, d, e, f, g);\n" - } -} diff --git a/cli/tests/testdata/lsp/document_symbol_response.json b/cli/tests/testdata/lsp/document_symbol_response.json deleted file mode 100644 index 90dd76411ff80f..00000000000000 --- a/cli/tests/testdata/lsp/document_symbol_response.json +++ /dev/null @@ -1,371 +0,0 @@ -[ - { - "name": "bar", - "kind": 13, - "range": { - "start": { - "line": 17, - "character": 4 - }, - "end": { - "line": 17, - "character": 26 - } - }, - "selectionRange": { - "start": { - "line": 17, - "character": 4 - }, - "end": { - "line": 17, - "character": 7 - } - } - }, - { - "name": "Bar", - "kind": 5, - "range": { - "start": { - "line": 4, - "character": 0 - }, - "end": { - "line": 13, - "character": 1 - } - }, - "selectionRange": { - "start": { - "line": 4, - "character": 6 - }, - "end": { - "line": 4, - "character": 9 - } - }, - "children": [ - { - "name": "constructor", - "kind": 9, - "range": { - "start": { - "line": 5, - "character": 2 - }, - "end": { - "line": 5, - "character": 35 - } - }, - "selectionRange": { - "start": { - "line": 5, - "character": 2 - }, - "end": { - "line": 5, - "character": 35 - } - } - }, - { - "name": "baz", - "kind": 6, - "tags": [ - 1 - ], - "range": { - "start": { - "line": 8, - "character": 2 - }, - "end": { - "line": 8, - "character": 25 - } - }, - "selectionRange": { - "start": { - "line": 8, - "character": 2 - }, - "end": { - "line": 8, - "character": 5 - } - } - }, - { - "name": "foo", - "kind": 6, - "range": { - "start": { - "line": 6, - "character": 2 - }, - "end": { - "line": 6, - "character": 24 - } - }, - "selectionRange": { - "start": { - "line": 6, - "character": 2 - }, - "end": { - "line": 6, - "character": 5 - } - } - }, - { - "name": "getStaticBar", - "kind": 6, - "range": { - "start": { - "line": 12, - "character": 2 - }, - "end": { - "line": 12, - "character": 57 - } - }, - "selectionRange": { - "start": { - "line": 12, - "character": 17 - }, - "end": { - "line": 12, - "character": 29 - } - } - }, - { - "name": "staticBar", - "kind": 8, - "range": { - "start": { - "line": 11, - "character": 2 - }, - "end": { - "line": 11, - "character": 32 - } - }, - "selectionRange": { - "start": { - "line": 11, - "character": 9 - }, - "end": { - "line": 11, - "character": 18 - } - } - }, - { - "name": "(get) value", - "kind": 8, - "range": { - "start": { - "line": 9, - "character": 2 - }, - "end": { - "line": 9, - "character": 35 - } - }, - "selectionRange": { - "start": { - "line": 9, - "character": 6 - }, - "end": { - "line": 9, - "character": 11 - } - } - }, - { - "name": "(set) value", - "kind": 8, - "range": { - "start": { - "line": 10, - "character": 2 - }, - "end": { - "line": 10, - "character": 42 - } - }, - "selectionRange": { - "start": { - "line": 10, - "character": 6 - }, - "end": { - "line": 10, - "character": 11 - } - } - }, - { - "name": "x", - "kind": 8, - "range": { - "start": { - "line": 5, - "character": 14 - }, - "end": { - "line": 5, - "character": 30 - } - }, - "selectionRange": { - "start": { - "line": 5, - "character": 21 - }, - "end": { - "line": 5, - "character": 22 - } - } - } - ] - }, - { - "name": "IFoo", - "kind": 11, - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 2, - "character": 1 - } - }, - "selectionRange": { - "start": { - "line": 0, - "character": 10 - }, - "end": { - "line": 0, - "character": 14 - } - }, - "children": [ - { - "name": "foo", - "kind": 6, - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 17 - } - }, - "selectionRange": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 5 - } - } - } - ] - }, - { - "name": "Values", - "kind": 10, - "range": { - "start": { - "line": 15, - "character": 0 - }, - "end": { - "line": 15, - "character": 30 - } - }, - "selectionRange": { - "start": { - "line": 15, - "character": 5 - }, - "end": { - "line": 15, - "character": 11 - } - }, - "children": [ - { - "name": "value1", - "kind": 22, - "range": { - "start": { - "line": 15, - "character": 14 - }, - "end": { - "line": 15, - "character": 20 - } - }, - "selectionRange": { - "start": { - "line": 15, - "character": 14 - }, - "end": { - "line": 15, - "character": 20 - } - } - }, - { - "name": "value2", - "kind": 22, - "range": { - "start": { - "line": 15, - "character": 22 - }, - "end": { - "line": 15, - "character": 28 - } - }, - "selectionRange": { - "start": { - "line": 15, - "character": 22 - }, - "end": { - "line": 15, - "character": 28 - } - } - } - ] - } -] diff --git a/cli/tests/testdata/lsp/incoming_calls_params.json b/cli/tests/testdata/lsp/incoming_calls_params.json deleted file mode 100644 index 6b38d26ee59179..00000000000000 --- a/cli/tests/testdata/lsp/incoming_calls_params.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "item": { - "name": "baz", - "kind": 6, - "detail": "Bar", - "uri": "file:///a/file.ts", - "range": { - "start": { - "line": 5, - "character": 2 - }, - "end": { - "line": 7, - "character": 3 - } - }, - "selectionRange": { - "start": { - "line": 5, - "character": 2 - }, - "end": { - "line": 5, - "character": 5 - } - } - } -} diff --git a/cli/tests/testdata/lsp/incoming_calls_response.json b/cli/tests/testdata/lsp/incoming_calls_response.json deleted file mode 100644 index 231919a8c81996..00000000000000 --- a/cli/tests/testdata/lsp/incoming_calls_response.json +++ /dev/null @@ -1,42 +0,0 @@ -[ - { - "from": { - "name": "main", - "kind": 12, - "detail": "", - "uri": "file:///a/file.ts", - "range": { - "start": { - "line": 10, - "character": 0 - }, - "end": { - "line": 13, - "character": 1 - } - }, - "selectionRange": { - "start": { - "line": 10, - "character": 9 - }, - "end": { - "line": 10, - "character": 13 - } - } - }, - "fromRanges": [ - { - "start": { - "line": 12, - "character": 6 - }, - "end": { - "line": 12, - "character": 9 - } - } - ] - } -] diff --git a/cli/tests/testdata/lsp/outgoing_calls_params.json b/cli/tests/testdata/lsp/outgoing_calls_params.json deleted file mode 100644 index 6b38d26ee59179..00000000000000 --- a/cli/tests/testdata/lsp/outgoing_calls_params.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "item": { - "name": "baz", - "kind": 6, - "detail": "Bar", - "uri": "file:///a/file.ts", - "range": { - "start": { - "line": 5, - "character": 2 - }, - "end": { - "line": 7, - "character": 3 - } - }, - "selectionRange": { - "start": { - "line": 5, - "character": 2 - }, - "end": { - "line": 5, - "character": 5 - } - } - } -} diff --git a/cli/tests/testdata/lsp/prepare_call_hierarchy_response.json b/cli/tests/testdata/lsp/prepare_call_hierarchy_response.json deleted file mode 100644 index 93a7d4f1be8e51..00000000000000 --- a/cli/tests/testdata/lsp/prepare_call_hierarchy_response.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "name": "baz", - "kind": 6, - "detail": "Bar", - "uri": "file:///a/file.ts", - "range": { - "start": { - "line": 5, - "character": 2 - }, - "end": { - "line": 7, - "character": 3 - } - }, - "selectionRange": { - "start": { - "line": 5, - "character": 2 - }, - "end": { - "line": 5, - "character": 5 - } - } - } -] diff --git a/cli/tests/testdata/lsp/rename_response.json b/cli/tests/testdata/lsp/rename_response.json deleted file mode 100644 index 5e0e28e4c074e2..00000000000000 --- a/cli/tests/testdata/lsp/rename_response.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "documentChanges": [ - { - "textDocument": { - "uri": "file:///a/file.ts", - "version": 1 - }, - "edits": [ - { - "range": { - "start": { - "line": 0, - "character": 4 - }, - "end": { - "line": 0, - "character": 12 - } - }, - "newText": "variable_modified" - }, - { - "range": { - "start": { - "line": 1, - "character": 12 - }, - "end": { - "line": 1, - "character": 20 - } - }, - "newText": "variable_modified" - } - ] - } - ] -} diff --git a/cli/tests/testdata/lsp/selection_range_response.json b/cli/tests/testdata/lsp/selection_range_response.json deleted file mode 100644 index c5a8b288e27937..00000000000000 --- a/cli/tests/testdata/lsp/selection_range_response.json +++ /dev/null @@ -1,98 +0,0 @@ -[ - { - "range": { - "start": { - "line": 2, - "character": 8 - }, - "end": { - "line": 2, - "character": 9 - } - }, - "parent": { - "range": { - "start": { - "line": 2, - "character": 8 - }, - "end": { - "line": 2, - "character": 15 - } - }, - "parent": { - "range": { - "start": { - "line": 2, - "character": 4 - }, - "end": { - "line": 4, - "character": 5 - } - }, - "parent": { - "range": { - "start": { - "line": 1, - "character": 13 - }, - "end": { - "line": 6, - "character": 2 - } - }, - "parent": { - "range": { - "start": { - "line": 1, - "character": 12 - }, - "end": { - "line": 6, - "character": 3 - } - }, - "parent": { - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 6, - "character": 3 - } - }, - "parent": { - "range": { - "start": { - "line": 0, - "character": 11 - }, - "end": { - "line": 7, - "character": 0 - } - }, - "parent": { - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 7, - "character": 1 - } - } - } - } - } - } - } - } - } - } -] From 00369d74f1971d2c8bce2031fe317b35eb6cb2ea Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 8 Mar 2023 17:19:30 -0500 Subject: [PATCH 6/9] More. --- cli/tests/integration/lsp_tests.rs | 1102 ++++++++++++++++- .../lsp/code_action_ignore_lint_response.json | 92 -- .../testdata/lsp/code_action_params.json | 39 - .../lsp/code_action_params_cache.json | 41 - .../lsp/code_action_params_imports.json | 54 - .../lsp/code_action_redirect_response.json | 0 .../lsp/code_action_resolve_params.json | 27 - .../code_action_resolve_params_imports.json | 42 - .../lsp/code_action_resolve_response.json | 91 -- .../code_action_resolve_response_imports.json | 67 - .../testdata/lsp/code_action_response.json | 90 -- ...code_action_update_ignore_lint_params.json | 39 - ...de_action_update_ignore_lint_response.json | 92 -- .../code_actions/cache_npm/cache_action.json | 41 - .../cache_npm/cache_response.json | 36 - .../code_actions/cache_npm/diagnostics.json | 25 - .../lsp/code_lens_resolve_response_impl.json | 38 - .../lsp/code_lens_response_changed.json | 50 - .../testdata/lsp/code_lens_response_impl.json | 98 -- .../testdata/lsp/code_lens_response_test.json | 370 ------ .../testdata/lsp/diagnostics_deno_deps.json | 25 - .../lsp/did_open_params_test_code_lens.json | 8 - 22 files changed, 1039 insertions(+), 1428 deletions(-) delete mode 100644 cli/tests/testdata/lsp/code_action_ignore_lint_response.json delete mode 100644 cli/tests/testdata/lsp/code_action_params.json delete mode 100644 cli/tests/testdata/lsp/code_action_params_cache.json delete mode 100644 cli/tests/testdata/lsp/code_action_params_imports.json delete mode 100644 cli/tests/testdata/lsp/code_action_redirect_response.json delete mode 100644 cli/tests/testdata/lsp/code_action_resolve_params.json delete mode 100644 cli/tests/testdata/lsp/code_action_resolve_params_imports.json delete mode 100644 cli/tests/testdata/lsp/code_action_resolve_response.json delete mode 100644 cli/tests/testdata/lsp/code_action_resolve_response_imports.json delete mode 100644 cli/tests/testdata/lsp/code_action_response.json delete mode 100644 cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json delete mode 100644 cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json delete mode 100644 cli/tests/testdata/lsp/code_actions/cache_npm/cache_action.json delete mode 100644 cli/tests/testdata/lsp/code_actions/cache_npm/cache_response.json delete mode 100644 cli/tests/testdata/lsp/code_actions/cache_npm/diagnostics.json delete mode 100644 cli/tests/testdata/lsp/code_lens_resolve_response_impl.json delete mode 100644 cli/tests/testdata/lsp/code_lens_response_changed.json delete mode 100644 cli/tests/testdata/lsp/code_lens_response_impl.json delete mode 100644 cli/tests/testdata/lsp/code_lens_response_test.json delete mode 100644 cli/tests/testdata/lsp/diagnostics_deno_deps.json delete mode 100644 cli/tests/testdata/lsp/did_open_params_test_code_lens.json diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 3e6f5fd954f53c..fc8d7a44eecc29 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -693,21 +693,17 @@ fn lsp_import_assertions() { "end": { "line": 0, "character": 27 } }, "context": { - "diagnostics": [ - { - "range": { - "start": { "line": 0, "character": 14 }, - "end": { "line": 0, "character": 27 } - }, - "severity": 1, - "code": "no-assert-type", - "source": "deno", - "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement." - } - ], - "only": [ - "quickfix" - ] + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 14 }, + "end": { "line": 0, "character": 27 } + }, + "severity": 1, + "code": "no-assert-type", + "source": "deno", + "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement." + }], + "only": ["quickfix"] } }), ) @@ -2980,7 +2976,61 @@ fn lsp_code_lens_impl() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_lens_response_impl.json")) + Some(json!([ { + "range": { + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "implementations" + } + }, { + "range": { + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }, { + "range": { + "start": { "line": 4, "character": 6 }, + "end": { "line": 4, "character": 7 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }, { + "range": { + "start": { "line": 10, "character": 10 }, + "end": { "line": 10, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "implementations" + } + }, { + "range": { + "start": { "line": 10, "character": 10 }, + "end": { "line": 10, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }, { + "range": { + "start": { "line": 11, "character": 2 }, + "end": { "line": 11, "character": 3 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }])) ); let (maybe_res, maybe_err) = client .write_request( @@ -3000,7 +3050,27 @@ fn lsp_code_lens_impl() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_lens_resolve_response_impl.json")) + Some(json!({ + "range": { + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 11 } + }, + "command": { + "title": "1 implementation", + "command": "deno.showReferences", + "arguments": [ + "file:///a/file.ts", + { "line": 0, "character": 10 }, + [{ + "uri": "file:///a/file.ts", + "range": { + "start": { "line": 4, "character": 6 }, + "end": { "line": 4, "character": 7 } + } + }] + ] + } + })) ); let (maybe_res, maybe_err) = client .write_request::<_, _, Value>( @@ -3042,7 +3112,14 @@ fn lsp_code_lens_test() { }); did_open( &mut client, - load_fixture("did_open_params_test_code_lens.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "const { test } = Deno;\nconst { test: test2 } = Deno;\nconst test3 = Deno.test;\n\nDeno.test(\"test a\", () => {});\nDeno.test({\n name: \"test b\",\n fn() {},\n});\ntest({\n name: \"test c\",\n fn() {},\n});\ntest(\"test d\", () => {});\ntest2({\n name: \"test e\",\n fn() {},\n});\ntest2(\"test f\", () => {});\ntest3({\n name: \"test g\",\n fn() {},\n});\ntest3(\"test h\", () => {});\n" + } + }), ); let (maybe_res, maybe_err) = client .write_request( @@ -3057,7 +3134,231 @@ fn lsp_code_lens_test() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_lens_response_test.json")) + Some(json!([{ + "range": { + "start": { "line": 4, "character": 5 }, + "end": { "line": 4, "character": 9 } + }, + "command": { + "title": "▶︎ Run Test", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test a", + { "inspect": false } + ] + } + }, { + "range": { + "start": { "line": 4, "character": 5 }, + "end": { "line": 4, "character": 9 } + }, + "command": { + "title": "Debug", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test a", + { "inspect": true } + ] + } + }, { + "range": { + "start": { "line": 5, "character": 5 }, + "end": { "line": 5, "character": 9 } + }, + "command": { + "title": "▶︎ Run Test", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test b", + { "inspect": false } + ] + } + }, { + "range": { + "start": { "line": 5, "character": 5 }, + "end": { "line": 5, "character": 9 } + }, + "command": { + "title": "Debug", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test b", + { "inspect": true } + ] + } + }, { + "range": { + "start": { "line": 9, "character": 0 }, + "end": { "line": 9, "character": 4 } + }, + "command": { + "title": "▶︎ Run Test", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test c", + { "inspect": false } + ] + } + }, { + "range": { + "start": { "line": 9, "character": 0 }, + "end": { "line": 9, "character": 4 } + }, + "command": { + "title": "Debug", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test c", + { "inspect": true } + ] + } + }, { + "range": { + "start": { "line": 13, "character": 0 }, + "end": { "line": 13, "character": 4 } + }, + "command": { + "title": "▶︎ Run Test", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test d", + { "inspect": false } + ] + } + }, { + "range": { + "start": { "line": 13, "character": 0 }, + "end": { "line": 13, "character": 4 } + }, + "command": { + "title": "Debug", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test d", + { "inspect": true } + ] + } + }, { + "range": { + "start": { "line": 14, "character": 0 }, + "end": { "line": 14, "character": 5 } + }, + "command": { + "title": "▶︎ Run Test", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test e", + { "inspect": false } + ] + } + }, { + "range": { + "start": { "line": 14, "character": 0 }, + "end": { "line": 14, "character": 5 } + }, + "command": { + "title": "Debug", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test e", + { "inspect": true } + ] + } + }, { + "range": { + "start": { "line": 18, "character": 0 }, + "end": { "line": 18, "character": 5 } + }, + "command": { + "title": "▶︎ Run Test", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test f", + { "inspect": false } + ] + } + }, { + "range": { + "start": { "line": 18, "character": 0 }, + "end": { "line": 18, "character": 5 } + }, + "command": { + "title": "Debug", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test f", + { "inspect": true } + ] + } + }, { + "range": { + "start": { "line": 19, "character": 0 }, + "end": { "line": 19, "character": 5 } + }, + "command": { + "title": "▶︎ Run Test", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test g", + { "inspect": false } + ] + } + }, { + "range": { + "start": { "line": 19, "character": 0 }, + "end": { "line": 19, "character": 5 } + }, + "command": { + "title": "Debug", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test g", + { "inspect": true } + ] + } + }, { + "range": { + "start": { "line": 23, "character": 0 }, + "end": { "line": 23, "character": 5 } + }, + "command": { + "title": "▶︎ Run Test", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test h", + { "inspect": false } + ] + } + }, { + "range": { + "start": { "line": 23, "character": 0 }, + "end": { "line": 23, "character": 5 } + }, + "command": { + "title": "Debug", + "command": "deno.test", + "arguments": [ + "file:///a/file.ts", + "test h", + { "inspect": true } + ] + } + }])) ); client.shutdown(); } @@ -3075,7 +3376,14 @@ fn lsp_code_lens_test_disabled() { client .write_notification( "textDocument/didOpen", - load_fixture("did_open_params_test_code_lens.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "const { test } = Deno;\nconst { test: test2 } = Deno;\nconst test3 = Deno.test;\n\nDeno.test(\"test a\", () => {});\nDeno.test({\n name: \"test b\",\n fn() {},\n});\ntest({\n name: \"test c\",\n fn() {},\n});\ntest(\"test d\", () => {});\ntest2({\n name: \"test e\",\n fn() {},\n});\ntest2(\"test f\", () => {});\ntest3({\n name: \"test g\",\n fn() {},\n});\ntest3(\"test h\", () => {});\n" + } + }), ) .unwrap(); @@ -3219,7 +3527,61 @@ fn lsp_nav_tree_updates() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_lens_response_impl.json")) + Some(Some(json!([ { + "range": { + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "implementations" + } + }, { + "range": { + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }, { + "range": { + "start": { "line": 4, "character": 6 }, + "end": { "line": 4, "character": 7 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }, { + "range": { + "start": { "line": 10, "character": 10 }, + "end": { "line": 10, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "implementations" + } + }, { + "range": { + "start": { "line": 10, "character": 10 }, + "end": { "line": 10, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }, { + "range": { + "start": { "line": 11, "character": 2 }, + "end": { "line": 11, "character": 3 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }]))) ); client .write_notification( @@ -3254,7 +3616,34 @@ fn lsp_nav_tree_updates() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_lens_response_changed.json")) + Some(json!([{ + "range": { + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "implementations" + } + }, { + "range": { + "start": { "line": 0, "character": 10 }, + "end": { "line": 0, "character": 11 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }, { + "range": { + "start": { "line": 4, "character": 6 }, + "end": { "line": 4, "character": 7 } + }, + "data": { + "specifier": "file:///a/file.ts", + "source": "references" + } + }])) ); client.shutdown(); } @@ -3403,26 +3792,182 @@ fn lsp_code_actions() { "version": 1, "text": "export function a(): void {\n await Promise.resolve(\"a\");\n}\n\nexport function b(): void {\n await Promise.resolve(\"b\");\n}\n" } - }), - ); - let (maybe_res, maybe_err) = client - .write_request( - "textDocument/codeAction", - load_fixture("code_action_params.json"), - ) - .unwrap(); - assert!(maybe_err.is_none()); - assert_eq!(maybe_res, Some(load_fixture("code_action_response.json"))); - let (maybe_res, maybe_err) = client - .write_request( - "codeAction/resolve", - load_fixture("code_action_resolve_params.json"), - ) - .unwrap(); - assert!(maybe_err.is_none()); - assert_eq!( - maybe_res, - Some(load_fixture("code_action_resolve_response.json")) + }), + ); + let (maybe_res, maybe_err) = client + .write_request( + "textDocument/codeAction", + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "range": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 7 } + }, + "context": { + "diagnostics": [{ + "range": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 7 } + }, + "severity": 1, + "code": 1308, + "source": "deno-ts", + "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", + "relatedInformation": [] + }], + "only": ["quickfix"] + } + }), + ) + .unwrap(); + assert!(maybe_err.is_none()); + assert_eq!( + maybe_res, + Some(json!([{ + "title": "Add async modifier to containing function", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 7 } + }, + "severity": 1, + "code": 1308, + "source": "deno-ts", + "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", + "relatedInformation": [] + }], + "edit": { + "documentChanges": [{ + "textDocument": { + "uri": "file:///a/file.ts", + "version": 1 + }, + "edits": [{ + "range": { + "start": { "line": 0, "character": 7 }, + "end": { "line": 0, "character": 7 } + }, + "newText": "async " + }, { + "range": { + "start": { "line": 0, "character": 21 }, + "end": { "line": 0, "character": 25 } + }, + "newText": "Promise" + }] + }] + } + }, { + "title": "Add all missing 'async' modifiers", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 7 } + }, + "severity": 1, + "code": 1308, + "source": "deno-ts", + "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", + "relatedInformation": [] + }], + "data": { + "specifier": "file:///a/file.ts", + "fixId": "fixAwaitInSyncFunction" + } + }])) + ); + let (maybe_res, maybe_err) = client + .write_request( + "codeAction/resolve", + json!({ + "title": "Add all missing 'async' modifiers", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 1, "character": 2 }, + "end": { "line": 1, "character": 7 } + }, + "severity": 1, + "code": 1308, + "source": "deno-ts", + "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", + "relatedInformation": [] + }], + "data": { + "specifier": "file:///a/file.ts", + "fixId": "fixAwaitInSyncFunction" + } + }), + ) + .unwrap(); + assert!(maybe_err.is_none()); + assert_eq!( + maybe_res, + Some(json!({ + "title": "Add all missing 'async' modifiers", + "kind": "quickfix", + "diagnostics": [ + { + "range": { + "start": { + "line": 1, + "character": 2 + }, + "end": { + "line": 1, + "character": 7 + } + }, + "severity": 1, + "code": 1308, + "source": "deno-ts", + "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", + "relatedInformation": [] + } + ], + "edit": { + "documentChanges": [{ + "textDocument": { + "uri": "file:///a/file.ts", + "version": 1 + }, + "edits": [{ + "range": { + "start": { "line": 0, "character": 7 }, + "end": { "line": 0, "character": 7 } + }, + "newText": "async " + }, { + "range": { + "start": { "line": 0, "character": 21 }, + "end": { "line": 0, "character": 25 } + }, + "newText": "Promise" + }, { + "range": { + "start": { "line": 4, "character": 7 }, + "end": { "line": 4, "character": 7 } + }, + "newText": "async " + }, + { + "range": { + "start": { "line": 4, "character": 21 }, + "end": { "line": 4, "character": 25 } + }, + "newText": "Promise" + }] + }] + }, + "data": { + "specifier": "file:///a/file.ts", + "fixId": "fixAwaitInSyncFunction" + } + })) ); client.shutdown(); } @@ -3442,14 +3987,52 @@ fn lsp_code_actions_deno_cache() { })); assert_eq!( diagnostics.with_source("deno"), - load_fixture_as("diagnostics_deno_deps.json") + serde_json::from_value(json!({ + "uri": "file:///a/file.ts", + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 49 } + }, + "severity": 1, + "code": "no-cache", + "source": "deno", + "message": "Uncached or missing remote URL: \"https://deno.land/x/a/mod.ts\".", + "data": { "specifier": "https://deno.land/x/a/mod.ts" } + }], + "version": 1 + })).unwrap() ); let (maybe_res, maybe_err) = session .client .write_request( "textDocument/codeAction", - load_fixture("code_action_params_cache.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "range": { + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 49 } + }, + "context": { + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 49 } + }, + "severity": 1, + "code": "no-cache", + "source": "deno", + "message": "Unable to load the remote module: \"https://deno.land/x/a/mod.ts\".", + "data": { + "specifier": "https://deno.land/x/a/mod.ts" + } + }], + "only": ["quickfix"] + } + }), ) .unwrap(); assert!(maybe_err.is_none()); @@ -3475,20 +4058,76 @@ fn lsp_code_actions_deno_cache_npm() { })); assert_eq!( diagnostics.with_source("deno"), - load_fixture_as("code_actions/cache_npm/diagnostics.json") + serde_json::from_value(json!({ + "uri": "file:///a/file.ts", + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 18 }, + "end": { "line": 0, "character": 29 } + }, + "severity": 1, + "code": "no-cache-npm", + "source": "deno", + "message": "Uncached or missing npm package: \"chalk\".", + "data": { "specifier": "npm:chalk" } + }], + "version": 1 + })) + .unwrap() ); let (maybe_res, maybe_err) = session .client .write_request( "textDocument/codeAction", - load_fixture("code_actions/cache_npm/cache_action.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "range": { + "start": { "line": 0, "character": 18 }, + "end": { "line": 0, "character": 29 } + }, + "context": { + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 18 }, + "end": { "line": 0, "character": 29 } + }, + "severity": 1, + "code": "no-cache-npm", + "source": "deno", + "message": "Uncached or missing npm package: \"chalk\".", + "data": { "specifier": "npm:chalk" } + }], + "only": ["quickfix"] + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_actions/cache_npm/cache_response.json")) + Some(json!([{ + "title": "Cache \"npm:chalk\" and its dependencies.", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 18 }, + "end": { "line": 0, "character": 29 } + }, + "severity": 1, + "code": "no-cache-npm", + "source": "deno", + "message": "Uncached or missing npm package: \"chalk\".", + "data": { "specifier": "npm:chalk" } + }], + "command": { + "title": "", + "command": "deno.cache", + "arguments": [["npm:chalk"]] + } + }])) ); session.shutdown_and_exit(); } @@ -3548,25 +4187,196 @@ export class DuckConfig { .client .write_request( "textDocument/codeAction", - load_fixture("code_action_params_imports.json"), + json!({ + "textDocument": { + "uri": "file:///a/file00.ts" + }, + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 6, "character": 0 } + }, + "context": { + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 50 }, + "end": { "line": 0, "character": 67 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfigOptions'." + }, { + "range": { + "start": { "line": 4, "character": 39 }, + "end": { "line": 4, "character": 49 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfig'." + }], + "only": ["quickfix"] + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_response_imports.json")) + Some(json!([{ + "title": "Add import from \"./file02.ts\"", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 50 }, + "end": { "line": 0, "character": 67 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfigOptions'." + }], + "edit": { + "documentChanges": [{ + "textDocument": { + "uri": "file:///a/file00.ts", + "version": 1 + }, + "edits": [{ + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "import { DuckConfigOptions } from \"./file02.ts\";\n\n" + }] + }] + } + }, { + "title": "Add all missing imports", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 50 }, + "end": { "line": 0, "character": 67 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfigOptions'." + }], + "data": { + "specifier": "file:///a/file00.ts", + "fixId": "fixMissingImport" + } + }, { + "title": "Add import from \"./file01.ts\"", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 4, "character": 39 }, + "end": { "line": 4, "character": 49 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfig'." + }], + "edit": { + "documentChanges": [{ + "textDocument": { + "uri": "file:///a/file00.ts", + "version": 1 + }, + "edits": [{ + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "import { DuckConfig } from \"./file01.ts\";\n\n" + }] + }] + } + }])) ); let (maybe_res, maybe_err) = session .client .write_request( "codeAction/resolve", - load_fixture("code_action_resolve_params_imports.json"), + json!({ + "title": "Add all missing imports", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 50 }, + "end": { "line": 0, "character": 67 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfigOptions'." + }, { + "range": { + "start": { "line": 4, "character": 39 }, + "end": { "line": 4, "character": 49 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfig'." + }], + "data": { + "specifier": "file:///a/file00.ts", + "fixId": "fixMissingImport" + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_resolve_response_imports.json")) + Some(json!({ + "title": "Add all missing imports", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 50 }, + "end": { "line": 0, "character": 67 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfigOptions'." + }, + { + "range": { + "start": { "line": 4, "character": 39 }, + "end": { "line": 4, "character": 49 } + }, + "severity": 1, + "code": 2304, + "source": "deno-ts", + "message": "Cannot find name 'DuckConfig'." + }], + "edit": { + "documentChanges": [{ + "textDocument": { + "uri": "file:///a/file00.ts", + "version": 1 + }, + "edits": [{ + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "import { DuckConfig } from \"./file01.ts\";\nimport { DuckConfigOptions } from \"./file02.ts\";\n\n" + }] + }] + }, + "data": { + "specifier": "file:///a/file00.ts", + "fixId": "fixMissingImport" + } + })) ); session.shutdown_and_exit(); @@ -4598,9 +5408,7 @@ fn lsp_completions_node_specifier() { }, "context": { "diagnostics": json!(diagnostics), - "only": [ - "quickfix" - ] + "only": ["quickfix"] } }), ) @@ -5291,9 +6099,7 @@ fn lsp_redirect_quick_fix() { }, "context": { "diagnostics": diagnostics, - "only": [ - "quickfix" - ] + "only": ["quickfix"] } })), ) @@ -6371,9 +7177,7 @@ fn lsp_code_actions_ignore_lint() { "relatedInformation": [] } ], - "only": [ - "quickfix" - ] + "only": ["quickfix"] } }), ) @@ -6381,7 +7185,82 @@ fn lsp_code_actions_ignore_lint() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_ignore_lint_response.json")) + Some(json!([{ + "title": "Disable prefer-const for this line", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 1, "character": 5 }, + "end": { "line": 1, "character": 12 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'message' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + }], + "edit": { + "changes": { + "file:///a/file.ts": [{ + "range": { + "start": { "line": 1, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "newText": "// deno-lint-ignore prefer-const\n" + }] + } + } + }, { + "title": "Disable prefer-const for the entire file", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 1, "character": 5 }, + "end": { "line": 1, "character": 12 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'message' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + }], + "edit": { + "changes": { + "file:///a/file.ts": [{ + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "// deno-lint-ignore-file prefer-const\n" + }] + } + } + }, { + "title": "Ignore lint errors for the entire file", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 1, "character": 5 }, + "end": { "line": 1, "character": 12 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'message' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + }], + "edit": { + "changes": { + "file:///a/file.ts": [{ + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "// deno-lint-ignore-file\n" + }] + } + } + }])) ); client.shutdown(); } @@ -6410,13 +7289,110 @@ console.log(snake_case); let (maybe_res, maybe_err) = client .write_request( "textDocument/codeAction", - load_fixture("code_action_update_ignore_lint_params.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "range": { + "start": { "line": 3, "character": 5 }, + "end": { "line": 3, "character": 15 } + }, + "context": { + "diagnostics": [{ + "range": { + "start": { "line": 3, "character": 5 }, + "end": { "line": 3, "character": 15 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'snake_case' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + }], + "only": ["quickfix"] + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_update_ignore_lint_response.json")) + Some(json!([{ + "title": "Disable prefer-const for this line", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 3, "character": 5 }, + "end": { "line": 3, "character": 15 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'snake_case' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + }], + "edit": { + "changes": { + "file:///a/file.ts": [{ + "range": { + "start": { "line": 3, "character": 0 }, + "end": { "line": 3, "character": 0 } + }, + "newText": "// deno-lint-ignore prefer-const\n" + }] + } + } + }, { + "title": "Disable prefer-const for the entire file", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 3, "character": 5 }, + "end": { "line": 3, "character": 15 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'snake_case' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + }], + "edit": { + "changes": { + "file:///a/file.ts": [{ + "range": { + "start": { "line": 1, "character": 34 }, + "end": { "line": 1, "character": 34 } + }, + "newText": " prefer-const" + }] + } + } + }, { + "title": "Ignore lint errors for the entire file", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 3, "character": 5 }, + "end": { "line": 3, "character": 15 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'snake_case' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + }], + "edit": { + "changes": { + "file:///a/file.ts": [{ + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "// deno-lint-ignore-file\n" + }] + } + } + }])) ); client.shutdown(); } diff --git a/cli/tests/testdata/lsp/code_action_ignore_lint_response.json b/cli/tests/testdata/lsp/code_action_ignore_lint_response.json deleted file mode 100644 index d15fccca96219d..00000000000000 --- a/cli/tests/testdata/lsp/code_action_ignore_lint_response.json +++ /dev/null @@ -1,92 +0,0 @@ -[ - { - "title": "Disable prefer-const for this line", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { "line": 1, "character": 5 }, - "end": { "line": 1, "character": 12 } - }, - "severity": 1, - "code": "prefer-const", - "source": "deno-lint", - "message": "'message' is never reassigned\nUse 'const' instead", - "relatedInformation": [] - } - ], - "edit": { - "changes": { - "file:///a/file.ts": [ - { - "range": { - "start": { "line": 1, "character": 0 }, - "end": { "line": 1, "character": 0 } - }, - "newText": "// deno-lint-ignore prefer-const\n" - } - ] - } - } - }, - { - "title": "Disable prefer-const for the entire file", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { "line": 1, "character": 5 }, - "end": { "line": 1, "character": 12 } - }, - "severity": 1, - "code": "prefer-const", - "source": "deno-lint", - "message": "'message' is never reassigned\nUse 'const' instead", - "relatedInformation": [] - } - ], - "edit": { - "changes": { - "file:///a/file.ts": [ - { - "range": { - "start": { "line": 0, "character": 0 }, - "end": { "line": 0, "character": 0 } - }, - "newText": "// deno-lint-ignore-file prefer-const\n" - } - ] - } - } - }, - { - "title": "Ignore lint errors for the entire file", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { "line": 1, "character": 5 }, - "end": { "line": 1, "character": 12 } - }, - "severity": 1, - "code": "prefer-const", - "source": "deno-lint", - "message": "'message' is never reassigned\nUse 'const' instead", - "relatedInformation": [] - } - ], - "edit": { - "changes": { - "file:///a/file.ts": [ - { - "range": { - "start": { "line": 0, "character": 0 }, - "end": { "line": 0, "character": 0 } - }, - "newText": "// deno-lint-ignore-file\n" - } - ] - } - } - } -] diff --git a/cli/tests/testdata/lsp/code_action_params.json b/cli/tests/testdata/lsp/code_action_params.json deleted file mode 100644 index d026d61f6873de..00000000000000 --- a/cli/tests/testdata/lsp/code_action_params.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts" - }, - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 7 - } - }, - "context": { - "diagnostics": [ - { - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 7 - } - }, - "severity": 1, - "code": 1308, - "source": "deno-ts", - "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", - "relatedInformation": [] - } - ], - "only": [ - "quickfix" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_action_params_cache.json b/cli/tests/testdata/lsp/code_action_params_cache.json deleted file mode 100644 index 61ae555a3ce19d..00000000000000 --- a/cli/tests/testdata/lsp/code_action_params_cache.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts" - }, - "range": { - "start": { - "line": 0, - "character": 19 - }, - "end": { - "line": 0, - "character": 49 - } - }, - "context": { - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 19 - }, - "end": { - "line": 0, - "character": 49 - } - }, - "severity": 1, - "code": "no-cache", - "source": "deno", - "message": "Unable to load the remote module: \"https://deno.land/x/a/mod.ts\".", - "data": { - "specifier": "https://deno.land/x/a/mod.ts" - } - } - ], - "only": [ - "quickfix" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_action_params_imports.json b/cli/tests/testdata/lsp/code_action_params_imports.json deleted file mode 100644 index 891257ca01bfe8..00000000000000 --- a/cli/tests/testdata/lsp/code_action_params_imports.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file00.ts" - }, - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 6, - "character": 0 - } - }, - "context": { - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 50 - }, - "end": { - "line": 0, - "character": 67 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfigOptions'." - }, - { - "range": { - "start": { - "line": 4, - "character": 39 - }, - "end": { - "line": 4, - "character": 49 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfig'." - } - ], - "only": [ - "quickfix" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_action_redirect_response.json b/cli/tests/testdata/lsp/code_action_redirect_response.json deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/cli/tests/testdata/lsp/code_action_resolve_params.json b/cli/tests/testdata/lsp/code_action_resolve_params.json deleted file mode 100644 index 50c1f9a43b7f70..00000000000000 --- a/cli/tests/testdata/lsp/code_action_resolve_params.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "title": "Add all missing 'async' modifiers", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 7 - } - }, - "severity": 1, - "code": 1308, - "source": "deno-ts", - "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", - "relatedInformation": [] - } - ], - "data": { - "specifier": "file:///a/file.ts", - "fixId": "fixAwaitInSyncFunction" - } -} diff --git a/cli/tests/testdata/lsp/code_action_resolve_params_imports.json b/cli/tests/testdata/lsp/code_action_resolve_params_imports.json deleted file mode 100644 index 5e1beb87bc0774..00000000000000 --- a/cli/tests/testdata/lsp/code_action_resolve_params_imports.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "title": "Add all missing imports", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 50 - }, - "end": { - "line": 0, - "character": 67 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfigOptions'." - }, - { - "range": { - "start": { - "line": 4, - "character": 39 - }, - "end": { - "line": 4, - "character": 49 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfig'." - } - ], - "data": { - "specifier": "file:///a/file00.ts", - "fixId": "fixMissingImport" - } -} diff --git a/cli/tests/testdata/lsp/code_action_resolve_response.json b/cli/tests/testdata/lsp/code_action_resolve_response.json deleted file mode 100644 index e3f5b3f0edf185..00000000000000 --- a/cli/tests/testdata/lsp/code_action_resolve_response.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "title": "Add all missing 'async' modifiers", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 7 - } - }, - "severity": 1, - "code": 1308, - "source": "deno-ts", - "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", - "relatedInformation": [] - } - ], - "edit": { - "documentChanges": [ - { - "textDocument": { - "uri": "file:///a/file.ts", - "version": 1 - }, - "edits": [ - { - "range": { - "start": { - "line": 0, - "character": 7 - }, - "end": { - "line": 0, - "character": 7 - } - }, - "newText": "async " - }, - { - "range": { - "start": { - "line": 0, - "character": 21 - }, - "end": { - "line": 0, - "character": 25 - } - }, - "newText": "Promise" - }, - { - "range": { - "start": { - "line": 4, - "character": 7 - }, - "end": { - "line": 4, - "character": 7 - } - }, - "newText": "async " - }, - { - "range": { - "start": { - "line": 4, - "character": 21 - }, - "end": { - "line": 4, - "character": 25 - } - }, - "newText": "Promise" - } - ] - } - ] - }, - "data": { - "specifier": "file:///a/file.ts", - "fixId": "fixAwaitInSyncFunction" - } -} diff --git a/cli/tests/testdata/lsp/code_action_resolve_response_imports.json b/cli/tests/testdata/lsp/code_action_resolve_response_imports.json deleted file mode 100644 index 6ffc3192ed3ae3..00000000000000 --- a/cli/tests/testdata/lsp/code_action_resolve_response_imports.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "title": "Add all missing imports", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 50 - }, - "end": { - "line": 0, - "character": 67 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfigOptions'." - }, - { - "range": { - "start": { - "line": 4, - "character": 39 - }, - "end": { - "line": 4, - "character": 49 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfig'." - } - ], - "edit": { - "documentChanges": [ - { - "textDocument": { - "uri": "file:///a/file00.ts", - "version": 1 - }, - "edits": [ - { - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 0, - "character": 0 - } - }, - "newText": "import { DuckConfig } from \"./file01.ts\";\nimport { DuckConfigOptions } from \"./file02.ts\";\n\n" - } - ] - } - ] - }, - "data": { - "specifier": "file:///a/file00.ts", - "fixId": "fixMissingImport" - } -} diff --git a/cli/tests/testdata/lsp/code_action_response.json b/cli/tests/testdata/lsp/code_action_response.json deleted file mode 100644 index ab30898f8ec0a4..00000000000000 --- a/cli/tests/testdata/lsp/code_action_response.json +++ /dev/null @@ -1,90 +0,0 @@ -[ - { - "title": "Add async modifier to containing function", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 7 - } - }, - "severity": 1, - "code": 1308, - "source": "deno-ts", - "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", - "relatedInformation": [] - } - ], - "edit": { - "documentChanges": [ - { - "textDocument": { - "uri": "file:///a/file.ts", - "version": 1 - }, - "edits": [ - { - "range": { - "start": { - "line": 0, - "character": 7 - }, - "end": { - "line": 0, - "character": 7 - } - }, - "newText": "async " - }, - { - "range": { - "start": { - "line": 0, - "character": 21 - }, - "end": { - "line": 0, - "character": 25 - } - }, - "newText": "Promise" - } - ] - } - ] - } - }, - { - "title": "Add all missing 'async' modifiers", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 1, - "character": 2 - }, - "end": { - "line": 1, - "character": 7 - } - }, - "severity": 1, - "code": 1308, - "source": "deno-ts", - "message": "'await' expressions are only allowed within async functions and at the top levels of modules.", - "relatedInformation": [] - } - ], - "data": { - "specifier": "file:///a/file.ts", - "fixId": "fixAwaitInSyncFunction" - } - } -] diff --git a/cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json b/cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json deleted file mode 100644 index 8cbf1185f4c06f..00000000000000 --- a/cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts" - }, - "range": { - "start": { - "line": 3, - "character": 5 - }, - "end": { - "line": 3, - "character": 15 - } - }, - "context": { - "diagnostics": [ - { - "range": { - "start": { - "line": 3, - "character": 5 - }, - "end": { - "line": 3, - "character": 15 - } - }, - "severity": 1, - "code": "prefer-const", - "source": "deno-lint", - "message": "'snake_case' is never reassigned\nUse 'const' instead", - "relatedInformation": [] - } - ], - "only": [ - "quickfix" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json b/cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json deleted file mode 100644 index a23e719e0ceb66..00000000000000 --- a/cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json +++ /dev/null @@ -1,92 +0,0 @@ -[ - { - "title": "Disable prefer-const for this line", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { "line": 3, "character": 5 }, - "end": { "line": 3, "character": 15 } - }, - "severity": 1, - "code": "prefer-const", - "source": "deno-lint", - "message": "'snake_case' is never reassigned\nUse 'const' instead", - "relatedInformation": [] - } - ], - "edit": { - "changes": { - "file:///a/file.ts": [ - { - "range": { - "start": { "line": 3, "character": 0 }, - "end": { "line": 3, "character": 0 } - }, - "newText": "// deno-lint-ignore prefer-const\n" - } - ] - } - } - }, - { - "title": "Disable prefer-const for the entire file", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { "line": 3, "character": 5 }, - "end": { "line": 3, "character": 15 } - }, - "severity": 1, - "code": "prefer-const", - "source": "deno-lint", - "message": "'snake_case' is never reassigned\nUse 'const' instead", - "relatedInformation": [] - } - ], - "edit": { - "changes": { - "file:///a/file.ts": [ - { - "range": { - "start": { "line": 1, "character": 34 }, - "end": { "line": 1, "character": 34 } - }, - "newText": " prefer-const" - } - ] - } - } - }, - { - "title": "Ignore lint errors for the entire file", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { "line": 3, "character": 5 }, - "end": { "line": 3, "character": 15 } - }, - "severity": 1, - "code": "prefer-const", - "source": "deno-lint", - "message": "'snake_case' is never reassigned\nUse 'const' instead", - "relatedInformation": [] - } - ], - "edit": { - "changes": { - "file:///a/file.ts": [ - { - "range": { - "start": { "line": 0, "character": 0 }, - "end": { "line": 0, "character": 0 } - }, - "newText": "// deno-lint-ignore-file\n" - } - ] - } - } - } -] diff --git a/cli/tests/testdata/lsp/code_actions/cache_npm/cache_action.json b/cli/tests/testdata/lsp/code_actions/cache_npm/cache_action.json deleted file mode 100644 index b698df3bd8834d..00000000000000 --- a/cli/tests/testdata/lsp/code_actions/cache_npm/cache_action.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts" - }, - "range": { - "start": { - "line": 0, - "character": 18 - }, - "end": { - "line": 0, - "character": 29 - } - }, - "context": { - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 18 - }, - "end": { - "line": 0, - "character": 29 - } - }, - "severity": 1, - "code": "no-cache-npm", - "source": "deno", - "message": "Uncached or missing npm package: \"chalk\".", - "data": { - "specifier": "npm:chalk" - } - } - ], - "only": [ - "quickfix" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_actions/cache_npm/cache_response.json b/cli/tests/testdata/lsp/code_actions/cache_npm/cache_response.json deleted file mode 100644 index 1b41babcb8ef31..00000000000000 --- a/cli/tests/testdata/lsp/code_actions/cache_npm/cache_response.json +++ /dev/null @@ -1,36 +0,0 @@ -[ - { - "title": "Cache \"npm:chalk\" and its dependencies.", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 18 - }, - "end": { - "line": 0, - "character": 29 - } - }, - "severity": 1, - "code": "no-cache-npm", - "source": "deno", - "message": "Uncached or missing npm package: \"chalk\".", - "data": { - "specifier": "npm:chalk" - } - } - ], - "command": { - "title": "", - "command": "deno.cache", - "arguments": [ - [ - "npm:chalk" - ] - ] - } - } -] diff --git a/cli/tests/testdata/lsp/code_actions/cache_npm/diagnostics.json b/cli/tests/testdata/lsp/code_actions/cache_npm/diagnostics.json deleted file mode 100644 index 63c9d0029d5215..00000000000000 --- a/cli/tests/testdata/lsp/code_actions/cache_npm/diagnostics.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "uri": "file:///a/file.ts", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 18 - }, - "end": { - "line": 0, - "character": 29 - } - }, - "severity": 1, - "code": "no-cache-npm", - "source": "deno", - "message": "Uncached or missing npm package: \"chalk\".", - "data": { - "specifier": "npm:chalk" - } - } - ], - "version": 1 -} diff --git a/cli/tests/testdata/lsp/code_lens_resolve_response_impl.json b/cli/tests/testdata/lsp/code_lens_resolve_response_impl.json deleted file mode 100644 index cabf2f8334be8d..00000000000000 --- a/cli/tests/testdata/lsp/code_lens_resolve_response_impl.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "range": { - "start": { - "line": 0, - "character": 10 - }, - "end": { - "line": 0, - "character": 11 - } - }, - "command": { - "title": "1 implementation", - "command": "deno.showReferences", - "arguments": [ - "file:///a/file.ts", - { - "line": 0, - "character": 10 - }, - [ - { - "uri": "file:///a/file.ts", - "range": { - "start": { - "line": 4, - "character": 6 - }, - "end": { - "line": 4, - "character": 7 - } - } - } - ] - ] - } -} diff --git a/cli/tests/testdata/lsp/code_lens_response_changed.json b/cli/tests/testdata/lsp/code_lens_response_changed.json deleted file mode 100644 index b0073a23f7c36c..00000000000000 --- a/cli/tests/testdata/lsp/code_lens_response_changed.json +++ /dev/null @@ -1,50 +0,0 @@ -[ - { - "range": { - "start": { - "line": 0, - "character": 10 - }, - "end": { - "line": 0, - "character": 11 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "implementations" - } - }, - { - "range": { - "start": { - "line": 0, - "character": 10 - }, - "end": { - "line": 0, - "character": 11 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "references" - } - }, - { - "range": { - "start": { - "line": 4, - "character": 6 - }, - "end": { - "line": 4, - "character": 7 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "references" - } - } -] diff --git a/cli/tests/testdata/lsp/code_lens_response_impl.json b/cli/tests/testdata/lsp/code_lens_response_impl.json deleted file mode 100644 index c6e5bd92d3e868..00000000000000 --- a/cli/tests/testdata/lsp/code_lens_response_impl.json +++ /dev/null @@ -1,98 +0,0 @@ -[ - { - "range": { - "start": { - "line": 0, - "character": 10 - }, - "end": { - "line": 0, - "character": 11 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "implementations" - } - }, - { - "range": { - "start": { - "line": 0, - "character": 10 - }, - "end": { - "line": 0, - "character": 11 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "references" - } - }, - { - "range": { - "start": { - "line": 4, - "character": 6 - }, - "end": { - "line": 4, - "character": 7 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "references" - } - }, - { - "range": { - "start": { - "line": 10, - "character": 10 - }, - "end": { - "line": 10, - "character": 11 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "implementations" - } - }, - { - "range": { - "start": { - "line": 10, - "character": 10 - }, - "end": { - "line": 10, - "character": 11 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "references" - } - }, - { - "range": { - "start": { - "line": 11, - "character": 2 - }, - "end": { - "line": 11, - "character": 3 - } - }, - "data": { - "specifier": "file:///a/file.ts", - "source": "references" - } - } -] diff --git a/cli/tests/testdata/lsp/code_lens_response_test.json b/cli/tests/testdata/lsp/code_lens_response_test.json deleted file mode 100644 index 159839816c860c..00000000000000 --- a/cli/tests/testdata/lsp/code_lens_response_test.json +++ /dev/null @@ -1,370 +0,0 @@ -[ - { - "range": { - "start": { - "line": 4, - "character": 5 - }, - "end": { - "line": 4, - "character": 9 - } - }, - "command": { - "title": "▶︎ Run Test", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test a", - { - "inspect": false - } - ] - } - }, - { - "range": { - "start": { - "line": 4, - "character": 5 - }, - "end": { - "line": 4, - "character": 9 - } - }, - "command": { - "title": "Debug", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test a", - { - "inspect": true - } - ] - } - }, - { - "range": { - "start": { - "line": 5, - "character": 5 - }, - "end": { - "line": 5, - "character": 9 - } - }, - "command": { - "title": "▶︎ Run Test", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test b", - { - "inspect": false - } - ] - } - }, - { - "range": { - "start": { - "line": 5, - "character": 5 - }, - "end": { - "line": 5, - "character": 9 - } - }, - "command": { - "title": "Debug", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test b", - { - "inspect": true - } - ] - } - }, - { - "range": { - "start": { - "line": 9, - "character": 0 - }, - "end": { - "line": 9, - "character": 4 - } - }, - "command": { - "title": "▶︎ Run Test", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test c", - { - "inspect": false - } - ] - } - }, - { - "range": { - "start": { - "line": 9, - "character": 0 - }, - "end": { - "line": 9, - "character": 4 - } - }, - "command": { - "title": "Debug", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test c", - { - "inspect": true - } - ] - } - }, - { - "range": { - "start": { - "line": 13, - "character": 0 - }, - "end": { - "line": 13, - "character": 4 - } - }, - "command": { - "title": "▶︎ Run Test", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test d", - { - "inspect": false - } - ] - } - }, - { - "range": { - "start": { - "line": 13, - "character": 0 - }, - "end": { - "line": 13, - "character": 4 - } - }, - "command": { - "title": "Debug", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test d", - { - "inspect": true - } - ] - } - }, - { - "range": { - "start": { - "line": 14, - "character": 0 - }, - "end": { - "line": 14, - "character": 5 - } - }, - "command": { - "title": "▶︎ Run Test", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test e", - { - "inspect": false - } - ] - } - }, - { - "range": { - "start": { - "line": 14, - "character": 0 - }, - "end": { - "line": 14, - "character": 5 - } - }, - "command": { - "title": "Debug", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test e", - { - "inspect": true - } - ] - } - }, - { - "range": { - "start": { - "line": 18, - "character": 0 - }, - "end": { - "line": 18, - "character": 5 - } - }, - "command": { - "title": "▶︎ Run Test", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test f", - { - "inspect": false - } - ] - } - }, - { - "range": { - "start": { - "line": 18, - "character": 0 - }, - "end": { - "line": 18, - "character": 5 - } - }, - "command": { - "title": "Debug", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test f", - { - "inspect": true - } - ] - } - }, - { - "range": { - "start": { - "line": 19, - "character": 0 - }, - "end": { - "line": 19, - "character": 5 - } - }, - "command": { - "title": "▶︎ Run Test", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test g", - { - "inspect": false - } - ] - } - }, - { - "range": { - "start": { - "line": 19, - "character": 0 - }, - "end": { - "line": 19, - "character": 5 - } - }, - "command": { - "title": "Debug", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test g", - { - "inspect": true - } - ] - } - }, - { - "range": { - "start": { - "line": 23, - "character": 0 - }, - "end": { - "line": 23, - "character": 5 - } - }, - "command": { - "title": "▶︎ Run Test", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test h", - { - "inspect": false - } - ] - } - }, - { - "range": { - "start": { - "line": 23, - "character": 0 - }, - "end": { - "line": 23, - "character": 5 - } - }, - "command": { - "title": "Debug", - "command": "deno.test", - "arguments": [ - "file:///a/file.ts", - "test h", - { - "inspect": true - } - ] - } - } -] diff --git a/cli/tests/testdata/lsp/diagnostics_deno_deps.json b/cli/tests/testdata/lsp/diagnostics_deno_deps.json deleted file mode 100644 index ec6cc4f516b652..00000000000000 --- a/cli/tests/testdata/lsp/diagnostics_deno_deps.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "uri": "file:///a/file.ts", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 19 - }, - "end": { - "line": 0, - "character": 49 - } - }, - "severity": 1, - "code": "no-cache", - "source": "deno", - "message": "Uncached or missing remote URL: \"https://deno.land/x/a/mod.ts\".", - "data": { - "specifier": "https://deno.land/x/a/mod.ts" - } - } - ], - "version": 1 -} diff --git a/cli/tests/testdata/lsp/did_open_params_test_code_lens.json b/cli/tests/testdata/lsp/did_open_params_test_code_lens.json deleted file mode 100644 index dcb9e11f30af42..00000000000000 --- a/cli/tests/testdata/lsp/did_open_params_test_code_lens.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts", - "languageId": "typescript", - "version": 1, - "text": "const { test } = Deno;\nconst { test: test2 } = Deno;\nconst test3 = Deno.test;\n\nDeno.test(\"test a\", () => {});\nDeno.test({\n name: \"test b\",\n fn() {},\n});\ntest({\n name: \"test c\",\n fn() {},\n});\ntest(\"test d\", () => {});\ntest2({\n name: \"test e\",\n fn() {},\n});\ntest2(\"test f\", () => {});\ntest3({\n name: \"test g\",\n fn() {},\n});\ntest3(\"test h\", () => {});\n" - } -} From ead1c95497015432189ad20f67e2a4c1d86db807 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 8 Mar 2023 17:37:43 -0500 Subject: [PATCH 7/9] Remove load_fixture --- cli/tests/integration/lsp_tests.rs | 372 +++++++++- .../lsp/code_action_ignore_lint_params.json | 39 - .../lsp/code_action_params_deadlock.json | 38 - .../lsp/code_action_params_refactor.json | 21 - .../code_action_resolve_params_refactor.json | 20 - ...code_action_resolve_response_refactor.json | 58 -- .../lsp/code_action_response_cache.json | 36 - .../lsp/code_action_response_imports.json | 122 ---- .../lsp/code_action_response_no_disabled.json | 42 -- .../lsp/code_action_response_refactor.json | 177 ----- .../completion_request_params_optional.json | 13 - .../lsp/completion_resolve_params.json | 14 - .../lsp/completion_resolve_response.json | 11 - .../testdata/lsp/did_open_params_large.json | 8 - .../testdata/lsp/formatting_mbc_response.json | 54 -- cli/tests/testdata/lsp/large_file.txt | 676 ++++++++++++++++++ .../testdata/lsp/outgoing_calls_response.json | 42 -- test_util/src/builders.rs | 6 +- test_util/src/lsp.rs | 4 +- 19 files changed, 1021 insertions(+), 732 deletions(-) delete mode 100644 cli/tests/testdata/lsp/code_action_ignore_lint_params.json delete mode 100644 cli/tests/testdata/lsp/code_action_params_deadlock.json delete mode 100644 cli/tests/testdata/lsp/code_action_params_refactor.json delete mode 100644 cli/tests/testdata/lsp/code_action_resolve_params_refactor.json delete mode 100644 cli/tests/testdata/lsp/code_action_resolve_response_refactor.json delete mode 100644 cli/tests/testdata/lsp/code_action_response_cache.json delete mode 100644 cli/tests/testdata/lsp/code_action_response_imports.json delete mode 100644 cli/tests/testdata/lsp/code_action_response_no_disabled.json delete mode 100644 cli/tests/testdata/lsp/code_action_response_refactor.json delete mode 100644 cli/tests/testdata/lsp/completion_request_params_optional.json delete mode 100644 cli/tests/testdata/lsp/completion_resolve_params.json delete mode 100644 cli/tests/testdata/lsp/completion_resolve_response.json delete mode 100644 cli/tests/testdata/lsp/did_open_params_large.json delete mode 100644 cli/tests/testdata/lsp/formatting_mbc_response.json create mode 100644 cli/tests/testdata/lsp/large_file.txt delete mode 100644 cli/tests/testdata/lsp/outgoing_calls_response.json diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index fc8d7a44eecc29..a48c56b5f377ff 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -1,7 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use deno_ast::ModuleSpecifier; -use deno_core::serde::de::DeserializeOwned; use deno_core::serde::Deserialize; use deno_core::serde::Serialize; use deno_core::serde_json; @@ -20,24 +19,6 @@ use test_util::testdata_path; use test_util::TestContextBuilder; use tower_lsp::lsp_types as lsp; -fn load_fixture(path: &str) -> Value { - load_fixture_as(path) -} - -fn load_fixture_as(path: &str) -> T -where - T: DeserializeOwned, -{ - let fixture_str = load_fixture_str(path); - serde_json::from_str::(&fixture_str).unwrap() -} - -fn load_fixture_str(path: &str) -> String { - let fixtures_path = testdata_path().join("lsp"); - let path = fixtures_path.join(path); - fs::read_to_string(path).unwrap() -} - fn did_open( client: &mut LspClient, params: V, @@ -80,7 +61,7 @@ fn read_diagnostics(client: &mut LspClient) -> CollectedDiagnostics { CollectedDiagnostics(diagnostics) } -// todo(THIS PR): get rid of this in favour of LspClient +// todo(dsherret): get rid of this in favour of LspClient struct TestSession { client: LspClient, open_file_count: usize, @@ -2288,7 +2269,20 @@ fn lsp_call_hierarchy() { fn lsp_large_doc_changes() { let mut client = LspClientBuilder::new().build(); client.initialize_default(); - did_open(&mut client, load_fixture("did_open_params_large.json")); + let large_file_text = + fs::read_to_string(testdata_path().join("lsp").join("large_file.txt")) + .unwrap(); + did_open( + &mut client, + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "javascript", + "version": 1, + "text": large_file_text, + } + }), + ); client .write_notification( "textDocument/didChange", @@ -4038,7 +4032,28 @@ fn lsp_code_actions_deno_cache() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_response_cache.json")) + Some(json!([{ + "title": "Cache \"https://deno.land/x/a/mod.ts\" and its dependencies.", + "kind": "quickfix", + "diagnostics": [{ + "range": { + "start": { "line": 0, "character": 19 }, + "end": { "line": 0, "character": 49 } + }, + "severity": 1, + "code": "no-cache", + "source": "deno", + "message": "Unable to load the remote module: \"https://deno.land/x/a/mod.ts\".", + "data": { + "specifier": "https://deno.land/x/a/mod.ts" + } + }], + "command": { + "title": "", + "command": "deno.cache", + "arguments": [["https://deno.land/x/a/mod.ts"]] + } + }])) ); session.shutdown_and_exit(); } @@ -4400,24 +4415,202 @@ fn lsp_code_actions_refactor() { let (maybe_res, maybe_err) = client .write_request( "textDocument/codeAction", - load_fixture("code_action_params_refactor.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "context": { + "diagnostics": [], + "only": ["refactor"] + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_response_refactor.json")) + Some(json!([{ + "title": "Extract to function in module scope", + "kind": "refactor.extract.function", + "isPreferred": false, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "refactorName": "Extract Symbol", + "actionName": "function_scope_0" + } + }, { + "title": "Extract to constant in enclosing scope", + "kind": "refactor.extract.constant", + "isPreferred": false, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "refactorName": "Extract Symbol", + "actionName": "constant_scope_0" + } + }, { + "title": "Move to a new file", + "kind": "refactor.move.newFile", + "isPreferred": false, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "refactorName": "Move to a new file", + "actionName": "Move to a new file" + } + }, { + "title": "Convert default export to named export", + "kind": "refactor.rewrite.export.named", + "isPreferred": false, + "disabled": { + "reason": "This file already has a default export" + }, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "refactorName": "Convert export", + "actionName": "Convert default export to named export" + } + }, { + "title": "Convert named export to default export", + "kind": "refactor.rewrite.export.default", + "isPreferred": false, + "disabled": { + "reason": "This file already has a default export" + }, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "refactorName": "Convert export", + "actionName": "Convert named export to default export" + } + }, { + "title": "Convert namespace import to named imports", + "kind": "refactor.rewrite.import.named", + "isPreferred": false, + "disabled": { + "reason": "Selection is not an import declaration." + }, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "refactorName": "Convert import", + "actionName": "Convert namespace import to named imports" + } + }, { + "title": "Convert named imports to default import", + "kind": "refactor.rewrite.import.default", + "isPreferred": false, + "disabled": { + "reason": "Selection is not an import declaration." + }, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "refactorName": "Convert import", + "actionName": "Convert named imports to default import" + } + }, { + "title": "Convert named imports to namespace import", + "kind": "refactor.rewrite.import.namespace", + "isPreferred": false, + "disabled": { + "reason": "Selection is not an import declaration." + }, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 1, "character": 0 } + }, + "refactorName": "Convert import", + "actionName": "Convert named imports to namespace import" + } + }])) ); let (maybe_res, maybe_err) = client .write_request( "codeAction/resolve", - load_fixture("code_action_resolve_params_refactor.json"), + json!({ + "title": "Extract to interface", + "kind": "refactor.extract.interface", + "isPreferred": true, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 7 }, + "end": { "line": 0, "character": 33 } + }, + "refactorName": "Extract type", + "actionName": "Extract to interface" + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_resolve_response_refactor.json")) + Some(json!({ + "title": "Extract to interface", + "kind": "refactor.extract.interface", + "edit": { + "documentChanges": [{ + "textDocument": { + "uri": "file:///a/file.ts", + "version": 1 + }, + "edits": [{ + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "interface NewType {\n a?: number;\n b?: string;\n}\n\n" + }, { + "range": { + "start": { "line": 0, "character": 7 }, + "end": { "line": 0, "character": 33 } + }, + "newText": "NewType" + }] + }] + }, + "isPreferred": true, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 7 }, + "end": { "line": 0, "character": 33 } + }, + "refactorName": "Extract type", + "actionName": "Extract to interface" + } + })) ); client.shutdown(); } @@ -4466,7 +4659,33 @@ fn lsp_code_actions_refactor_no_disabled_support() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("code_action_response_no_disabled.json")) + Some(json!([{ + "title": "Extract to function in module scope", + "kind": "refactor.extract.function", + "isPreferred": false, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 14, "character": 0 } + }, + "refactorName": "Extract Symbol", + "actionName": "function_scope_0" + } + }, { + "title": "Move to a new file", + "kind": "refactor.move.newFile", + "isPreferred": false, + "data": { + "specifier": "file:///a/file.ts", + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 14, "character": 0 } + }, + "refactorName": "Move to a new file", + "actionName": "Move to a new file" + } + }])) ); client.shutdown(); } @@ -4475,10 +4694,20 @@ fn lsp_code_actions_refactor_no_disabled_support() { fn lsp_code_actions_deadlock() { let mut client = LspClientBuilder::new().build(); client.initialize_default(); + let large_file_text = + fs::read_to_string(testdata_path().join("lsp").join("large_file.txt")) + .unwrap(); client .write_notification( "textDocument/didOpen", - load_fixture("did_open_params_large.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "javascript", + "version": 1, + "text": large_file_text, + } + }), ) .unwrap(); let (id, method, _) = client.read_request::().unwrap(); @@ -4579,7 +4808,28 @@ fn lsp_code_actions_deadlock() { let (maybe_res, maybe_err) = client .write_request::<_, _, Value>( "textDocument/codeAction", - load_fixture("code_action_params_deadlock.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "range": { + "start": { "line": 441, "character": 33 }, + "end": { "line": 441, "character": 42 } + }, + "context": { + "diagnostics": [{ + "range": { + "start": { "line": 441, "character": 33 }, + "end": { "line": 441, "character": 42 } + }, + "severity": 1, + "code": 7031, + "source": "deno-ts", + "message": "Binding element 'debugFlag' implicitly has an 'any' type." + }], + "only": [ "quickfix" ] + } + }), ) .unwrap(); assert!(maybe_err.is_none()); @@ -4630,13 +4880,36 @@ fn lsp_completions() { let (maybe_res, maybe_err) = client .write_request( "completionItem/resolve", - load_fixture("completion_resolve_params.json"), + json!({ + "label": "build", + "kind": 6, + "sortText": "1", + "insertTextFormat": 1, + "data": { + "tsc": { + "specifier": "file:///a/file.ts", + "position": 5, + "name": "build", + "useCodeSnippet": false + } + } + }), ) .unwrap(); assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(load_fixture("completion_resolve_response.json")) + Some(json!({ + "label": "build", + "kind": 6, + "detail": "const Deno.build: {\n target: string;\n arch: \"x86_64\" | \"aarch64\";\n os: \"darwin\" | \"linux\" | \"windows\" | \"freebsd\" | \"netbsd\" | \"aix\" | \"solaris\" | \"illumos\";\n vendor: string;\n env?: string | undefined;\n}", + "documentation": { + "kind": "markdown", + "value": "Information related to the build of the current Deno runtime.\n\nUsers are discouraged from code branching based on this information, as\nassumptions about what is available in what build environment might change\nover time. Developers should specifically sniff out the features they\nintend to use.\n\nThe intended use for the information is for logging and debugging purposes.\n\n*@category* - Runtime Environment" + }, + "sortText": "1", + "insertTextFormat": 1 + })) ); client.shutdown(); } @@ -4700,7 +4973,16 @@ fn lsp_completions_optional() { let (maybe_res, maybe_err) = client .write_request( "textDocument/completion", - load_fixture("completion_request_params_optional.json"), + json!({ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "position": { "line": 8, "character": 4 }, + "context": { + "triggerKind": 2, + "triggerCharacter": "." + } + }), ) .unwrap(); assert!(maybe_err.is_none()); @@ -6469,7 +6751,31 @@ fn lsp_format_mbc() { assert!(maybe_err.is_none()); assert_eq!( maybe_res, - Some(json!(load_fixture("formatting_mbc_response.json"))) + Some(json!([{ + "range": { + "start": { "line": 0, "character": 12 }, + "end": { "line": 0, "character": 13 } + }, + "newText": "\"" + }, { + "range": { + "start": { "line": 0, "character": 21 }, + "end": { "line": 0, "character": 22 } + }, + "newText": "\";" + }, { + "range": { + "start": { "line": 1, "character": 12 }, + "end": { "line": 1, "character": 13 } + }, + "newText": "\"" + }, { + "range": { + "start": { "line": 1, "character": 23 }, + "end": { "line": 1, "character": 25 } + }, + "newText": "\");" + }])) ); client.shutdown(); } diff --git a/cli/tests/testdata/lsp/code_action_ignore_lint_params.json b/cli/tests/testdata/lsp/code_action_ignore_lint_params.json deleted file mode 100644 index 7711812fdb10ee..00000000000000 --- a/cli/tests/testdata/lsp/code_action_ignore_lint_params.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts" - }, - "range": { - "start": { - "line": 1, - "character": 5 - }, - "end": { - "line": 1, - "character": 12 - } - }, - "context": { - "diagnostics": [ - { - "range": { - "start": { - "line": 1, - "character": 5 - }, - "end": { - "line": 1, - "character": 12 - } - }, - "severity": 1, - "code": "prefer-const", - "source": "deno-lint", - "message": "'message' is never reassigned\nUse 'const' instead", - "relatedInformation": [] - } - ], - "only": [ - "quickfix" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_action_params_deadlock.json b/cli/tests/testdata/lsp/code_action_params_deadlock.json deleted file mode 100644 index be0e317e1dfe14..00000000000000 --- a/cli/tests/testdata/lsp/code_action_params_deadlock.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts" - }, - "range": { - "start": { - "line": 441, - "character": 33 - }, - "end": { - "line": 441, - "character": 42 - } - }, - "context": { - "diagnostics": [ - { - "range": { - "start": { - "line": 441, - "character": 33 - }, - "end": { - "line": 441, - "character": 42 - } - }, - "severity": 1, - "code": 7031, - "source": "deno-ts", - "message": "Binding element 'debugFlag' implicitly has an 'any' type." - } - ], - "only": [ - "quickfix" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_action_params_refactor.json b/cli/tests/testdata/lsp/code_action_params_refactor.json deleted file mode 100644 index 121c400ed90e67..00000000000000 --- a/cli/tests/testdata/lsp/code_action_params_refactor.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts" - }, - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "context": { - "diagnostics": [], - "only": [ - "refactor" - ] - } -} diff --git a/cli/tests/testdata/lsp/code_action_resolve_params_refactor.json b/cli/tests/testdata/lsp/code_action_resolve_params_refactor.json deleted file mode 100644 index d4bb3bd81c5c7b..00000000000000 --- a/cli/tests/testdata/lsp/code_action_resolve_params_refactor.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "title": "Extract to interface", - "kind": "refactor.extract.interface", - "isPreferred": true, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 7 - }, - "end": { - "line": 0, - "character": 33 - } - }, - "refactorName": "Extract type", - "actionName": "Extract to interface" - } -} diff --git a/cli/tests/testdata/lsp/code_action_resolve_response_refactor.json b/cli/tests/testdata/lsp/code_action_resolve_response_refactor.json deleted file mode 100644 index 721a76a6b82b11..00000000000000 --- a/cli/tests/testdata/lsp/code_action_resolve_response_refactor.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "title": "Extract to interface", - "kind": "refactor.extract.interface", - "edit": { - "documentChanges": [ - { - "textDocument": { - "uri": "file:///a/file.ts", - "version": 1 - }, - "edits": [ - { - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 0, - "character": 0 - } - }, - "newText": "interface NewType {\n a?: number;\n b?: string;\n}\n\n" - }, - { - "range": { - "start": { - "line": 0, - "character": 7 - }, - "end": { - "line": 0, - "character": 33 - } - }, - "newText": "NewType" - } - ] - } - ] - }, - "isPreferred": true, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 7 - }, - "end": { - "line": 0, - "character": 33 - } - }, - "refactorName": "Extract type", - "actionName": "Extract to interface" - } -} diff --git a/cli/tests/testdata/lsp/code_action_response_cache.json b/cli/tests/testdata/lsp/code_action_response_cache.json deleted file mode 100644 index c56b350233e17c..00000000000000 --- a/cli/tests/testdata/lsp/code_action_response_cache.json +++ /dev/null @@ -1,36 +0,0 @@ -[ - { - "title": "Cache \"https://deno.land/x/a/mod.ts\" and its dependencies.", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 19 - }, - "end": { - "line": 0, - "character": 49 - } - }, - "severity": 1, - "code": "no-cache", - "source": "deno", - "message": "Unable to load the remote module: \"https://deno.land/x/a/mod.ts\".", - "data": { - "specifier": "https://deno.land/x/a/mod.ts" - } - } - ], - "command": { - "title": "", - "command": "deno.cache", - "arguments": [ - [ - "https://deno.land/x/a/mod.ts" - ] - ] - } - } -] diff --git a/cli/tests/testdata/lsp/code_action_response_imports.json b/cli/tests/testdata/lsp/code_action_response_imports.json deleted file mode 100644 index 23eb6645d3e0a5..00000000000000 --- a/cli/tests/testdata/lsp/code_action_response_imports.json +++ /dev/null @@ -1,122 +0,0 @@ -[ - { - "title": "Add import from \"./file02.ts\"", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 50 - }, - "end": { - "line": 0, - "character": 67 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfigOptions'." - } - ], - "edit": { - "documentChanges": [ - { - "textDocument": { - "uri": "file:///a/file00.ts", - "version": 1 - }, - "edits": [ - { - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 0, - "character": 0 - } - }, - "newText": "import { DuckConfigOptions } from \"./file02.ts\";\n\n" - } - ] - } - ] - } - }, - { - "title": "Add all missing imports", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 0, - "character": 50 - }, - "end": { - "line": 0, - "character": 67 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfigOptions'." - } - ], - "data": { - "specifier": "file:///a/file00.ts", - "fixId": "fixMissingImport" - } - }, - { - "title": "Add import from \"./file01.ts\"", - "kind": "quickfix", - "diagnostics": [ - { - "range": { - "start": { - "line": 4, - "character": 39 - }, - "end": { - "line": 4, - "character": 49 - } - }, - "severity": 1, - "code": 2304, - "source": "deno-ts", - "message": "Cannot find name 'DuckConfig'." - } - ], - "edit": { - "documentChanges": [ - { - "textDocument": { - "uri": "file:///a/file00.ts", - "version": 1 - }, - "edits": [ - { - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 0, - "character": 0 - } - }, - "newText": "import { DuckConfig } from \"./file01.ts\";\n\n" - } - ] - } - ] - } - } -] diff --git a/cli/tests/testdata/lsp/code_action_response_no_disabled.json b/cli/tests/testdata/lsp/code_action_response_no_disabled.json deleted file mode 100644 index 11d2136b5e3030..00000000000000 --- a/cli/tests/testdata/lsp/code_action_response_no_disabled.json +++ /dev/null @@ -1,42 +0,0 @@ -[ - { - "title": "Extract to function in module scope", - "kind": "refactor.extract.function", - "isPreferred": false, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 14, - "character": 0 - } - }, - "refactorName": "Extract Symbol", - "actionName": "function_scope_0" - } - }, - { - "title": "Move to a new file", - "kind": "refactor.move.newFile", - "isPreferred": false, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 14, - "character": 0 - } - }, - "refactorName": "Move to a new file", - "actionName": "Move to a new file" - } - } -] diff --git a/cli/tests/testdata/lsp/code_action_response_refactor.json b/cli/tests/testdata/lsp/code_action_response_refactor.json deleted file mode 100644 index d0d9fb0ee2e36d..00000000000000 --- a/cli/tests/testdata/lsp/code_action_response_refactor.json +++ /dev/null @@ -1,177 +0,0 @@ -[ - { - "title": "Extract to function in module scope", - "kind": "refactor.extract.function", - "isPreferred": false, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "refactorName": "Extract Symbol", - "actionName": "function_scope_0" - } - }, - { - "title": "Extract to constant in enclosing scope", - "kind": "refactor.extract.constant", - "isPreferred": false, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "refactorName": "Extract Symbol", - "actionName": "constant_scope_0" - } - }, - { - "title": "Move to a new file", - "kind": "refactor.move.newFile", - "isPreferred": false, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "refactorName": "Move to a new file", - "actionName": "Move to a new file" - } - }, - { - "title": "Convert default export to named export", - "kind": "refactor.rewrite.export.named", - "isPreferred": false, - "disabled": { - "reason": "This file already has a default export" - }, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "refactorName": "Convert export", - "actionName": "Convert default export to named export" - } - }, - { - "title": "Convert named export to default export", - "kind": "refactor.rewrite.export.default", - "isPreferred": false, - "disabled": { - "reason": "This file already has a default export" - }, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "refactorName": "Convert export", - "actionName": "Convert named export to default export" - } - }, - { - "title": "Convert namespace import to named imports", - "kind": "refactor.rewrite.import.named", - "isPreferred": false, - "disabled": { - "reason": "Selection is not an import declaration." - }, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "refactorName": "Convert import", - "actionName": "Convert namespace import to named imports" - } - }, - { - "title": "Convert named imports to default import", - "kind": "refactor.rewrite.import.default", - "isPreferred": false, - "disabled": { - "reason": "Selection is not an import declaration." - }, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "refactorName": "Convert import", - "actionName": "Convert named imports to default import" - } - }, - { - "title": "Convert named imports to namespace import", - "kind": "refactor.rewrite.import.namespace", - "isPreferred": false, - "disabled": { - "reason": "Selection is not an import declaration." - }, - "data": { - "specifier": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 1, - "character": 0 - } - }, - "refactorName": "Convert import", - "actionName": "Convert named imports to namespace import" - } - } -] diff --git a/cli/tests/testdata/lsp/completion_request_params_optional.json b/cli/tests/testdata/lsp/completion_request_params_optional.json deleted file mode 100644 index 1f3c079c738d82..00000000000000 --- a/cli/tests/testdata/lsp/completion_request_params_optional.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts" - }, - "position": { - "line": 8, - "character": 4 - }, - "context": { - "triggerKind": 2, - "triggerCharacter": "." - } -} diff --git a/cli/tests/testdata/lsp/completion_resolve_params.json b/cli/tests/testdata/lsp/completion_resolve_params.json deleted file mode 100644 index 26231036da156f..00000000000000 --- a/cli/tests/testdata/lsp/completion_resolve_params.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "label": "build", - "kind": 6, - "sortText": "1", - "insertTextFormat": 1, - "data": { - "tsc": { - "specifier": "file:///a/file.ts", - "position": 5, - "name": "build", - "useCodeSnippet": false - } - } -} diff --git a/cli/tests/testdata/lsp/completion_resolve_response.json b/cli/tests/testdata/lsp/completion_resolve_response.json deleted file mode 100644 index 28ad756a332e01..00000000000000 --- a/cli/tests/testdata/lsp/completion_resolve_response.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "label": "build", - "kind": 6, - "detail": "const Deno.build: {\n target: string;\n arch: \"x86_64\" | \"aarch64\";\n os: \"darwin\" | \"linux\" | \"windows\" | \"freebsd\" | \"netbsd\" | \"aix\" | \"solaris\" | \"illumos\";\n vendor: string;\n env?: string | undefined;\n}", - "documentation": { - "kind": "markdown", - "value": "Information related to the build of the current Deno runtime.\n\nUsers are discouraged from code branching based on this information, as\nassumptions about what is available in what build environment might change\nover time. Developers should specifically sniff out the features they\nintend to use.\n\nThe intended use for the information is for logging and debugging purposes.\n\n*@category* - Runtime Environment" - }, - "sortText": "1", - "insertTextFormat": 1 -} diff --git a/cli/tests/testdata/lsp/did_open_params_large.json b/cli/tests/testdata/lsp/did_open_params_large.json deleted file mode 100644 index 0347ab67b27bbf..00000000000000 --- a/cli/tests/testdata/lsp/did_open_params_large.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "textDocument": { - "uri": "file:///a/file.ts", - "languageId": "javascript", - "version": 1, - "text": "// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.\n\n// @ts-check\n/// \n// deno-lint-ignore-file no-undef\n\n// This module is the entry point for \"compiler\" isolate, ie. the one\n// that is created when Deno needs to type check TypeScript, and in some\n// instances convert TypeScript to JavaScript.\n\n// Removes the `__proto__` for security reasons. This intentionally makes\n// Deno non compliant with ECMA-262 Annex B.2.2.1\ndelete Object.prototype.__proto__;\n\n((window) => {\n /** @type {DenoCore} */\n const core = window.Deno.core;\n\n let logDebug = false;\n let logSource = \"JS\";\n\n function setLogDebug(debug, source) {\n logDebug = debug;\n if (source) {\n logSource = source;\n }\n }\n\n function debug(...args) {\n if (logDebug) {\n const stringifiedArgs = args.map((arg) =>\n typeof arg === \"string\" ? arg : JSON.stringify(arg)\n ).join(\" \");\n // adding a non-zero integer value to the end of the debug string causes\n // the message to be printed to stderr instead of stdout, which is better\n // aligned to the behaviour of debug messages\n core.print(`DEBUG ${logSource} - ${stringifiedArgs}\\n`, 1);\n }\n }\n\n function error(...args) {\n const stringifiedArgs = args.map((arg) =>\n typeof arg === \"string\" || arg instanceof Error\n ? String(arg)\n : JSON.stringify(arg)\n ).join(\" \");\n core.print(`ERROR ${logSource} = ${stringifiedArgs}\\n`, 1);\n }\n\n class AssertionError extends Error {\n constructor(msg) {\n super(msg);\n this.name = \"AssertionError\";\n }\n }\n\n function assert(cond, msg = \"Assertion failed.\") {\n if (!cond) {\n throw new AssertionError(msg);\n }\n }\n\n /** @type {Map} */\n const sourceFileCache = new Map();\n\n /** @param {ts.DiagnosticRelatedInformation} diagnostic */\n function fromRelatedInformation({\n start,\n length,\n file,\n messageText: msgText,\n ...ri\n }) {\n let messageText;\n let messageChain;\n if (typeof msgText === \"object\") {\n messageChain = msgText;\n } else {\n messageText = msgText;\n }\n if (start !== undefined && length !== undefined && file) {\n const startPos = file.getLineAndCharacterOfPosition(start);\n const sourceLine = file.getFullText().split(\"\\n\")[startPos.line];\n const fileName = file.fileName;\n return {\n start: startPos,\n end: file.getLineAndCharacterOfPosition(start + length),\n fileName,\n messageChain,\n messageText,\n sourceLine,\n ...ri,\n };\n } else {\n return {\n messageChain,\n messageText,\n ...ri,\n };\n }\n }\n\n /** @param {ts.Diagnostic[]} diagnostics */\n function fromTypeScriptDiagnostic(diagnostics) {\n return diagnostics.map(({ relatedInformation: ri, source, ...diag }) => {\n /** @type {any} */\n const value = fromRelatedInformation(diag);\n value.relatedInformation = ri\n ? ri.map(fromRelatedInformation)\n : undefined;\n value.source = source;\n return value;\n });\n }\n\n // Using incremental compile APIs requires that all\n // paths must be either relative or absolute. Since\n // analysis in Rust operates on fully resolved URLs,\n // it makes sense to use the same scheme here.\n const ASSETS = \"asset:///\";\n const CACHE = \"cache:///\";\n\n /** Diagnostics that are intentionally ignored when compiling TypeScript in\n * Deno, as they provide misleading or incorrect information. */\n const IGNORED_DIAGNOSTICS = [\n // TS1208: All files must be modules when the '--isolatedModules' flag is\n // provided. We can ignore because we guarantee that all files are\n // modules.\n 1208,\n // TS1375: 'await' expressions are only allowed at the top level of a file\n // when that file is a module, but this file has no imports or exports.\n // Consider adding an empty 'export {}' to make this file a module.\n 1375,\n // TS1103: 'for-await-of' statement is only allowed within an async function\n // or async generator.\n 1103,\n // TS2306: File 'file:///Users/rld/src/deno/subdir/amd_like.js' is\n // not a module.\n 2306,\n // TS2691: An import path cannot end with a '.ts' extension. Consider\n // importing 'bad-module' instead.\n 2691,\n // TS2792: Cannot find module. Did you mean to set the 'moduleResolution'\n // option to 'node', or to add aliases to the 'paths' option?\n 2792,\n // TS5009: Cannot find the common subdirectory path for the input files.\n 5009,\n // TS5055: Cannot write file\n // 'http://localhost:4545/subdir/mt_application_x_javascript.j4.js'\n // because it would overwrite input file.\n 5055,\n // TypeScript is overly opinionated that only CommonJS modules kinds can\n // support JSON imports. Allegedly this was fixed in\n // Microsoft/TypeScript#26825 but that doesn't seem to be working here,\n // so we will ignore complaints about this compiler setting.\n 5070,\n // TS7016: Could not find a declaration file for module '...'. '...'\n // implicitly has an 'any' type. This is due to `allowJs` being off by\n // default but importing of a JavaScript module.\n 7016,\n ];\n\n const SNAPSHOT_COMPILE_OPTIONS = {\n esModuleInterop: true,\n jsx: ts.JsxEmit.React,\n module: ts.ModuleKind.ESNext,\n noEmit: true,\n strict: true,\n target: ts.ScriptTarget.ESNext,\n };\n\n class ScriptSnapshot {\n /** @type {string} */\n specifier;\n /** @type {string} */\n version;\n /**\n * @param {string} specifier\n * @param {string} version \n */\n constructor(specifier, version) {\n this.specifier = specifier;\n this.version = version;\n }\n /**\n * @param {number} start \n * @param {number} end \n * @returns {string}\n */\n getText(start, end) {\n const { specifier, version } = this;\n debug(\n `snapshot.getText(${start}, ${end}) specifier: ${specifier} version: ${version}`,\n );\n return core.jsonOpSync(\"op_get_text\", { specifier, version, start, end });\n }\n /**\n * @returns {number}\n */\n getLength() {\n const { specifier, version } = this;\n debug(`snapshot.getLength() specifier: ${specifier} version: ${version}`);\n return core.jsonOpSync(\"op_get_length\", { specifier, version });\n }\n /**\n * @param {ScriptSnapshot} oldSnapshot\n * @returns {ts.TextChangeRange | undefined}\n */\n getChangeRange(oldSnapshot) {\n const { specifier, version } = this;\n const { version: oldVersion } = oldSnapshot;\n const oldLength = oldSnapshot.getLength();\n debug(\n `snapshot.getLength() specifier: ${specifier} oldVersion: ${oldVersion} version: ${version}`,\n );\n return core.jsonOpSync(\n \"op_get_change_range\",\n { specifier, oldLength, oldVersion, version },\n );\n }\n dispose() {\n const { specifier, version } = this;\n debug(`snapshot.dispose() specifier: ${specifier} version: ${version}`);\n core.jsonOpSync(\"op_dispose\", { specifier, version });\n }\n }\n\n /** @type {ts.CompilerOptions} */\n let compilationSettings = {};\n\n /** @type {ts.LanguageService} */\n let languageService;\n\n /** An object literal of the incremental compiler host, which provides the\n * specific \"bindings\" to the Deno environment that tsc needs to work.\n *\n * @type {ts.CompilerHost & ts.LanguageServiceHost} */\n const host = {\n fileExists(fileName) {\n debug(`host.fileExists(\"${fileName}\")`);\n return false;\n },\n readFile(specifier) {\n debug(`host.readFile(\"${specifier}\")`);\n return core.jsonOpSync(\"op_load\", { specifier }).data;\n },\n getSourceFile(\n specifier,\n languageVersion,\n _onError,\n _shouldCreateNewSourceFile,\n ) {\n debug(\n `host.getSourceFile(\"${specifier}\", ${\n ts.ScriptTarget[languageVersion]\n })`,\n );\n let sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return sourceFile;\n }\n\n /** @type {{ data: string; hash?: string; scriptKind: ts.ScriptKind }} */\n const { data, hash, scriptKind } = core.jsonOpSync(\n \"op_load\",\n { specifier },\n );\n assert(\n data != null,\n `\"data\" is unexpectedly null for \"${specifier}\".`,\n );\n sourceFile = ts.createSourceFile(\n specifier,\n data,\n languageVersion,\n false,\n scriptKind,\n );\n sourceFile.moduleName = specifier;\n sourceFile.version = hash;\n sourceFileCache.set(specifier, sourceFile);\n return sourceFile;\n },\n getDefaultLibFileName() {\n return `${ASSETS}/lib.esnext.d.ts`;\n },\n getDefaultLibLocation() {\n return ASSETS;\n },\n writeFile(fileName, data, _writeByteOrderMark, _onError, sourceFiles) {\n debug(`host.writeFile(\"${fileName}\")`);\n let maybeSpecifiers;\n if (sourceFiles) {\n maybeSpecifiers = sourceFiles.map((sf) => sf.moduleName);\n }\n return core.jsonOpSync(\n \"op_emit\",\n { maybeSpecifiers, fileName, data },\n );\n },\n getCurrentDirectory() {\n return CACHE;\n },\n getCanonicalFileName(fileName) {\n return fileName;\n },\n useCaseSensitiveFileNames() {\n return true;\n },\n getNewLine() {\n return \"\\n\";\n },\n resolveModuleNames(specifiers, base) {\n debug(`host.resolveModuleNames()`);\n debug(` base: ${base}`);\n debug(` specifiers: ${specifiers.join(\", \")}`);\n /** @type {Array<[string, ts.Extension] | undefined>} */\n const resolved = core.jsonOpSync(\"op_resolve\", {\n specifiers,\n base,\n });\n if (resolved) {\n const result = resolved.map((item) => {\n if (item) {\n const [resolvedFileName, extension] = item;\n return {\n resolvedFileName,\n extension,\n isExternalLibraryImport: false,\n };\n }\n return undefined;\n });\n result.length = specifiers.length;\n return result;\n } else {\n return new Array(specifiers.length);\n }\n },\n createHash(data) {\n return core.jsonOpSync(\"op_create_hash\", { data }).hash;\n },\n\n // LanguageServiceHost\n getCompilationSettings() {\n debug(\"host.getCompilationSettings()\");\n return compilationSettings;\n },\n getScriptFileNames() {\n debug(\"host.getScriptFileNames()\");\n return core.jsonOpSync(\"op_script_names\", undefined);\n },\n getScriptVersion(specifier) {\n debug(`host.getScriptVersion(\"${specifier}\")`);\n const sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return sourceFile.version ?? \"1\";\n }\n return core.jsonOpSync(\"op_script_version\", { specifier });\n },\n getScriptSnapshot(specifier) {\n debug(`host.getScriptSnapshot(\"${specifier}\")`);\n const sourceFile = sourceFileCache.get(specifier);\n if (sourceFile) {\n return {\n getText(start, end) {\n return sourceFile.text.substring(start, end);\n },\n getLength() {\n return sourceFile.text.length;\n },\n getChangeRange() {\n return undefined;\n },\n };\n }\n /** @type {string | undefined} */\n const version = core.jsonOpSync(\"op_script_version\", { specifier });\n if (version != null) {\n return new ScriptSnapshot(specifier, version);\n }\n return undefined;\n },\n };\n\n /** @type {Array<[string, number]>} */\n const stats = [];\n let statsStart = 0;\n\n function performanceStart() {\n stats.length = 0;\n statsStart = Date.now();\n ts.performance.enable();\n }\n\n /**\n * @param {{ program: ts.Program | ts.EmitAndSemanticDiagnosticsBuilderProgram, fileCount?: number }} options \n */\n function performanceProgram({ program, fileCount }) {\n if (program) {\n if (\"getProgram\" in program) {\n program = program.getProgram();\n }\n stats.push([\"Files\", program.getSourceFiles().length]);\n stats.push([\"Nodes\", program.getNodeCount()]);\n stats.push([\"Identifiers\", program.getIdentifierCount()]);\n stats.push([\"Symbols\", program.getSymbolCount()]);\n stats.push([\"Types\", program.getTypeCount()]);\n stats.push([\"Instantiations\", program.getInstantiationCount()]);\n } else if (fileCount != null) {\n stats.push([\"Files\", fileCount]);\n }\n const programTime = ts.performance.getDuration(\"Program\");\n const bindTime = ts.performance.getDuration(\"Bind\");\n const checkTime = ts.performance.getDuration(\"Check\");\n const emitTime = ts.performance.getDuration(\"Emit\");\n stats.push([\"Parse time\", programTime]);\n stats.push([\"Bind time\", bindTime]);\n stats.push([\"Check time\", checkTime]);\n stats.push([\"Emit time\", emitTime]);\n stats.push(\n [\"Total TS time\", programTime + bindTime + checkTime + emitTime],\n );\n }\n\n function performanceEnd() {\n const duration = Date.now() - statsStart;\n stats.push([\"Compile time\", duration]);\n return stats;\n }\n\n /**\n * @typedef {object} Request\n * @property {Record} config\n * @property {boolean} debug\n * @property {string[]} rootNames\n */\n\n /** The API that is called by Rust when executing a request.\n * @param {Request} request\n */\n function exec({ config, debug: debugFlag, rootNames }) {\n setLogDebug(debugFlag, \"TS\");\n performanceStart();\n debug(\">>> exec start\", { rootNames });\n debug(config);\n\n const { options, errors: configFileParsingDiagnostics } = ts\n .convertCompilerOptionsFromJson(config, \"\");\n // The `allowNonTsExtensions` is a \"hidden\" compiler option used in VSCode\n // which is not allowed to be passed in JSON, we need it to allow special\n // URLs which Deno supports. So we need to either ignore the diagnostic, or\n // inject it ourselves.\n Object.assign(options, { allowNonTsExtensions: true });\n const program = ts.createIncrementalProgram({\n rootNames,\n options,\n host,\n configFileParsingDiagnostics,\n });\n\n const { diagnostics: emitDiagnostics } = program.emit();\n\n const diagnostics = [\n ...program.getConfigFileParsingDiagnostics(),\n ...program.getSyntacticDiagnostics(),\n ...program.getOptionsDiagnostics(),\n ...program.getGlobalDiagnostics(),\n ...program.getSemanticDiagnostics(),\n ...emitDiagnostics,\n ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code));\n performanceProgram({ program });\n\n core.jsonOpSync(\"op_respond\", {\n diagnostics: fromTypeScriptDiagnostic(diagnostics),\n stats: performanceEnd(),\n });\n debug(\"<<< exec stop\");\n }\n\n /**\n * @param {number} id \n * @param {any} data \n */\n function respond(id, data = null) {\n core.jsonOpSync(\"op_respond\", { id, data });\n }\n\n /**\n * @param {LanguageServerRequest} request \n */\n function serverRequest({ id, ...request }) {\n debug(`serverRequest()`, { id, ...request });\n switch (request.method) {\n case \"configure\": {\n const { options, errors } = ts\n .convertCompilerOptionsFromJson(request.compilerOptions, \"\");\n Object.assign(options, { allowNonTsExtensions: true });\n if (errors.length) {\n debug(ts.formatDiagnostics(errors, host));\n }\n compilationSettings = options;\n return respond(id, true);\n }\n case \"getAsset\": {\n const sourceFile = host.getSourceFile(\n request.specifier,\n ts.ScriptTarget.ESNext,\n );\n return respond(id, sourceFile && sourceFile.text);\n }\n case \"getDiagnostics\": {\n try {\n /** @type {Record} */\n const diagnosticMap = {};\n for (const specifier of request.specifiers) {\n diagnosticMap[specifier] = fromTypeScriptDiagnostic([\n ...languageService.getSemanticDiagnostics(specifier),\n ...languageService.getSuggestionDiagnostics(specifier),\n ...languageService.getSyntacticDiagnostics(specifier),\n ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code)));\n }\n return respond(id, diagnosticMap);\n } catch (e) {\n if (\"stack\" in e) {\n error(e.stack);\n } else {\n error(e);\n }\n return respond(id, {});\n }\n }\n case \"getQuickInfo\": {\n return respond(\n id,\n languageService.getQuickInfoAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getCompletions\": {\n return respond(\n id,\n languageService.getCompletionsAtPosition(\n request.specifier,\n request.position,\n request.preferences,\n ),\n );\n }\n case \"getDocumentHighlights\": {\n return respond(\n id,\n languageService.getDocumentHighlights(\n request.specifier,\n request.position,\n request.filesToSearch,\n ),\n );\n }\n case \"getReferences\": {\n return respond(\n id,\n languageService.getReferencesAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getDefinition\": {\n return respond(\n id,\n languageService.getDefinitionAndBoundSpan(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"getImplementation\": {\n return respond(\n id,\n languageService.getImplementationAtPosition(\n request.specifier,\n request.position,\n ),\n );\n }\n case \"findRenameLocations\": {\n return respond(\n id,\n languageService.findRenameLocations(\n request.specifier,\n request.position,\n request.findInStrings,\n request.findInComments,\n request.providePrefixAndSuffixTextForRename,\n ),\n );\n }\n default:\n throw new TypeError(\n // @ts-ignore exhausted case statement sets type to never\n `Invalid request method for request: \"${request.method}\" (${id})`,\n );\n }\n }\n\n /** @param {{ debug: boolean; }} init */\n function serverInit({ debug: debugFlag }) {\n if (hasStarted) {\n throw new Error(\"The language server has already been initialized.\");\n }\n hasStarted = true;\n languageService = ts.createLanguageService(host);\n core.ops();\n setLogDebug(debugFlag, \"TSLS\");\n debug(\"serverInit()\");\n }\n\n let hasStarted = false;\n\n /** Startup the runtime environment, setting various flags.\n * @param {{ debugFlag?: boolean; legacyFlag?: boolean; }} msg\n */\n function startup({ debugFlag = false }) {\n if (hasStarted) {\n throw new Error(\"The compiler runtime already started.\");\n }\n hasStarted = true;\n core.ops();\n setLogDebug(!!debugFlag, \"TS\");\n }\n\n // Setup the compiler runtime during the build process.\n core.ops();\n core.registerErrorClass(\"Error\", Error);\n\n // A build time only op that provides some setup information that is used to\n // ensure the snapshot is setup properly.\n /** @type {{ buildSpecifier: string; libs: string[] }} */\n const { buildSpecifier, libs } = core.jsonOpSync(\"op_build_info\", {});\n for (const lib of libs) {\n const specifier = `lib.${lib}.d.ts`;\n // we are using internal APIs here to \"inject\" our custom libraries into\n // tsc, so things like `\"lib\": [ \"deno.ns\" ]` are supported.\n if (!ts.libs.includes(lib)) {\n ts.libs.push(lib);\n ts.libMap.set(lib, `lib.${lib}.d.ts`);\n }\n // we are caching in memory common type libraries that will be re-used by\n // tsc on when the snapshot is restored\n assert(\n host.getSourceFile(`${ASSETS}${specifier}`, ts.ScriptTarget.ESNext),\n );\n }\n // this helps ensure as much as possible is in memory that is re-usable\n // before the snapshotting is done, which helps unsure fast \"startup\" for\n // subsequent uses of tsc in Deno.\n const TS_SNAPSHOT_PROGRAM = ts.createProgram({\n rootNames: [buildSpecifier],\n options: SNAPSHOT_COMPILE_OPTIONS,\n host,\n });\n ts.getPreEmitDiagnostics(TS_SNAPSHOT_PROGRAM);\n\n // exposes the two functions that are called by `tsc::exec()` when type\n // checking TypeScript.\n globalThis.startup = startup;\n globalThis.exec = exec;\n\n // exposes the functions that are called when the compiler is used as a\n // language service.\n globalThis.serverInit = serverInit;\n globalThis.serverRequest = serverRequest;\n})(this);\n" - } -} diff --git a/cli/tests/testdata/lsp/formatting_mbc_response.json b/cli/tests/testdata/lsp/formatting_mbc_response.json deleted file mode 100644 index 1c0b9f8e890637..00000000000000 --- a/cli/tests/testdata/lsp/formatting_mbc_response.json +++ /dev/null @@ -1,54 +0,0 @@ -[ - { - "range": { - "start": { - "line": 0, - "character": 12 - }, - "end": { - "line": 0, - "character": 13 - } - }, - "newText": "\"" - }, - { - "range": { - "start": { - "line": 0, - "character": 21 - }, - "end": { - "line": 0, - "character": 22 - } - }, - "newText": "\";" - }, - { - "range": { - "start": { - "line": 1, - "character": 12 - }, - "end": { - "line": 1, - "character": 13 - } - }, - "newText": "\"" - }, - { - "range": { - "start": { - "line": 1, - "character": 23 - }, - "end": { - "line": 1, - "character": 25 - } - }, - "newText": "\");" - } -] diff --git a/cli/tests/testdata/lsp/large_file.txt b/cli/tests/testdata/lsp/large_file.txt new file mode 100644 index 00000000000000..f1ca0481c6efeb --- /dev/null +++ b/cli/tests/testdata/lsp/large_file.txt @@ -0,0 +1,676 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +// @ts-check +/// +// deno-lint-ignore-file no-undef + +// This module is the entry point for "compiler" isolate, ie. the one +// that is created when Deno needs to type check TypeScript, and in some +// instances convert TypeScript to JavaScript. + +// Removes the `__proto__` for security reasons. This intentionally makes +// Deno non compliant with ECMA-262 Annex B.2.2.1 +delete Object.prototype.__proto__; + +((window) => { + /** @type {DenoCore} */ + const core = window.Deno.core; + + let logDebug = false; + let logSource = "JS"; + + function setLogDebug(debug, source) { + logDebug = debug; + if (source) { + logSource = source; + } + } + + function debug(...args) { + if (logDebug) { + const stringifiedArgs = args.map((arg) => + typeof arg === "string" ? arg : JSON.stringify(arg) + ).join(" "); + // adding a non-zero integer value to the end of the debug string causes + // the message to be printed to stderr instead of stdout, which is better + // aligned to the behaviour of debug messages + core.print(`DEBUG ${logSource} - ${stringifiedArgs}\n`, 1); + } + } + + function error(...args) { + const stringifiedArgs = args.map((arg) => + typeof arg === "string" || arg instanceof Error + ? String(arg) + : JSON.stringify(arg) + ).join(" "); + core.print(`ERROR ${logSource} = ${stringifiedArgs}\n`, 1); + } + + class AssertionError extends Error { + constructor(msg) { + super(msg); + this.name = "AssertionError"; + } + } + + function assert(cond, msg = "Assertion failed.") { + if (!cond) { + throw new AssertionError(msg); + } + } + + /** @type {Map} */ + const sourceFileCache = new Map(); + + /** @param {ts.DiagnosticRelatedInformation} diagnostic */ + function fromRelatedInformation({ + start, + length, + file, + messageText: msgText, + ...ri + }) { + let messageText; + let messageChain; + if (typeof msgText === "object") { + messageChain = msgText; + } else { + messageText = msgText; + } + if (start !== undefined && length !== undefined && file) { + const startPos = file.getLineAndCharacterOfPosition(start); + const sourceLine = file.getFullText().split("\n")[startPos.line]; + const fileName = file.fileName; + return { + start: startPos, + end: file.getLineAndCharacterOfPosition(start + length), + fileName, + messageChain, + messageText, + sourceLine, + ...ri, + }; + } else { + return { + messageChain, + messageText, + ...ri, + }; + } + } + + /** @param {ts.Diagnostic[]} diagnostics */ + function fromTypeScriptDiagnostic(diagnostics) { + return diagnostics.map(({ relatedInformation: ri, source, ...diag }) => { + /** @type {any} */ + const value = fromRelatedInformation(diag); + value.relatedInformation = ri + ? ri.map(fromRelatedInformation) + : undefined; + value.source = source; + return value; + }); + } + + // Using incremental compile APIs requires that all + // paths must be either relative or absolute. Since + // analysis in Rust operates on fully resolved URLs, + // it makes sense to use the same scheme here. + const ASSETS = "asset:///"; + const CACHE = "cache:///"; + + /** Diagnostics that are intentionally ignored when compiling TypeScript in + * Deno, as they provide misleading or incorrect information. */ + const IGNORED_DIAGNOSTICS = [ + // TS1208: All files must be modules when the '--isolatedModules' flag is + // provided. We can ignore because we guarantee that all files are + // modules. + 1208, + // TS1375: 'await' expressions are only allowed at the top level of a file + // when that file is a module, but this file has no imports or exports. + // Consider adding an empty 'export {}' to make this file a module. + 1375, + // TS1103: 'for-await-of' statement is only allowed within an async function + // or async generator. + 1103, + // TS2306: File 'file:///Users/rld/src/deno/subdir/amd_like.js' is + // not a module. + 2306, + // TS2691: An import path cannot end with a '.ts' extension. Consider + // importing 'bad-module' instead. + 2691, + // TS2792: Cannot find module. Did you mean to set the 'moduleResolution' + // option to 'node', or to add aliases to the 'paths' option? + 2792, + // TS5009: Cannot find the common subdirectory path for the input files. + 5009, + // TS5055: Cannot write file + // 'http://localhost:4545/subdir/mt_application_x_javascript.j4.js' + // because it would overwrite input file. + 5055, + // TypeScript is overly opinionated that only CommonJS modules kinds can + // support JSON imports. Allegedly this was fixed in + // Microsoft/TypeScript#26825 but that doesn't seem to be working here, + // so we will ignore complaints about this compiler setting. + 5070, + // TS7016: Could not find a declaration file for module '...'. '...' + // implicitly has an 'any' type. This is due to `allowJs` being off by + // default but importing of a JavaScript module. + 7016, + ]; + + const SNAPSHOT_COMPILE_OPTIONS = { + esModuleInterop: true, + jsx: ts.JsxEmit.React, + module: ts.ModuleKind.ESNext, + noEmit: true, + strict: true, + target: ts.ScriptTarget.ESNext, + }; + + class ScriptSnapshot { + /** @type {string} */ + specifier; + /** @type {string} */ + version; + /** + * @param {string} specifier + * @param {string} version + */ + constructor(specifier, version) { + this.specifier = specifier; + this.version = version; + } + /** + * @param {number} start + * @param {number} end + * @returns {string} + */ + getText(start, end) { + const { specifier, version } = this; + debug( + `snapshot.getText(${start}, ${end}) specifier: ${specifier} version: ${version}`, + ); + return core.jsonOpSync("op_get_text", { specifier, version, start, end }); + } + /** + * @returns {number} + */ + getLength() { + const { specifier, version } = this; + debug(`snapshot.getLength() specifier: ${specifier} version: ${version}`); + return core.jsonOpSync("op_get_length", { specifier, version }); + } + /** + * @param {ScriptSnapshot} oldSnapshot + * @returns {ts.TextChangeRange | undefined} + */ + getChangeRange(oldSnapshot) { + const { specifier, version } = this; + const { version: oldVersion } = oldSnapshot; + const oldLength = oldSnapshot.getLength(); + debug( + `snapshot.getLength() specifier: ${specifier} oldVersion: ${oldVersion} version: ${version}`, + ); + return core.jsonOpSync( + "op_get_change_range", + { specifier, oldLength, oldVersion, version }, + ); + } + dispose() { + const { specifier, version } = this; + debug(`snapshot.dispose() specifier: ${specifier} version: ${version}`); + core.jsonOpSync("op_dispose", { specifier, version }); + } + } + + /** @type {ts.CompilerOptions} */ + let compilationSettings = {}; + + /** @type {ts.LanguageService} */ + let languageService; + + /** An object literal of the incremental compiler host, which provides the + * specific "bindings" to the Deno environment that tsc needs to work. + * + * @type {ts.CompilerHost & ts.LanguageServiceHost} */ + const host = { + fileExists(fileName) { + debug(`host.fileExists("${fileName}")`); + return false; + }, + readFile(specifier) { + debug(`host.readFile("${specifier}")`); + return core.jsonOpSync("op_load", { specifier }).data; + }, + getSourceFile( + specifier, + languageVersion, + _onError, + _shouldCreateNewSourceFile, + ) { + debug( + `host.getSourceFile("${specifier}", ${ + ts.ScriptTarget[languageVersion] + })`, + ); + let sourceFile = sourceFileCache.get(specifier); + if (sourceFile) { + return sourceFile; + } + + /** @type {{ data: string; hash?: string; scriptKind: ts.ScriptKind }} */ + const { data, hash, scriptKind } = core.jsonOpSync( + "op_load", + { specifier }, + ); + assert( + data != null, + `"data" is unexpectedly null for "${specifier}".`, + ); + sourceFile = ts.createSourceFile( + specifier, + data, + languageVersion, + false, + scriptKind, + ); + sourceFile.moduleName = specifier; + sourceFile.version = hash; + sourceFileCache.set(specifier, sourceFile); + return sourceFile; + }, + getDefaultLibFileName() { + return `${ASSETS}/lib.esnext.d.ts`; + }, + getDefaultLibLocation() { + return ASSETS; + }, + writeFile(fileName, data, _writeByteOrderMark, _onError, sourceFiles) { + debug(`host.writeFile("${fileName}")`); + let maybeSpecifiers; + if (sourceFiles) { + maybeSpecifiers = sourceFiles.map((sf) => sf.moduleName); + } + return core.jsonOpSync( + "op_emit", + { maybeSpecifiers, fileName, data }, + ); + }, + getCurrentDirectory() { + return CACHE; + }, + getCanonicalFileName(fileName) { + return fileName; + }, + useCaseSensitiveFileNames() { + return true; + }, + getNewLine() { + return "\n"; + }, + resolveModuleNames(specifiers, base) { + debug(`host.resolveModuleNames()`); + debug(` base: ${base}`); + debug(` specifiers: ${specifiers.join(", ")}`); + /** @type {Array<[string, ts.Extension] | undefined>} */ + const resolved = core.jsonOpSync("op_resolve", { + specifiers, + base, + }); + if (resolved) { + const result = resolved.map((item) => { + if (item) { + const [resolvedFileName, extension] = item; + return { + resolvedFileName, + extension, + isExternalLibraryImport: false, + }; + } + return undefined; + }); + result.length = specifiers.length; + return result; + } else { + return new Array(specifiers.length); + } + }, + createHash(data) { + return core.jsonOpSync("op_create_hash", { data }).hash; + }, + + // LanguageServiceHost + getCompilationSettings() { + debug("host.getCompilationSettings()"); + return compilationSettings; + }, + getScriptFileNames() { + debug("host.getScriptFileNames()"); + return core.jsonOpSync("op_script_names", undefined); + }, + getScriptVersion(specifier) { + debug(`host.getScriptVersion("${specifier}")`); + const sourceFile = sourceFileCache.get(specifier); + if (sourceFile) { + return sourceFile.version ?? "1"; + } + return core.jsonOpSync("op_script_version", { specifier }); + }, + getScriptSnapshot(specifier) { + debug(`host.getScriptSnapshot("${specifier}")`); + const sourceFile = sourceFileCache.get(specifier); + if (sourceFile) { + return { + getText(start, end) { + return sourceFile.text.substring(start, end); + }, + getLength() { + return sourceFile.text.length; + }, + getChangeRange() { + return undefined; + }, + }; + } + /** @type {string | undefined} */ + const version = core.jsonOpSync("op_script_version", { specifier }); + if (version != null) { + return new ScriptSnapshot(specifier, version); + } + return undefined; + }, + }; + + /** @type {Array<[string, number]>} */ + const stats = []; + let statsStart = 0; + + function performanceStart() { + stats.length = 0; + statsStart = Date.now(); + ts.performance.enable(); + } + + /** + * @param {{ program: ts.Program | ts.EmitAndSemanticDiagnosticsBuilderProgram, fileCount?: number }} options + */ + function performanceProgram({ program, fileCount }) { + if (program) { + if ("getProgram" in program) { + program = program.getProgram(); + } + stats.push(["Files", program.getSourceFiles().length]); + stats.push(["Nodes", program.getNodeCount()]); + stats.push(["Identifiers", program.getIdentifierCount()]); + stats.push(["Symbols", program.getSymbolCount()]); + stats.push(["Types", program.getTypeCount()]); + stats.push(["Instantiations", program.getInstantiationCount()]); + } else if (fileCount != null) { + stats.push(["Files", fileCount]); + } + const programTime = ts.performance.getDuration("Program"); + const bindTime = ts.performance.getDuration("Bind"); + const checkTime = ts.performance.getDuration("Check"); + const emitTime = ts.performance.getDuration("Emit"); + stats.push(["Parse time", programTime]); + stats.push(["Bind time", bindTime]); + stats.push(["Check time", checkTime]); + stats.push(["Emit time", emitTime]); + stats.push( + ["Total TS time", programTime + bindTime + checkTime + emitTime], + ); + } + + function performanceEnd() { + const duration = Date.now() - statsStart; + stats.push(["Compile time", duration]); + return stats; + } + + /** + * @typedef {object} Request + * @property {Record} config + * @property {boolean} debug + * @property {string[]} rootNames + */ + + /** The API that is called by Rust when executing a request. + * @param {Request} request + */ + function exec({ config, debug: debugFlag, rootNames }) { + setLogDebug(debugFlag, "TS"); + performanceStart(); + debug(">>> exec start", { rootNames }); + debug(config); + + const { options, errors: configFileParsingDiagnostics } = ts + .convertCompilerOptionsFromJson(config, ""); + // The `allowNonTsExtensions` is a "hidden" compiler option used in VSCode + // which is not allowed to be passed in JSON, we need it to allow special + // URLs which Deno supports. So we need to either ignore the diagnostic, or + // inject it ourselves. + Object.assign(options, { allowNonTsExtensions: true }); + const program = ts.createIncrementalProgram({ + rootNames, + options, + host, + configFileParsingDiagnostics, + }); + + const { diagnostics: emitDiagnostics } = program.emit(); + + const diagnostics = [ + ...program.getConfigFileParsingDiagnostics(), + ...program.getSyntacticDiagnostics(), + ...program.getOptionsDiagnostics(), + ...program.getGlobalDiagnostics(), + ...program.getSemanticDiagnostics(), + ...emitDiagnostics, + ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code)); + performanceProgram({ program }); + + core.jsonOpSync("op_respond", { + diagnostics: fromTypeScriptDiagnostic(diagnostics), + stats: performanceEnd(), + }); + debug("<<< exec stop"); + } + + /** + * @param {number} id + * @param {any} data + */ + function respond(id, data = null) { + core.jsonOpSync("op_respond", { id, data }); + } + + /** + * @param {LanguageServerRequest} request + */ + function serverRequest({ id, ...request }) { + debug(`serverRequest()`, { id, ...request }); + switch (request.method) { + case "configure": { + const { options, errors } = ts + .convertCompilerOptionsFromJson(request.compilerOptions, ""); + Object.assign(options, { allowNonTsExtensions: true }); + if (errors.length) { + debug(ts.formatDiagnostics(errors, host)); + } + compilationSettings = options; + return respond(id, true); + } + case "getAsset": { + const sourceFile = host.getSourceFile( + request.specifier, + ts.ScriptTarget.ESNext, + ); + return respond(id, sourceFile && sourceFile.text); + } + case "getDiagnostics": { + try { + /** @type {Record} */ + const diagnosticMap = {}; + for (const specifier of request.specifiers) { + diagnosticMap[specifier] = fromTypeScriptDiagnostic([ + ...languageService.getSemanticDiagnostics(specifier), + ...languageService.getSuggestionDiagnostics(specifier), + ...languageService.getSyntacticDiagnostics(specifier), + ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code))); + } + return respond(id, diagnosticMap); + } catch (e) { + if ("stack" in e) { + error(e.stack); + } else { + error(e); + } + return respond(id, {}); + } + } + case "getQuickInfo": { + return respond( + id, + languageService.getQuickInfoAtPosition( + request.specifier, + request.position, + ), + ); + } + case "getCompletions": { + return respond( + id, + languageService.getCompletionsAtPosition( + request.specifier, + request.position, + request.preferences, + ), + ); + } + case "getDocumentHighlights": { + return respond( + id, + languageService.getDocumentHighlights( + request.specifier, + request.position, + request.filesToSearch, + ), + ); + } + case "getReferences": { + return respond( + id, + languageService.getReferencesAtPosition( + request.specifier, + request.position, + ), + ); + } + case "getDefinition": { + return respond( + id, + languageService.getDefinitionAndBoundSpan( + request.specifier, + request.position, + ), + ); + } + case "getImplementation": { + return respond( + id, + languageService.getImplementationAtPosition( + request.specifier, + request.position, + ), + ); + } + case "findRenameLocations": { + return respond( + id, + languageService.findRenameLocations( + request.specifier, + request.position, + request.findInStrings, + request.findInComments, + request.providePrefixAndSuffixTextForRename, + ), + ); + } + default: + throw new TypeError( + // @ts-ignore exhausted case statement sets type to never + `Invalid request method for request: "${request.method}" (${id})`, + ); + } + } + + /** @param {{ debug: boolean; }} init */ + function serverInit({ debug: debugFlag }) { + if (hasStarted) { + throw new Error("The language server has already been initialized."); + } + hasStarted = true; + languageService = ts.createLanguageService(host); + core.ops(); + setLogDebug(debugFlag, "TSLS"); + debug("serverInit()"); + } + + let hasStarted = false; + + /** Startup the runtime environment, setting various flags. + * @param {{ debugFlag?: boolean; legacyFlag?: boolean; }} msg + */ + function startup({ debugFlag = false }) { + if (hasStarted) { + throw new Error("The compiler runtime already started."); + } + hasStarted = true; + core.ops(); + setLogDebug(!!debugFlag, "TS"); + } + + // Setup the compiler runtime during the build process. + core.ops(); + core.registerErrorClass("Error", Error); + + // A build time only op that provides some setup information that is used to + // ensure the snapshot is setup properly. + /** @type {{ buildSpecifier: string; libs: string[] }} */ + const { buildSpecifier, libs } = core.jsonOpSync("op_build_info", {}); + for (const lib of libs) { + const specifier = `lib.${lib}.d.ts`; + // we are using internal APIs here to "inject" our custom libraries into + // tsc, so things like `"lib": [ "deno.ns" ]` are supported. + if (!ts.libs.includes(lib)) { + ts.libs.push(lib); + ts.libMap.set(lib, `lib.${lib}.d.ts`); + } + // we are caching in memory common type libraries that will be re-used by + // tsc on when the snapshot is restored + assert( + host.getSourceFile(`${ASSETS}${specifier}`, ts.ScriptTarget.ESNext), + ); + } + // this helps ensure as much as possible is in memory that is re-usable + // before the snapshotting is done, which helps unsure fast "startup" for + // subsequent uses of tsc in Deno. + const TS_SNAPSHOT_PROGRAM = ts.createProgram({ + rootNames: [buildSpecifier], + options: SNAPSHOT_COMPILE_OPTIONS, + host, + }); + ts.getPreEmitDiagnostics(TS_SNAPSHOT_PROGRAM); + + // exposes the two functions that are called by `tsc::exec()` when type + // checking TypeScript. + globalThis.startup = startup; + globalThis.exec = exec; + + // exposes the functions that are called when the compiler is used as a + // language service. + globalThis.serverInit = serverInit; + globalThis.serverRequest = serverRequest; +})(this); diff --git a/cli/tests/testdata/lsp/outgoing_calls_response.json b/cli/tests/testdata/lsp/outgoing_calls_response.json deleted file mode 100644 index c7cf85cf8143b7..00000000000000 --- a/cli/tests/testdata/lsp/outgoing_calls_response.json +++ /dev/null @@ -1,42 +0,0 @@ -[ - { - "to": { - "name": "foo", - "kind": 12, - "detail": "", - "uri": "file:///a/file.ts", - "range": { - "start": { - "line": 0, - "character": 0 - }, - "end": { - "line": 2, - "character": 1 - } - }, - "selectionRange": { - "start": { - "line": 0, - "character": 9 - }, - "end": { - "line": 0, - "character": 12 - } - } - }, - "fromRanges": [ - { - "start": { - "line": 6, - "character": 11 - }, - "end": { - "line": 6, - "character": 14 - } - } - ] - } -] diff --git a/test_util/src/builders.rs b/test_util/src/builders.rs index 9b47d3c9ef5bba..e72ce9b63593ad 100644 --- a/test_util/src/builders.rs +++ b/test_util/src/builders.rs @@ -112,7 +112,7 @@ impl TestContextBuilder { testdata_path() }; - let deno_exe = self.deno_exe.clone().unwrap_or_else(|| deno_exe_path()); + let deno_exe = self.deno_exe.clone().unwrap_or_else(deno_exe_path); println!("deno_exe path {}", deno_exe.display()); let http_server_guard = if self.use_http_server { @@ -179,7 +179,7 @@ impl TestContext { pub fn new_lsp_command(&self) -> LspClientBuilder { let mut builder = LspClientBuilder::new(); - builder.deno_exe(&self.deno_exe).set_test_context(&self); + builder.deno_exe(&self.deno_exe).set_test_context(self); builder } } @@ -298,7 +298,7 @@ impl TestCommandBuilder { let mut command = if command_name == "deno" { Command::new(deno_exe_path()) } else { - Command::new(&command_name) + Command::new(command_name) }; command.env("DENO_DIR", self.context.deno_dir.path()); diff --git a/test_util/src/lsp.rs b/test_util/src/lsp.rs index 77d8966991a0a1..5798235b678cfa 100644 --- a/test_util/src/lsp.rs +++ b/test_util/src/lsp.rs @@ -176,6 +176,7 @@ pub struct InitializeParamsBuilder { } impl InitializeParamsBuilder { + #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { params: InitializeParams { @@ -404,7 +405,7 @@ impl InitializeParamsBuilder { let hosts = imports.get_mut("hosts").unwrap().as_object_mut().unwrap(); hosts.clear(); for (key, value) in values { - hosts.insert(key.into(), value.into()); + hosts.insert(key, value.into()); } self } @@ -436,6 +437,7 @@ pub struct LspClientBuilder { } impl LspClientBuilder { + #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { print_stderr: false, From e5b18beedbfdc92958a4d47d90c7282a573a1143 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 8 Mar 2023 17:45:19 -0500 Subject: [PATCH 8/9] Lint. --- cli/tests/integration/lsp_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index a48c56b5f377ff..bed543bb860fbc 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -7923,7 +7923,7 @@ Deno.test({ } }); "#; - temp_dir.write("./test.ts", &contents); + temp_dir.write("./test.ts", contents); temp_dir.write("./deno.jsonc", "{}"); let specifier = temp_dir.uri().join("test.ts").unwrap(); From 35512eb8006e4b6df8b0d2dbc3e5e3562965f83c Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 8 Mar 2023 17:52:03 -0500 Subject: [PATCH 9/9] Remove more lines of code --- cli/tests/integration/lsp_tests.rs | 158 +++++++++-------------------- 1 file changed, 49 insertions(+), 109 deletions(-) diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index bed543bb860fbc..344ba0804fc0b1 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -230,9 +230,7 @@ fn lsp_tsconfig_types() { "types.tsconfig.json", r#"{ "compilerOptions": { - "types": [ - "./a.d.ts" - ] + "types": ["./a.d.ts"] }, "lint": { "rules": { @@ -590,8 +588,7 @@ fn lsp_deno_task() { { "name": "build", "detail": "deno test" - }, - { + }, { "name": "some:test", "detail": "deno bundle mod.ts" } @@ -789,32 +786,28 @@ fn lsp_import_map_import_completions() { "sortText": "1", "insertText": ".", "commitCharacters": ["\"", "'"], - }, - { + }, { "label": "..", "kind": 19, "detail": "(local)", "sortText": "1", "insertText": "..", "commitCharacters": ["\"", "'"], - }, - { + }, { "label": "std", "kind": 19, "detail": "(import map)", "sortText": "std", "insertText": "std", "commitCharacters": ["\"", "'"], - }, - { + }, { "label": "fs", "kind": 17, "detail": "(import map)", "sortText": "fs", "insertText": "fs", "commitCharacters": ["\"", "'"], - }, - { + }, { "label": "/~", "kind": 19, "detail": "(import map)", @@ -1111,55 +1104,46 @@ fn lsp_inlay_hints() { "label": ": string", "kind": 1, "paddingLeft": true - }, - { + }, { "position": { "line": 4, "character": 10 }, "label": "b:", "kind": 2, "paddingRight": true - }, - { + }, { "position": { "line": 7, "character": 11 }, "label": "= 0", "paddingLeft": true - }, - { + }, { "position": { "line": 10, "character": 17 }, "label": "string:", "kind": 2, "paddingRight": true - }, - { + }, { "position": { "line": 10, "character": 24 }, "label": "radix:", "kind": 2, "paddingRight": true - }, - { + }, { "position": { "line": 12, "character": 15 }, "label": ": number", "kind": 1, "paddingLeft": true - }, - { + }, { "position": { "line": 15, "character": 11 }, "label": ": number", "kind": 1, "paddingLeft": true - }, - { + }, { "position": { "line": 18, "character": 18 }, "label": "callbackfn:", "kind": 2, "paddingRight": true - }, - { + }, { "position": { "line": 18, "character": 20 }, "label": ": string", "kind": 1, "paddingLeft": true - }, - { + }, { "position": { "line": 18, "character": 21 }, "label": ": string", "kind": 1, @@ -1247,9 +1231,7 @@ fn lsp_workspace_enable_paths() { &mut client, json!([{ "enable": false, - "enablePaths": [ - "./worker" - ], + "enablePaths": ["./worker"], }]), ); @@ -2451,9 +2433,7 @@ fn lsp_document_symbol() { }, { "name": "baz", "kind": 6, - "tags": [ - 1 - ], + "tags": [1], "range": { "start": { "line": 8, "character": 2 }, "end": { "line": 8, "character": 25 } @@ -3691,8 +3671,7 @@ fn lsp_signature_help() { "kind": "markdown", "value": "This is a first number." } - }, - { + }, { "label": "b: number", "documentation": { "kind": "markdown", @@ -3755,8 +3734,7 @@ fn lsp_signature_help() { "kind": "markdown", "value": "This is a first number." } - }, - { + }, { "label": "b: number", "documentation": { "kind": "markdown", @@ -3947,8 +3925,7 @@ fn lsp_code_actions() { "end": { "line": 4, "character": 7 } }, "newText": "async " - }, - { + }, { "range": { "start": { "line": 4, "character": 21 }, "end": { "line": 4, "character": 25 } @@ -4361,8 +4338,7 @@ export class DuckConfig { "code": 2304, "source": "deno-ts", "message": "Cannot find name 'DuckConfigOptions'." - }, - { + }, { "range": { "start": { "line": 4, "character": 39 }, "end": { "line": 4, "character": 49 } @@ -4649,9 +4625,7 @@ fn lsp_code_actions_refactor_no_disabled_support() { }, "context": { "diagnostics": [], - "only": [ - "refactor" - ] + "only": ["refactor"] } }), ) @@ -5359,8 +5333,7 @@ fn lsp_completions_npm() { "uris": [ { "uri": "npm:@denotest/cjs-default-export", - }, - { + }, { "uri": "npm:chalk", } ] @@ -6448,13 +6421,11 @@ fn lsp_diagnostics_deprecated() { "uri": "file:///a/file.ts", "diagnostics": [], "version": 1 - }, - { + }, { "uri": "file:///a/file.ts", "diagnostics": [], "version": 1 - }, - { + }, { "uri": "file:///a/file.ts", "diagnostics": [ { @@ -6467,9 +6438,7 @@ fn lsp_diagnostics_deprecated() { "source": "deno-ts", "message": "'a' is deprecated.", "relatedInformation": [], - "tags": [ - 2 - ] + "tags": [2] } ], "version": 1 @@ -6790,9 +6759,7 @@ fn lsp_format_exclude_with_config() { r#"{ "fmt": { "files": { - "exclude": [ - "ignored.ts" - ] + "exclude": ["ignored.ts"] }, "options": { "useTabs": true, @@ -6851,9 +6818,7 @@ fn lsp_format_exclude_default_config() { r#"{ "fmt": { "files": { - "exclude": [ - "ignored.ts" - ] + "exclude": ["ignored.ts"] }, "options": { "useTabs": true, @@ -6947,15 +6912,13 @@ fn lsp_format_json() { "end": { "line": 0, "character": 1 } }, "newText": " " - }, - { + }, { "range": { "start": { "line": 0, "character": 7 }, "end": { "line": 0, "character": 7 } }, "newText": " " - }, - { + }, { "range": { "start": { "line": 0, "character": 14 }, "end": { "line": 0, "character": 15 } @@ -7058,8 +7021,7 @@ fn lsp_format_markdown() { "end": { "line": 0, "character": 3 } }, "newText": "" - }, - { + }, { "range": { "start": { "line": 0, "character": 15 }, "end": { "line": 0, "character": 15 } @@ -7135,50 +7097,43 @@ fn lsp_format_with_config() { "end": { "line": 1, "character": 0 } }, "newText": "\t" - }, - { + }, { "range": { "start": { "line": 1, "character": 23 }, "end": { "line": 1, "character": 24 } }, "newText": "\n\t\t'" - }, - { + }, { "range": { "start": { "line": 1, "character": 73 }, "end": { "line": 1, "character": 74 } }, "newText": "',\n\t" - }, - { + }, { "range": { "start": { "line": 2, "character": 0 }, "end": { "line": 2, "character": 0 } }, "newText": "\t" - }, - { + }, { "range": { "start": { "line": 3, "character": 0 }, "end": { "line": 3, "character": 0 } }, "newText": "\t" - }, - { + }, { "range": { "start": { "line": 3, "character": 12 }, "end": { "line": 3, "character": 13 } }, "newText": "'" - }, - { + }, { "range": { "start": { "line": 3, "character": 22 }, "end": { "line": 3, "character": 24 } }, "newText": "');" - }, - { + }, { "range": { "start": { "line": 4, "character": 1 }, "end": { "line": 4, "character": 1 } @@ -7401,8 +7356,7 @@ fn lsp_workspace_symbol() { } }, "containerName": "A" - }, - { + }, { "name": "fieldB", "kind": 8, "location": { @@ -7413,8 +7367,7 @@ fn lsp_workspace_symbol() { } }, "containerName": "A" - }, - { + }, { "name": "fieldC", "kind": 8, "location": { @@ -7425,8 +7378,7 @@ fn lsp_workspace_symbol() { } }, "containerName": "B" - }, - { + }, { "name": "fieldD", "kind": 8, "location": { @@ -7713,12 +7665,8 @@ fn lsp_lint_with_config() { r#"{ "lint": { "rules": { - "exclude": [ - "camelcase" - ], - "include": [ - "ban-untagged-todo" - ], + "exclude": ["camelcase"], + "include": ["ban-untagged-todo"], "tags": [] } } @@ -7760,17 +7708,11 @@ fn lsp_lint_exclude_with_config() { r#"{ "lint": { "files": { - "exclude": [ - "ignored.ts" - ] + "exclude": ["ignored.ts"] }, "rules": { - "exclude": [ - "camelcase" - ], - "include": [ - "ban-untagged-todo" - ], + "exclude": ["camelcase"], + "include": ["ban-untagged-todo"], "tags": [] } } @@ -7834,11 +7776,9 @@ export function B() { "referrer": { "uri": "file:///a/file.tsx", }, - "uris": [ - { - "uri": "http://127.0.0.1:4545/jsx/jsx-runtime", - } - ], + "uris": [{ + "uri": "http://127.0.0.1:4545/jsx/jsx-runtime", + }], }), ) .unwrap();