summaryrefslogtreecommitdiff
path: root/cli/tests/integration/lsp_tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tests/integration/lsp_tests.rs')
-rw-r--r--cli/tests/integration/lsp_tests.rs389
1 files changed, 224 insertions, 165 deletions
diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs
index e831e8627..35a2e29ac 100644
--- a/cli/tests/integration/lsp_tests.rs
+++ b/cli/tests/integration/lsp_tests.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2022 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;
@@ -17,10 +18,15 @@ use test_util::lsp::LspClient;
use test_util::testdata_path;
fn load_fixture(path: &str) -> Value {
- let fixtures_path = testdata_path().join("lsp");
- let path = fixtures_path.join(path);
- let fixture_str = fs::read_to_string(path).unwrap();
- serde_json::from_str(&fixture_str).unwrap()
+ load_fixture_as(path)
+}
+
+fn load_fixture_as<T>(path: &str) -> T
+where
+ T: DeserializeOwned,
+{
+ let fixture_str = load_fixture_str(path);
+ serde_json::from_str::<T>(&fixture_str).unwrap()
}
fn load_fixture_str(path: &str) -> String {
@@ -64,6 +70,11 @@ where
)
.unwrap();
+ read_diagnostics(client).0
+}
+
+fn read_diagnostics(client: &mut LspClient) -> CollectedDiagnostics {
+ // diagnostics come in batches of three unless they're cancelled
let mut diagnostics = vec![];
for _ in 0..3 {
let (method, response) = client
@@ -72,8 +83,7 @@ where
assert_eq!(method, "textDocument/publishDiagnostics");
diagnostics.push(response.unwrap());
}
-
- diagnostics
+ CollectedDiagnostics(diagnostics)
}
fn shutdown(client: &mut LspClient) {
@@ -83,6 +93,110 @@ fn shutdown(client: &mut LspClient) {
client.write_notification("exit", json!(null)).unwrap();
}
+struct TestSession {
+ client: LspClient,
+ open_file_count: usize,
+}
+
+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,
+ open_file_count: 0,
+ }
+ }
+
+ pub fn did_open<V>(&mut self, params: V) -> CollectedDiagnostics
+ where
+ V: Serialize,
+ {
+ self
+ .client
+ .write_notification("textDocument/didOpen", params)
+ .unwrap();
+
+ let (id, method, _) = self.client.read_request::<Value>().unwrap();
+ assert_eq!(method, "workspace/configuration");
+ self
+ .client
+ .write_response(
+ id,
+ json!([{
+ "enable": true,
+ "codeLens": {
+ "test": true
+ }
+ }]),
+ )
+ .unwrap();
+
+ self.open_file_count += 1;
+ self.read_diagnostics()
+ }
+
+ pub fn read_diagnostics(&mut self) -> CollectedDiagnostics {
+ let mut all_diagnostics = Vec::new();
+ for _ in 0..self.open_file_count {
+ all_diagnostics.extend(read_diagnostics(&mut self.client).0);
+ }
+ CollectedDiagnostics(all_diagnostics)
+ }
+
+ pub fn shutdown_and_exit(&mut self) {
+ shutdown(&mut self.client);
+ }
+}
+
+#[derive(Debug, Clone)]
+struct CollectedDiagnostics(Vec<lsp::PublishDiagnosticsParams>);
+
+impl CollectedDiagnostics {
+ pub fn all(&self) -> Vec<lsp::Diagnostic> {
+ self
+ .0
+ .iter()
+ .flat_map(|p| p.diagnostics.clone().into_iter())
+ .collect()
+ }
+
+ pub fn with_source(&self, source: &str) -> lsp::PublishDiagnosticsParams {
+ self
+ .0
+ .iter()
+ .find(|p| {
+ p.diagnostics
+ .iter()
+ .any(|d| d.source == Some(source.to_string()))
+ })
+ .map(ToOwned::to_owned)
+ .unwrap()
+ }
+
+ pub fn with_file_and_source(
+ &self,
+ specifier: &str,
+ source: &str,
+ ) -> lsp::PublishDiagnosticsParams {
+ let specifier = ModuleSpecifier::parse(specifier).unwrap();
+ self
+ .0
+ .iter()
+ .find(|p| {
+ p.uri == specifier
+ && p
+ .diagnostics
+ .iter()
+ .any(|d| d.source == Some(source.to_string()))
+ })
+ .map(ToOwned::to_owned)
+ .unwrap()
+ }
+}
+
#[test]
fn lsp_startup_shutdown() {
let mut client = init("initialize_params.json");
@@ -361,7 +475,7 @@ fn lsp_import_assertions() {
)
.unwrap();
- let mut diagnostics = did_open(
+ let diagnostics = CollectedDiagnostics(did_open(
&mut client,
json!({
"textDocument": {
@@ -371,11 +485,14 @@ fn lsp_import_assertions() {
"text": "import a from \"./test.json\";\n\nconsole.log(a);\n"
}
}),
- );
+ ));
- let last = diagnostics.pop().unwrap();
assert_eq!(
- json!(last.diagnostics),
+ json!(
+ diagnostics
+ .with_file_and_source("file:///a/a.ts", "deno")
+ .diagnostics
+ ),
json!([
{
"range": {
@@ -2521,13 +2638,11 @@ fn lsp_code_actions_deno_cache() {
client
.write_response(id, json!([{ "enable": true }]))
.unwrap();
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let (method, params) = client.read_notification().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- assert_eq!(params, Some(load_fixture("diagnostics_deno_deps.json")));
+ let diagnostics = read_diagnostics(&mut client);
+ assert_eq!(
+ diagnostics.with_source("deno"),
+ load_fixture_as("diagnostics_deno_deps.json")
+ );
let (maybe_res, maybe_err) = client
.write_request(
@@ -2545,31 +2660,26 @@ fn lsp_code_actions_deno_cache() {
#[test]
fn lsp_code_actions_imports() {
- let mut client = init("initialize_params.json");
- did_open(
- &mut client,
- json!({
- "textDocument": {
- "uri": "file:///a/file00.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "export const abc = \"abc\";\nexport const def = \"def\";\n"
- }
- }),
- );
- did_open(
- &mut client,
- json!({
- "textDocument": {
- "uri": "file:///a/file01.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "\nconsole.log(abc);\nconsole.log(def)\n"
- }
- }),
- );
+ let mut session = TestSession::from_file("initialize_params.json");
+ session.did_open(json!({
+ "textDocument": {
+ "uri": "file:///a/file00.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "export const abc = \"abc\";\nexport const def = \"def\";\n"
+ }
+ }));
+ session.did_open(json!({
+ "textDocument": {
+ "uri": "file:///a/file01.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "\nconsole.log(abc);\nconsole.log(def)\n"
+ }
+ }));
- let (maybe_res, maybe_err) = client
+ let (maybe_res, maybe_err) = session
+ .client
.write_request(
"textDocument/codeAction",
load_fixture("code_action_params_imports.json"),
@@ -2580,7 +2690,8 @@ fn lsp_code_actions_imports() {
maybe_res,
Some(load_fixture("code_action_response_imports.json"))
);
- let (maybe_res, maybe_err) = client
+ let (maybe_res, maybe_err) = session
+ .client
.write_request(
"codeAction/resolve",
load_fixture("code_action_resolve_params_imports.json"),
@@ -2591,7 +2702,8 @@ fn lsp_code_actions_imports() {
maybe_res,
Some(load_fixture("code_action_resolve_response_imports.json"))
);
- shutdown(&mut client);
+
+ session.shutdown_and_exit();
}
#[test]
@@ -2707,10 +2819,7 @@ fn lsp_code_actions_deadlock() {
.unwrap();
assert!(maybe_err.is_none());
assert!(maybe_res.is_some());
- for _ in 0..3 {
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- }
+ read_diagnostics(&mut client);
client
.write_notification(
"textDocument/didChange",
@@ -2818,12 +2927,8 @@ fn lsp_code_actions_deadlock() {
assert!(maybe_err.is_none());
assert!(maybe_res.is_some());
- for _ in 0..3 {
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- }
+ read_diagnostics(&mut client);
- assert!(client.queue_is_empty());
shutdown(&mut client);
}
@@ -3128,7 +3233,7 @@ fn lsp_cache_location() {
load_fixture("did_open_params_import_hover.json"),
);
let diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics);
- assert_eq!(diagnostics.count(), 14);
+ assert_eq!(diagnostics.count(), 7);
let (maybe_res, maybe_err) = client
.write_request::<_, _, Value>(
"deno/cache",
@@ -3233,24 +3338,23 @@ fn lsp_tls_cert() {
client
.write_request::<_, _, Value>("initialize", params)
.unwrap();
-
client.write_notification("initialized", json!({})).unwrap();
- did_open(
- &mut client,
- json!({
- "textDocument": {
- "uri": "file:///a/file_01.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "export const a = \"a\";\n",
- }
- }),
- );
+ let mut session = TestSession::from_client(client);
+
+ session.did_open(json!({
+ "textDocument": {
+ "uri": "file:///a/file_01.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "export const a = \"a\";\n",
+ }
+ }));
let diagnostics =
- did_open(&mut client, load_fixture("did_open_params_tls_cert.json"));
- let diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics);
- assert_eq!(diagnostics.count(), 14);
- let (maybe_res, maybe_err) = client
+ session.did_open(load_fixture("did_open_params_tls_cert.json"));
+ let diagnostics = diagnostics.all();
+ assert_eq!(diagnostics.len(), 7);
+ let (maybe_res, maybe_err) = session
+ .client
.write_request::<_, _, Value>(
"deno/cache",
json!({
@@ -3263,7 +3367,8 @@ fn lsp_tls_cert() {
.unwrap();
assert!(maybe_err.is_none());
assert!(maybe_res.is_some());
- let (maybe_res, maybe_err) = client
+ let (maybe_res, maybe_err) = session
+ .client
.write_request(
"textDocument/hover",
json!({
@@ -3297,7 +3402,8 @@ fn lsp_tls_cert() {
}
}))
);
- let (maybe_res, maybe_err) = client
+ let (maybe_res, maybe_err) = session
+ .client
.write_request::<_, _, Value>(
"textDocument/hover",
json!({
@@ -3331,7 +3437,7 @@ fn lsp_tls_cert() {
}
}))
);
- shutdown(&mut client);
+ session.shutdown_and_exit();
}
#[test]
@@ -3366,17 +3472,10 @@ fn lsp_diagnostics_warn() {
.unwrap();
assert!(maybe_err.is_none());
assert!(maybe_res.is_some());
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let (method, maybe_params) = client
- .read_notification::<lsp::PublishDiagnosticsParams>()
- .unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
+ let diagnostics = read_diagnostics(&mut client);
assert_eq!(
- maybe_params,
- Some(lsp::PublishDiagnosticsParams {
+ diagnostics.with_source("deno"),
+ lsp::PublishDiagnosticsParams {
uri: Url::parse("file:///a/file.ts").unwrap(),
diagnostics: vec![lsp::Diagnostic {
range: lsp::Range {
@@ -3396,7 +3495,7 @@ fn lsp_diagnostics_warn() {
..Default::default()
}],
version: Some(1),
- })
+ }
);
shutdown(&mut client);
}
@@ -3485,58 +3584,40 @@ fn lsp_diagnostics_deno_types() {
.unwrap();
assert!(maybe_res.is_some());
assert!(maybe_err.is_none());
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let (method, maybe_params) = client
- .read_notification::<lsp::PublishDiagnosticsParams>()
- .unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- assert!(maybe_params.is_some());
- let params = maybe_params.unwrap();
- assert_eq!(params.diagnostics.len(), 5);
+ let diagnostics = read_diagnostics(&mut client);
+ assert_eq!(diagnostics.all().len(), 5);
shutdown(&mut client);
}
#[test]
fn lsp_diagnostics_refresh_dependents() {
- let mut client = init("initialize_params.json");
- did_open(
- &mut client,
- json!({
- "textDocument": {
- "uri": "file:///a/file_00.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "export const a = \"a\";\n",
- },
- }),
- );
- did_open(
- &mut client,
- json!({
- "textDocument": {
- "uri": "file:///a/file_01.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "export * from \"./file_00.ts\";\n",
- },
- }),
- );
- let diagnostics = did_open(
- &mut client,
- json!({
- "textDocument": {
- "uri": "file:///a/file_02.ts",
- "languageId": "typescript",
- "version": 1,
- "text": "import { a, b } from \"./file_01.ts\";\n\nconsole.log(a, b);\n"
- }
- }),
- );
+ let mut session = TestSession::from_file("initialize_params.json");
+ session.did_open(json!({
+ "textDocument": {
+ "uri": "file:///a/file_00.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "export const a = \"a\";\n",
+ },
+ }));
+ session.did_open(json!({
+ "textDocument": {
+ "uri": "file:///a/file_01.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "export * from \"./file_00.ts\";\n",
+ },
+ }));
+ let diagnostics = session.did_open(json!({
+ "textDocument": {
+ "uri": "file:///a/file_02.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "import { a, b } from \"./file_01.ts\";\n\nconsole.log(a, b);\n"
+ }
+ }));
assert_eq!(
- json!(diagnostics[2]),
+ json!(diagnostics.with_file_and_source("file:///a/file_02.ts", "deno-ts")),
json!({
"uri": "file:///a/file_02.ts",
"diagnostics": [
@@ -3560,7 +3641,10 @@ fn lsp_diagnostics_refresh_dependents() {
"version": 1
})
);
- client
+
+ // fix the code causing the diagnostic
+ session
+ .client
.write_notification(
"textDocument/didChange",
json!({
@@ -3586,34 +3670,11 @@ fn lsp_diagnostics_refresh_dependents() {
}),
)
.unwrap();
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let (method, _) = client.read_notification::<Value>().unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- // ensure that the server publishes any inflight diagnostics
- std::thread::sleep(std::time::Duration::from_millis(250));
- client
- .write_request::<_, _, Value>("shutdown", json!(null))
- .unwrap();
- client.write_notification("exit", json!(null)).unwrap();
+ let diagnostics = session.read_diagnostics();
+ assert_eq!(diagnostics.all().len(), 0); // no diagnostics now
- let queue_len = client.queue_len();
- assert!(!client.queue_is_empty());
- for i in 0..queue_len {
- let (method, maybe_params) = client
- .read_notification::<lsp::PublishDiagnosticsParams>()
- .unwrap();
- assert_eq!(method, "textDocument/publishDiagnostics");
- // the last 3 diagnostic publishes should be the clear of any diagnostics
- if queue_len - i <= 3 {
- assert!(maybe_params.is_some());
- let params = maybe_params.unwrap();
- assert_eq!(params.diagnostics, Vec::with_capacity(0));
- }
- }
- assert!(client.queue_is_empty());
+ session.shutdown_and_exit();
+ assert_eq!(session.client.queue_len(), 0);
}
#[derive(Deserialize)]
@@ -3665,7 +3726,7 @@ fn lsp_performance() {
.unwrap();
assert!(maybe_err.is_none());
if let Some(res) = maybe_res {
- assert!(res.averages.len() >= 6);
+ assert_eq!(res.averages.len(), 13);
} else {
panic!("unexpected result");
}
@@ -4350,13 +4411,11 @@ fn lsp_lint_with_config() {
.into_iter()
.flat_map(|x| x.diagnostics)
.collect::<Vec<_>>();
- assert_eq!(diagnostics.len(), 3);
- for diagnostic in diagnostics {
- assert_eq!(
- diagnostic.code,
- Some(lsp::NumberOrString::String("ban-untagged-todo".to_string()))
- );
- }
+ assert_eq!(diagnostics.len(), 1);
+ assert_eq!(
+ diagnostics[0].code,
+ Some(lsp::NumberOrString::String("ban-untagged-todo".to_string()))
+ );
shutdown(&mut client);
}