diff options
Diffstat (limited to 'cli/lsp/diagnostics.rs')
-rw-r--r-- | cli/lsp/diagnostics.rs | 201 |
1 files changed, 98 insertions, 103 deletions
diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index a7f027c1b..1d0a1fac9 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -2,8 +2,8 @@ use super::analysis::get_lint_references; use super::analysis::references_to_diagnostics; +use super::language_server::StateSnapshot; use super::memory_cache::FileId; -use super::state::ServerStateSnapshot; use super::tsc; use crate::diagnostics; @@ -12,52 +12,11 @@ use crate::media_type::MediaType; use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::serde_json::Value; -use deno_core::url::Url; -use deno_core::JsRuntime; +use lspower::lsp_types; use std::collections::HashMap; use std::collections::HashSet; use std::mem; -impl<'a> From<&'a diagnostics::DiagnosticCategory> - for lsp_types::DiagnosticSeverity -{ - fn from(category: &'a diagnostics::DiagnosticCategory) -> Self { - match category { - diagnostics::DiagnosticCategory::Error => { - lsp_types::DiagnosticSeverity::Error - } - diagnostics::DiagnosticCategory::Warning => { - lsp_types::DiagnosticSeverity::Warning - } - diagnostics::DiagnosticCategory::Suggestion => { - lsp_types::DiagnosticSeverity::Hint - } - diagnostics::DiagnosticCategory::Message => { - lsp_types::DiagnosticSeverity::Information - } - } - } -} - -impl<'a> From<&'a diagnostics::Position> for lsp_types::Position { - fn from(pos: &'a diagnostics::Position) -> Self { - Self { - line: pos.line as u32, - character: pos.character as u32, - } - } -} - -fn to_lsp_range( - start: &diagnostics::Position, - end: &diagnostics::Position, -) -> lsp_types::Range { - lsp_types::Range { - start: start.into(), - end: end.into(), - } -} - #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum DiagnosticSource { Lint, @@ -108,41 +67,84 @@ impl DiagnosticCollection { pub type DiagnosticVec = Vec<(FileId, Option<i32>, Vec<lsp_types::Diagnostic>)>; -pub fn generate_linting_diagnostics( - state: &ServerStateSnapshot, +pub async fn generate_lint_diagnostics( + state_snapshot: StateSnapshot, + diagnostic_collection: DiagnosticCollection, ) -> DiagnosticVec { - if !state.config.settings.lint { - return Vec::new(); - } - let mut diagnostics = Vec::new(); - let file_cache = state.file_cache.read().unwrap(); - for (specifier, doc_data) in state.doc_data.iter() { - let file_id = file_cache.lookup(specifier).unwrap(); - let version = doc_data.version; - let current_version = state.diagnostics.get_version(&file_id); - if version != current_version { - let media_type = MediaType::from(specifier); - if let Ok(source_code) = file_cache.get_contents(file_id) { - if let Ok(references) = - get_lint_references(specifier, &media_type, &source_code) - { - if !references.is_empty() { - diagnostics.push(( - file_id, - version, - references_to_diagnostics(references), - )); - } else { - diagnostics.push((file_id, version, Vec::new())); + tokio::task::spawn_blocking(move || { + let mut diagnostic_list = Vec::new(); + + let file_cache = state_snapshot.file_cache.read().unwrap(); + for (specifier, doc_data) in state_snapshot.doc_data.iter() { + let file_id = file_cache.lookup(specifier).unwrap(); + let version = doc_data.version; + let current_version = diagnostic_collection.get_version(&file_id); + if version != current_version { + let media_type = MediaType::from(specifier); + if let Ok(source_code) = file_cache.get_contents(file_id) { + if let Ok(references) = + get_lint_references(specifier, &media_type, &source_code) + { + if !references.is_empty() { + diagnostic_list.push(( + file_id, + version, + references_to_diagnostics(references), + )); + } else { + diagnostic_list.push((file_id, version, Vec::new())); + } } + } else { + error!("Missing file contents for: {}", specifier); } - } else { - error!("Missing file contents for: {}", specifier); } } + + diagnostic_list + }) + .await + .unwrap() +} + +impl<'a> From<&'a diagnostics::DiagnosticCategory> + for lsp_types::DiagnosticSeverity +{ + fn from(category: &'a diagnostics::DiagnosticCategory) -> Self { + match category { + diagnostics::DiagnosticCategory::Error => { + lsp_types::DiagnosticSeverity::Error + } + diagnostics::DiagnosticCategory::Warning => { + lsp_types::DiagnosticSeverity::Warning + } + diagnostics::DiagnosticCategory::Suggestion => { + lsp_types::DiagnosticSeverity::Hint + } + diagnostics::DiagnosticCategory::Message => { + lsp_types::DiagnosticSeverity::Information + } + } + } +} + +impl<'a> From<&'a diagnostics::Position> for lsp_types::Position { + fn from(pos: &'a diagnostics::Position) -> Self { + Self { + line: pos.line as u32, + character: pos.character as u32, + } } +} - diagnostics +fn to_lsp_range( + start: &diagnostics::Position, + end: &diagnostics::Position, +) -> lsp_types::Range { + lsp_types::Range { + start: start.into(), + end: end.into(), + } } type TsDiagnostics = Vec<diagnostics::Diagnostic>; @@ -168,7 +170,7 @@ fn to_lsp_related_information( if let (Some(source), Some(start), Some(end)) = (&ri.source, &ri.start, &ri.end) { - let uri = Url::parse(&source).unwrap(); + let uri = lsp_types::Url::parse(&source).unwrap(); Some(lsp_types::DiagnosticRelatedInformation { location: lsp_types::Location { uri, @@ -223,43 +225,36 @@ fn ts_json_to_diagnostics( ) } -pub fn generate_ts_diagnostics( - state: &ServerStateSnapshot, - runtime: &mut JsRuntime, +pub async fn generate_ts_diagnostics( + ts_server: &tsc::TsServer, + diagnostic_collection: &DiagnosticCollection, + state_snapshot: StateSnapshot, ) -> Result<DiagnosticVec, AnyError> { - if !state.config.settings.enable { - return Ok(Vec::new()); - } let mut diagnostics = Vec::new(); - let file_cache = state.file_cache.read().unwrap(); - for (specifier, doc_data) in state.doc_data.iter() { - let file_id = file_cache.lookup(specifier).unwrap(); + let state_snapshot_ = state_snapshot.clone(); + for (specifier, doc_data) in state_snapshot_.doc_data.iter() { + let file_id = { + // TODO(lucacasonato): this is highly inefficient + let file_cache = state_snapshot_.file_cache.read().unwrap(); + file_cache.lookup(specifier).unwrap() + }; let version = doc_data.version; - let current_version = state.diagnostics.get_version(&file_id); + let current_version = diagnostic_collection.get_version(&file_id); if version != current_version { // TODO(@kitsonk): consider refactoring to get all diagnostics in one shot // for a file. - let request_semantic_diagnostics = - tsc::RequestMethod::GetSemanticDiagnostics(specifier.clone()); - let mut ts_diagnostics = ts_json_to_diagnostics(tsc::request( - runtime, - state, - request_semantic_diagnostics, - )?)?; - let request_suggestion_diagnostics = - tsc::RequestMethod::GetSuggestionDiagnostics(specifier.clone()); - ts_diagnostics.append(&mut ts_json_to_diagnostics(tsc::request( - runtime, - state, - request_suggestion_diagnostics, - )?)?); - let request_syntactic_diagnostics = - tsc::RequestMethod::GetSyntacticDiagnostics(specifier.clone()); - ts_diagnostics.append(&mut ts_json_to_diagnostics(tsc::request( - runtime, - state, - request_syntactic_diagnostics, - )?)?); + let req = tsc::RequestMethod::GetSemanticDiagnostics(specifier.clone()); + let mut ts_diagnostics = ts_json_to_diagnostics( + ts_server.request(state_snapshot.clone(), req).await?, + )?; + let req = tsc::RequestMethod::GetSuggestionDiagnostics(specifier.clone()); + ts_diagnostics.append(&mut ts_json_to_diagnostics( + ts_server.request(state_snapshot.clone(), req).await?, + )?); + let req = tsc::RequestMethod::GetSyntacticDiagnostics(specifier.clone()); + ts_diagnostics.append(&mut ts_json_to_diagnostics( + ts_server.request(state_snapshot.clone(), req).await?, + )?); diagnostics.push((file_id, version, ts_diagnostics)); } } |