summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/lsp/client.rs34
-rw-r--r--cli/lsp/diagnostics.rs134
-rw-r--r--cli/lsp/language_server.rs27
-rw-r--r--cli/lsp/lsp_custom.rs18
-rw-r--r--cli/lsp/mod.rs18
-rw-r--r--cli/tests/integration/lsp_tests.rs104
-rw-r--r--test_util/src/lsp.rs139
7 files changed, 125 insertions, 349 deletions
diff --git a/cli/lsp/client.rs b/cli/lsp/client.rs
index 5f1a7fcef..4923a4585 100644
--- a/cli/lsp/client.rs
+++ b/cli/lsp/client.rs
@@ -62,20 +62,6 @@ impl Client {
});
}
- /// This notification is sent to the client during internal testing
- /// purposes only in order to let the test client know when the latest
- /// diagnostics have been published.
- pub fn send_diagnostic_batch_notification(
- &self,
- params: lsp_custom::DiagnosticBatchNotificationParams,
- ) {
- // do on a task in case the caller currently is in the lsp lock
- let client = self.0.clone();
- spawn(async move {
- client.send_diagnostic_batch_notification(params).await;
- });
- }
-
pub fn send_test_notification(&self, params: TestingNotification) {
// do on a task in case the caller currently is in the lsp lock
let client = self.0.clone();
@@ -174,10 +160,6 @@ trait ClientTrait: Send + Sync {
&self,
params: lsp_custom::RegistryStateNotificationParams,
);
- async fn send_diagnostic_batch_notification(
- &self,
- params: lsp_custom::DiagnosticBatchNotificationParams,
- );
async fn send_test_notification(&self, params: TestingNotification);
async fn specifier_configurations(
&self,
@@ -215,16 +197,6 @@ impl ClientTrait for TowerClient {
.await
}
- async fn send_diagnostic_batch_notification(
- &self,
- params: lsp_custom::DiagnosticBatchNotificationParams,
- ) {
- self
- .0
- .send_notification::<lsp_custom::DiagnosticBatchNotification>(params)
- .await
- }
-
async fn send_test_notification(&self, notification: TestingNotification) {
match notification {
TestingNotification::Module(params) => {
@@ -339,12 +311,6 @@ impl ClientTrait for ReplClient {
) {
}
- async fn send_diagnostic_batch_notification(
- &self,
- _params: lsp_custom::DiagnosticBatchNotificationParams,
- ) {
- }
-
async fn send_test_notification(&self, _params: TestingNotification) {}
async fn specifier_configurations(
diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs
index a5e9d7bf8..1a57ad03b 100644
--- a/cli/lsp/diagnostics.rs
+++ b/cli/lsp/diagnostics.rs
@@ -16,7 +16,6 @@ use super::tsc::TsServer;
use crate::args::LintOptions;
use crate::graph_util;
use crate::graph_util::enhanced_resolution_error_message;
-use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
use crate::tools::lint::get_configured_rules;
use deno_ast::MediaType;
@@ -38,7 +37,6 @@ use deno_runtime::tokio_util::create_basic_runtime;
use deno_semver::npm::NpmPackageReqReference;
use log::error;
use std::collections::HashMap;
-use std::sync::atomic::AtomicUsize;
use std::sync::Arc;
use std::thread;
use tokio::sync::mpsc;
@@ -47,13 +45,8 @@ use tokio::time::Duration;
use tokio_util::sync::CancellationToken;
use tower_lsp::lsp_types as lsp;
-#[derive(Debug)]
-pub struct DiagnosticServerUpdateMessage {
- pub snapshot: Arc<StateSnapshot>,
- pub config: Arc<ConfigSnapshot>,
- pub lint_options: LintOptions,
-}
-
+pub type SnapshotForDiagnostics =
+ (Arc<StateSnapshot>, Arc<ConfigSnapshot>, LintOptions);
pub type DiagnosticRecord =
(ModuleSpecifier, Option<i32>, Vec<lsp::Diagnostic>);
pub type DiagnosticVec = Vec<DiagnosticRecord>;
@@ -152,55 +145,13 @@ impl TsDiagnosticsStore {
}
}
-pub fn should_send_diagnostic_batch_index_notifications() -> bool {
- crate::args::has_flag_env_var(
- "DENO_DONT_USE_INTERNAL_LSP_DIAGNOSTIC_SYNC_FLAG",
- )
-}
-
-#[derive(Clone, Debug)]
-struct DiagnosticBatchCounter(Option<Arc<AtomicUsize>>);
-
-impl Default for DiagnosticBatchCounter {
- fn default() -> Self {
- if should_send_diagnostic_batch_index_notifications() {
- Self(Some(Default::default()))
- } else {
- Self(None)
- }
- }
-}
-
-impl DiagnosticBatchCounter {
- pub fn inc(&self) -> Option<usize> {
- self
- .0
- .as_ref()
- .map(|value| value.fetch_add(1, std::sync::atomic::Ordering::SeqCst) + 1)
- }
-
- pub fn get(&self) -> Option<usize> {
- self
- .0
- .as_ref()
- .map(|value| value.load(std::sync::atomic::Ordering::SeqCst))
- }
-}
-
-#[derive(Debug)]
-struct ChannelMessage {
- message: DiagnosticServerUpdateMessage,
- batch_index: Option<usize>,
-}
-
#[derive(Debug)]
pub struct DiagnosticsServer {
- channel: Option<mpsc::UnboundedSender<ChannelMessage>>,
+ channel: Option<mpsc::UnboundedSender<SnapshotForDiagnostics>>,
ts_diagnostics: TsDiagnosticsStore,
client: Client,
performance: Arc<Performance>,
ts_server: Arc<TsServer>,
- batch_counter: DiagnosticBatchCounter,
}
impl DiagnosticsServer {
@@ -215,7 +166,6 @@ impl DiagnosticsServer {
client,
performance,
ts_server,
- batch_counter: Default::default(),
}
}
@@ -237,7 +187,7 @@ impl DiagnosticsServer {
#[allow(unused_must_use)]
pub fn start(&mut self) {
- let (tx, mut rx) = mpsc::unbounded_channel::<ChannelMessage>();
+ let (tx, mut rx) = mpsc::unbounded_channel::<SnapshotForDiagnostics>();
self.channel = Some(tx);
let client = self.client.clone();
let performance = self.performance.clone();
@@ -258,17 +208,7 @@ impl DiagnosticsServer {
match rx.recv().await {
// channel has closed
None => break,
- Some(message) => {
- let ChannelMessage {
- message:
- DiagnosticServerUpdateMessage {
- snapshot,
- config,
- lint_options,
- },
- batch_index,
- } = message;
-
+ Some((snapshot, config, lint_options)) => {
// cancel the previous run
token.cancel();
token = CancellationToken::new();
@@ -315,7 +255,6 @@ impl DiagnosticsServer {
})
.unwrap_or_default();
- let messages_len = diagnostics.len();
if !token.is_cancelled() {
ts_diagnostics_store.update(&diagnostics);
diagnostics_publisher.publish(diagnostics, &token).await;
@@ -324,17 +263,6 @@ impl DiagnosticsServer {
performance.measure(mark);
}
}
-
- if let Some(batch_index) = batch_index {
- diagnostics_publisher
- .client
- .send_diagnostic_batch_notification(
- DiagnosticBatchNotificationParams {
- batch_index,
- messages_len,
- },
- );
- }
}
}));
@@ -358,24 +286,10 @@ impl DiagnosticsServer {
)
.await;
- let messages_len = diagnostics.len();
- if !token.is_cancelled() {
- diagnostics_publisher.publish(diagnostics, &token).await;
+ diagnostics_publisher.publish(diagnostics, &token).await;
- if !token.is_cancelled() {
- performance.measure(mark);
- }
- }
-
- if let Some(batch_index) = batch_index {
- diagnostics_publisher
- .client
- .send_diagnostic_batch_notification(
- DiagnosticBatchNotificationParams {
- batch_index,
- messages_len,
- },
- );
+ if !token.is_cancelled() {
+ performance.measure(mark);
}
}
}));
@@ -401,24 +315,10 @@ impl DiagnosticsServer {
)
.await;
- let messages_len = diagnostics.len();
- if !token.is_cancelled() {
- diagnostics_publisher.publish(diagnostics, &token).await;
-
- if !token.is_cancelled() {
- performance.measure(mark);
- }
- }
+ diagnostics_publisher.publish(diagnostics, &token).await;
- if let Some(batch_index) = batch_index {
- diagnostics_publisher
- .client
- .send_diagnostic_batch_notification(
- DiagnosticBatchNotificationParams {
- batch_index,
- messages_len,
- },
- );
+ if !token.is_cancelled() {
+ performance.measure(mark);
}
}
}));
@@ -429,23 +329,15 @@ impl DiagnosticsServer {
});
}
- pub fn latest_batch_index(&self) -> Option<usize> {
- self.batch_counter.get()
- }
-
pub fn update(
&self,
- message: DiagnosticServerUpdateMessage,
+ message: SnapshotForDiagnostics,
) -> Result<(), AnyError> {
// todo(dsherret): instead of queuing up messages, it would be better to
// instead only store the latest message (ex. maybe using a
// tokio::sync::watch::channel)
if let Some(tx) = &self.channel {
- tx.send(ChannelMessage {
- message,
- batch_index: self.batch_counter.inc(),
- })
- .map_err(|err| err.into())
+ tx.send(message).map_err(|err| err.into())
} else {
Err(anyhow!("diagnostics server not started"))
}
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 7c4191c82..9a2b067c6 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -46,7 +46,6 @@ use super::completions;
use super::config::Config;
use super::config::SETTINGS_SECTION;
use super::diagnostics;
-use super::diagnostics::DiagnosticServerUpdateMessage;
use super::diagnostics::DiagnosticsServer;
use super::documents::to_hover_text;
use super::documents::to_lsp_range;
@@ -343,22 +342,6 @@ impl LanguageServer {
}
}
- /// This request is only used by the lsp integration tests to
- /// coordinate the tests receiving the latest diagnostics.
- pub async fn latest_diagnostic_batch_index_request(
- &self,
- ) -> LspResult<Option<Value>> {
- Ok(
- self
- .0
- .read()
- .await
- .diagnostics_server
- .latest_batch_index()
- .map(|v| v.into()),
- )
- }
-
pub async fn performance_request(&self) -> LspResult<Option<Value>> {
Ok(Some(self.0.read().await.get_performance()))
}
@@ -2949,11 +2932,11 @@ impl Inner {
}
fn send_diagnostics_update(&self) {
- let snapshot = DiagnosticServerUpdateMessage {
- snapshot: self.snapshot(),
- config: self.config.snapshot(),
- lint_options: self.lint_options.clone(),
- };
+ let snapshot = (
+ self.snapshot(),
+ self.config.snapshot(),
+ self.lint_options.clone(),
+ );
if let Err(err) = self.diagnostics_server.update(snapshot) {
error!("Cannot update diagnostics: {}", err);
}
diff --git a/cli/lsp/lsp_custom.rs b/cli/lsp/lsp_custom.rs
index 24c4bc131..70a245a66 100644
--- a/cli/lsp/lsp_custom.rs
+++ b/cli/lsp/lsp_custom.rs
@@ -10,8 +10,6 @@ pub const TASK_REQUEST: &str = "deno/task";
pub const RELOAD_IMPORT_REGISTRIES_REQUEST: &str =
"deno/reloadImportRegistries";
pub const VIRTUAL_TEXT_DOCUMENT: &str = "deno/virtualTextDocument";
-pub const LATEST_DIAGNOSTIC_BATCH_INDEX: &str =
- "deno/internalLatestDiagnosticBatchIndex";
// While lsp_types supports inlay hints currently, tower_lsp does not.
pub const INLAY_HINT: &str = "textDocument/inlayHint";
@@ -46,19 +44,3 @@ impl lsp::notification::Notification for RegistryStateNotification {
pub struct VirtualTextDocumentParams {
pub text_document: lsp::TextDocumentIdentifier,
}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub struct DiagnosticBatchNotificationParams {
- pub batch_index: usize,
- pub messages_len: usize,
-}
-
-/// This notification is only sent for testing purposes
-/// in order to know what the latest diagnostics are.
-pub enum DiagnosticBatchNotification {}
-
-impl lsp::notification::Notification for DiagnosticBatchNotification {
- type Params = DiagnosticBatchNotificationParams;
-
- const METHOD: &'static str = "deno/internalTestDiagnosticBatch";
-}
diff --git a/cli/lsp/mod.rs b/cli/lsp/mod.rs
index d13c90089..0d5552519 100644
--- a/cli/lsp/mod.rs
+++ b/cli/lsp/mod.rs
@@ -8,8 +8,6 @@ use crate::lsp::language_server::LanguageServer;
pub use repl::ReplCompletionItem;
pub use repl::ReplLanguageServer;
-use self::diagnostics::should_send_diagnostic_batch_index_notifications;
-
mod analysis;
mod cache;
mod capabilities;
@@ -38,7 +36,7 @@ pub async fn start() -> Result<(), AnyError> {
let stdin = tokio::io::stdin();
let stdout = tokio::io::stdout();
- let builder = LspService::build(|client| {
+ let (service, socket) = LspService::build(|client| {
language_server::LanguageServer::new(client::Client::from_tower(client))
})
.custom_method(lsp_custom::CACHE_REQUEST, LanguageServer::cache_request)
@@ -60,18 +58,8 @@ pub async fn start() -> Result<(), AnyError> {
lsp_custom::VIRTUAL_TEXT_DOCUMENT,
LanguageServer::virtual_text_document,
)
- .custom_method(lsp_custom::INLAY_HINT, LanguageServer::inlay_hint);
-
- let builder = if should_send_diagnostic_batch_index_notifications() {
- builder.custom_method(
- lsp_custom::LATEST_DIAGNOSTIC_BATCH_INDEX,
- LanguageServer::latest_diagnostic_batch_index_request,
- )
- } else {
- builder
- };
-
- let (service, socket) = builder.finish();
+ .custom_method(lsp_custom::INLAY_HINT, LanguageServer::inlay_hint)
+ .finish();
Server::new(stdin, stdout, socket).serve(service).await;
diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs
index eee83c4a2..4ddf5d4e3 100644
--- a/cli/tests/integration/lsp_tests.rs
+++ b/cli/tests/integration/lsp_tests.rs
@@ -53,7 +53,7 @@ fn lsp_init_tsconfig() {
}
}));
- assert_eq!(diagnostics.all().len(), 0);
+ assert_eq!(diagnostics.viewed().len(), 0);
client.shutdown();
}
@@ -93,7 +93,7 @@ fn lsp_tsconfig_types() {
}
}));
- assert_eq!(diagnostics.all().len(), 0);
+ assert_eq!(diagnostics.viewed().len(), 0);
client.shutdown();
}
@@ -121,7 +121,7 @@ fn lsp_tsconfig_bad_config_path() {
"text": "console.log(Deno.args);\n"
}
}));
- assert_eq!(diagnostics.all().len(), 0);
+ assert_eq!(diagnostics.viewed().len(), 0);
}
#[test]
@@ -142,7 +142,7 @@ fn lsp_triple_slash_types() {
}
}));
- assert_eq!(diagnostics.all().len(), 0);
+ assert_eq!(diagnostics.viewed().len(), 0);
client.shutdown();
}
@@ -176,7 +176,7 @@ fn lsp_import_map() {
}
}));
- assert_eq!(diagnostics.all().len(), 0);
+ assert_eq!(diagnostics.viewed().len(), 0);
let res = client.write_request(
"textDocument/hover",
@@ -223,7 +223,7 @@ fn lsp_import_map_data_url() {
}));
// This indicates that the import map is applied correctly.
- assert!(diagnostics.all().iter().any(|diagnostic| diagnostic.code
+ assert!(diagnostics.viewed().iter().any(|diagnostic| diagnostic.code
== Some(lsp::NumberOrString::String("no-cache".to_string()))
&& diagnostic
.message
@@ -268,7 +268,7 @@ fn lsp_import_map_config_file() {
}
}));
- assert_eq!(diagnostics.all().len(), 0);
+ assert_eq!(diagnostics.viewed().len(), 0);
let res = client.write_request(
"textDocument/hover",
@@ -329,7 +329,7 @@ fn lsp_import_map_embedded_in_config_file() {
}
}));
- assert_eq!(diagnostics.all().len(), 0);
+ assert_eq!(diagnostics.viewed().len(), 0);
let res = client.write_request(
"textDocument/hover",
@@ -431,7 +431,7 @@ fn lsp_import_assertions() {
assert_eq!(
json!(
diagnostics
- .messages_with_file_and_source("file:///a/a.ts", "deno")
+ .with_file_and_source("file:///a/a.ts", "deno")
.diagnostics
),
json!([
@@ -3692,7 +3692,7 @@ fn lsp_code_actions_deno_cache() {
}
}));
assert_eq!(
- diagnostics.messages_with_source("deno"),
+ diagnostics.with_source("deno"),
serde_json::from_value(json!({
"uri": "file:///a/file.ts",
"diagnostics": [{
@@ -3782,7 +3782,7 @@ fn lsp_code_actions_deno_cache_npm() {
}
}));
assert_eq!(
- diagnostics.messages_with_source("deno"),
+ diagnostics.with_source("deno"),
serde_json::from_value(json!({
"uri": "file:///a/file.ts",
"diagnostics": [{
@@ -5139,7 +5139,7 @@ fn lsp_completions_node_specifier() {
}));
let non_existent_diagnostics = diagnostics
- .messages_with_file_and_source("file:///a/file.ts", "deno")
+ .with_file_and_source("file:///a/file.ts", "deno")
.diagnostics
.into_iter()
.filter(|d| {
@@ -5183,7 +5183,7 @@ fn lsp_completions_node_specifier() {
);
let diagnostics = client.read_diagnostics();
let diagnostics = diagnostics
- .messages_with_file_and_source("file:///a/file.ts", "deno")
+ .with_file_and_source("file:///a/file.ts", "deno")
.diagnostics
.into_iter()
.filter(|d| {
@@ -5269,7 +5269,7 @@ fn lsp_completions_node_specifier() {
let diagnostics = client.read_diagnostics();
let cache_diagnostics = diagnostics
- .messages_with_file_and_source("file:///a/file.ts", "deno")
+ .with_file_and_source("file:///a/file.ts", "deno")
.diagnostics
.into_iter()
.filter(|d| {
@@ -5539,7 +5539,7 @@ fn lsp_cache_location() {
"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.all().len(), 7);
+ assert_eq!(diagnostics.viewed().len(), 7);
client.write_request(
"deno/cache",
json!({
@@ -5634,7 +5634,7 @@ fn lsp_tls_cert() {
"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.all();
+ let diagnostics = diagnostics.viewed();
assert_eq!(diagnostics.len(), 7);
client.write_request(
"deno/cache",
@@ -5725,7 +5725,7 @@ fn lsp_diagnostics_warn_redirect() {
);
let diagnostics = client.read_diagnostics();
assert_eq!(
- diagnostics.messages_with_source("deno"),
+ diagnostics.with_source("deno"),
lsp::PublishDiagnosticsParams {
uri: Url::parse("file:///a/file.ts").unwrap(),
diagnostics: vec![
@@ -5802,10 +5802,7 @@ fn lsp_redirect_quick_fix() {
],
}),
);
- let diagnostics = client
- .read_diagnostics()
- .messages_with_source("deno")
- .diagnostics;
+ let diagnostics = client.read_diagnostics().with_source("deno").diagnostics;
let res = client.write_request(
"textDocument/codeAction",
json!(json!({
@@ -5875,25 +5872,35 @@ fn lsp_diagnostics_deprecated() {
},
}));
assert_eq!(
- json!(diagnostics.all_messages()),
- json!([{
- "uri": "file:///a/file.ts",
- "diagnostics": [
- {
- "range": {
- "start": { "line": 3, "character": 0 },
- "end": { "line": 3, "character": 1 }
- },
- "severity": 4,
- "code": 6385,
- "source": "deno-ts",
- "message": "'a' is deprecated.",
- "relatedInformation": [],
- "tags": [2]
- }
- ],
- "version": 1
- }])
+ json!(diagnostics.0),
+ json!([
+ {
+ "uri": "file:///a/file.ts",
+ "diagnostics": [],
+ "version": 1
+ }, {
+ "uri": "file:///a/file.ts",
+ "diagnostics": [],
+ "version": 1
+ }, {
+ "uri": "file:///a/file.ts",
+ "diagnostics": [
+ {
+ "range": {
+ "start": { "line": 3, "character": 0 },
+ "end": { "line": 3, "character": 1 }
+ },
+ "severity": 4,
+ "code": 6385,
+ "source": "deno-ts",
+ "message": "'a' is deprecated.",
+ "relatedInformation": [],
+ "tags": [2]
+ }
+ ],
+ "version": 1
+ }
+ ])
);
client.shutdown();
}
@@ -5922,7 +5929,7 @@ fn lsp_diagnostics_deno_types() {
}
}),
);
- assert_eq!(diagnostics.all().len(), 5);
+ assert_eq!(diagnostics.viewed().len(), 5);
client.shutdown();
}
@@ -5956,8 +5963,7 @@ fn lsp_diagnostics_refresh_dependents() {
}
}));
assert_eq!(
- json!(diagnostics
- .messages_with_file_and_source("file:///a/file_02.ts", "deno-ts")),
+ json!(diagnostics.with_file_and_source("file:///a/file_02.ts", "deno-ts")),
json!({
"uri": "file:///a/file_02.ts",
"diagnostics": [
@@ -5996,7 +6002,7 @@ fn lsp_diagnostics_refresh_dependents() {
}),
);
let diagnostics = client.read_diagnostics();
- assert_eq!(diagnostics.all().len(), 0); // no diagnostics now
+ assert_eq!(diagnostics.viewed().len(), 0); // no diagnostics now
client.shutdown();
assert_eq!(client.queue_len(), 0);
@@ -7050,7 +7056,7 @@ fn lsp_lint_with_config() {
"text": "// TODO: fixme\nexport async function non_camel_case() {\nconsole.log(\"finished!\")\n}"
}
}));
- let diagnostics = diagnostics.all();
+ let diagnostics = diagnostics.viewed();
assert_eq!(diagnostics.len(), 1);
assert_eq!(
diagnostics[0].code,
@@ -7095,7 +7101,7 @@ fn lsp_lint_exclude_with_config() {
}
}),
);
- let diagnostics = diagnostics.all();
+ let diagnostics = diagnostics.viewed();
assert_eq!(diagnostics, Vec::new());
client.shutdown();
}
@@ -7478,7 +7484,7 @@ fn lsp_data_urls_with_jsx_compiler_option() {
"version": 1,
"text": "import a from \"data:application/typescript,export default 5;\";\na;"
}
- })).all();
+ })).viewed();
// there will be a diagnostic about not having cached the data url
assert_eq!(diagnostics.len(), 1);
@@ -7624,7 +7630,7 @@ fn lsp_node_modules_dir() {
refresh_config(&mut client);
let diagnostics = client.read_diagnostics();
- assert_eq!(diagnostics.all().len(), 2, "{:#?}", diagnostics); // not cached
+ assert_eq!(diagnostics.viewed().len(), 2); // not cached
cache(&mut client);
@@ -7641,7 +7647,7 @@ fn lsp_node_modules_dir() {
cache(&mut client);
let diagnostics = client.read_diagnostics();
- assert_eq!(diagnostics.all().len(), 0, "{:#?}", diagnostics);
+ assert_eq!(diagnostics.viewed().len(), 0, "{:#?}", diagnostics);
assert!(temp_dir.path().join("deno.lock").exists());
diff --git a/test_util/src/lsp.rs b/test_util/src/lsp.rs
index 5fbca7f35..a7061543f 100644
--- a/test_util/src/lsp.rs
+++ b/test_util/src/lsp.rs
@@ -87,12 +87,6 @@ impl<'a> From<&'a [u8]> for LspMessage {
}
}
-#[derive(Debug, Deserialize)]
-struct DiagnosticBatchNotificationParams {
- batch_index: usize,
- messages_len: usize,
-}
-
fn read_message<R>(reader: &mut R) -> Result<Option<Vec<u8>>>
where
R: io::Read + io::BufRead,
@@ -180,25 +174,6 @@ impl LspStdoutReader {
cvar.wait(&mut msg_queue);
}
}
-
- pub fn read_latest_message<R>(
- &mut self,
- mut get_match: impl FnMut(&LspMessage) -> Option<R>,
- ) -> R {
- let (msg_queue, cvar) = &*self.pending_messages;
- let mut msg_queue = msg_queue.lock();
- loop {
- for i in (0..msg_queue.len()).rev() {
- let msg = &msg_queue[i];
- if let Some(result) = get_match(msg) {
- let msg = msg_queue.remove(i);
- self.read_messages.push(msg);
- return result;
- }
- }
- cvar.wait(&mut msg_queue);
- }
- }
}
pub struct InitializeParamsBuilder {
@@ -510,8 +485,6 @@ impl LspClientBuilder {
command
.env("DENO_DIR", deno_dir.path())
.env("NPM_CONFIG_REGISTRY", npm_registry_url())
- // turn on diagnostic synchronization communication
- .env("DENO_DONT_USE_INTERNAL_LSP_DIAGNOSTIC_SYNC_FLAG", "1")
.arg("lsp")
.stdin(Stdio::piped())
.stdout(Stdio::piped());
@@ -537,6 +510,7 @@ impl LspClientBuilder {
.unwrap_or_else(|| TestContextBuilder::new().build()),
writer,
deno_dir,
+ diagnosable_open_file_count: 0,
})
}
}
@@ -549,6 +523,7 @@ pub struct LspClient {
writer: io::BufWriter<ChildStdin>,
deno_dir: TempDir,
context: TestContext,
+ diagnosable_open_file_count: usize,
}
impl Drop for LspClient {
@@ -634,6 +609,20 @@ impl LspClient {
}
pub fn did_open_raw(&mut self, params: Value) {
+ let text_doc = params
+ .as_object()
+ .unwrap()
+ .get("textDocument")
+ .unwrap()
+ .as_object()
+ .unwrap();
+ if matches!(
+ text_doc.get("languageId").unwrap().as_str().unwrap(),
+ "typescript" | "javascript"
+ ) {
+ self.diagnosable_open_file_count += 1;
+ }
+
self.write_notification("textDocument/didOpen", params);
}
@@ -643,46 +632,11 @@ impl LspClient {
self.write_response(id, result);
}
- fn get_latest_diagnostic_batch_index(&mut self) -> usize {
- let result = self
- .write_request("deno/internalLatestDiagnosticBatchIndex", json!(null));
- result.as_u64().unwrap() as usize
- }
-
- /// Reads the latest diagnostics. It's assumed that
pub fn read_diagnostics(&mut self) -> CollectedDiagnostics {
- // ask the server what the latest diagnostic batch index is
- let latest_diagnostic_batch_index =
- self.get_latest_diagnostic_batch_index();
-
- // now wait for three (deno, lint, and typescript diagnostics) batch
- // notification messages for that index
- let mut read = 0;
- let mut total_messages_len = 0;
- while read < 3 {
- let (method, response) =
- self.read_notification::<DiagnosticBatchNotificationParams>();
- assert_eq!(method, "deno/internalTestDiagnosticBatch");
- let response = response.unwrap();
- if response.batch_index == latest_diagnostic_batch_index {
- read += 1;
- total_messages_len += response.messages_len;
- }
+ let mut all_diagnostics = Vec::new();
+ for _ in 0..self.diagnosable_open_file_count {
+ all_diagnostics.extend(read_diagnostics(self).0);
}
-
- // now read the latest diagnostic messages
- let mut all_diagnostics = Vec::with_capacity(total_messages_len);
- let mut seen_files = HashSet::new();
- for _ in 0..total_messages_len {
- let (method, response) =
- self.read_latest_notification::<lsp::PublishDiagnosticsParams>();
- assert_eq!(method, "textDocument/publishDiagnostics");
- let response = response.unwrap();
- if seen_files.insert(response.uri.to_string()) {
- all_diagnostics.push(response);
- }
- }
-
CollectedDiagnostics(all_diagnostics)
}
@@ -714,19 +668,6 @@ impl LspClient {
})
}
- pub fn read_latest_notification<R>(&mut self) -> (String, Option<R>)
- where
- R: de::DeserializeOwned,
- {
- self.reader.read_latest_message(|msg| match msg {
- LspMessage::Notification(method, maybe_params) => {
- let params = serde_json::from_value(maybe_params.clone()?).ok()?;
- Some((method.to_string(), params))
- }
- _ => None,
- })
- }
-
pub fn read_notification_with_method<R>(
&mut self,
expected_method: &str,
@@ -878,29 +819,35 @@ impl LspClient {
}
#[derive(Debug, Clone)]
-pub struct CollectedDiagnostics(Vec<lsp::PublishDiagnosticsParams>);
+pub struct CollectedDiagnostics(pub Vec<lsp::PublishDiagnosticsParams>);
impl CollectedDiagnostics {
/// Gets the diagnostics that the editor will see after all the publishes.
- pub fn all(&self) -> Vec<lsp::Diagnostic> {
+ pub fn viewed(&self) -> Vec<lsp::Diagnostic> {
self
- .all_messages()
+ .viewed_messages()
.into_iter()
.flat_map(|m| m.diagnostics)
.collect()
}
/// Gets the messages that the editor will see after all the publishes.
- pub fn all_messages(&self) -> Vec<lsp::PublishDiagnosticsParams> {
- self.0.clone()
+ pub fn viewed_messages(&self) -> Vec<lsp::PublishDiagnosticsParams> {
+ // go over the publishes in reverse order in order to get
+ // the final messages that will be shown in the editor
+ let mut messages = Vec::new();
+ let mut had_specifier = HashSet::new();
+ for message in self.0.iter().rev() {
+ if had_specifier.insert(message.uri.clone()) {
+ messages.insert(0, message.clone());
+ }
+ }
+ messages
}
- pub fn messages_with_source(
- &self,
- source: &str,
- ) -> lsp::PublishDiagnosticsParams {
+ pub fn with_source(&self, source: &str) -> lsp::PublishDiagnosticsParams {
self
- .all_messages()
+ .viewed_messages()
.iter()
.find(|p| {
p.diagnostics
@@ -911,14 +858,14 @@ impl CollectedDiagnostics {
.unwrap()
}
- pub fn messages_with_file_and_source(
+ pub fn with_file_and_source(
&self,
specifier: &str,
source: &str,
) -> lsp::PublishDiagnosticsParams {
let specifier = Url::parse(specifier).unwrap();
self
- .all_messages()
+ .viewed_messages()
.iter()
.find(|p| {
p.uri == specifier
@@ -932,6 +879,18 @@ impl CollectedDiagnostics {
}
}
+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.read_notification::<lsp::PublishDiagnosticsParams>();
+ assert_eq!(method, "textDocument/publishDiagnostics");
+ diagnostics.push(response.unwrap());
+ }
+ CollectedDiagnostics(diagnostics)
+}
+
#[cfg(test)]
mod tests {
use super::*;