diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index a629757788..47e36d1328 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -459,6 +459,19 @@ impl Default for LanguagePreferences { } } +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SuggestionActionsSettings { + #[serde(default = "is_true")] + pub enabled: bool, +} + +impl Default for SuggestionActionsSettings { + fn default() -> Self { + SuggestionActionsSettings { enabled: true } + } +} + #[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct UpdateImportsOnFileMoveOptions { @@ -490,6 +503,8 @@ pub struct LanguageWorkspaceSettings { #[serde(default)] pub suggest: CompletionSettings, #[serde(default)] + pub suggestion_actions: SuggestionActionsSettings, + #[serde(default)] pub update_imports_on_file_move: UpdateImportsOnFileMoveOptions, } @@ -2292,6 +2307,7 @@ mod tests { enabled: true, }, }, + suggestion_actions: SuggestionActionsSettings { enabled: true }, update_imports_on_file_move: UpdateImportsOnFileMoveOptions { enabled: UpdateImportsOnFileMoveEnabled::Prompt } @@ -2338,6 +2354,7 @@ mod tests { enabled: true, }, }, + suggestion_actions: SuggestionActionsSettings { enabled: true }, update_imports_on_file_move: UpdateImportsOnFileMoveOptions { enabled: UpdateImportsOnFileMoveEnabled::Prompt } diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index 01fc3bf69e..e99e5a19b0 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -24,6 +24,7 @@ use crate::resolver::SloppyImportsCachedFs; use crate::tools::lint::CliLinter; use crate::tools::lint::CliLinterOptions; use crate::tools::lint::LintRuleProvider; +use crate::tsc::DiagnosticCategory; use crate::util::path::to_percent_decoded_str; use deno_ast::MediaType; @@ -906,8 +907,22 @@ async fn generate_ts_diagnostics( } else { Default::default() }; - for (specifier_str, ts_json_diagnostics) in ts_diagnostics_map { + for (specifier_str, mut ts_json_diagnostics) in ts_diagnostics_map { let specifier = resolve_url(&specifier_str)?; + let suggestion_actions_settings = snapshot + .config + .language_settings_for_specifier(&specifier) + .map(|s| s.suggestion_actions.clone()) + .unwrap_or_default(); + if !suggestion_actions_settings.enabled { + ts_json_diagnostics.retain(|d| { + d.category != DiagnosticCategory::Suggestion + // Still show deprecated and unused diagnostics. + // https://github.com/microsoft/vscode/blob/ce50bd4876af457f64d83cfd956bc916535285f4/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts#L113-L114 + || d.reports_deprecated == Some(true) + || d.reports_unnecessary == Some(true) + }); + } let version = snapshot .documents .get(&specifier) diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 957c3a6859..fddcd6e738 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -5746,6 +5746,7 @@ mod tests { "sourceLine": " import { A } from \".\";", "category": 2, "code": 6133, + "reportsUnnecessary": true, }] }) ); @@ -5828,6 +5829,7 @@ mod tests { "sourceLine": " import {", "category": 2, "code": 6192, + "reportsUnnecessary": true, }, { "start": { "line": 8, diff --git a/cli/tsc/diagnostics.rs b/cli/tsc/diagnostics.rs index d3795706eb..e4cc80723f 100644 --- a/cli/tsc/diagnostics.rs +++ b/cli/tsc/diagnostics.rs @@ -133,6 +133,12 @@ pub struct Diagnostic { pub file_name: Option, #[serde(skip_serializing_if = "Option::is_none")] pub related_information: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub reports_deprecated: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub reports_unnecessary: Option, + #[serde(flatten)] + pub other: deno_core::serde_json::Map, } impl Diagnostic { diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index a8e8d73b68..4c18d1a2b0 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -1444,6 +1444,9 @@ mod tests { source_line: None, file_name: None, related_information: None, + reports_deprecated: None, + reports_unnecessary: None, + other: Default::default(), }]), stats: Stats(vec![("a".to_string(), 12)]) }) diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs index 13a3c0d69b..92cefb98f0 100644 --- a/tests/integration/lsp_tests.rs +++ b/tests/integration/lsp_tests.rs @@ -2082,6 +2082,88 @@ fn lsp_inlay_hints_not_enabled() { client.shutdown(); } +#[test] +fn lsp_suggestion_actions_disabled() { + let context = TestContextBuilder::new().use_temp_cwd().build(); + let temp_dir = context.temp_dir(); + let mut client = context.new_lsp_command().build(); + client.initialize_default(); + client.change_configuration(json!({ + "deno": { + "enable": true, + "lint": false, + }, + "typescript": { + "suggestionActions": { + "enabled": false, + }, + }, + })); + client.read_diagnostics(); + let diagnostics = client.did_open(json!({ + "textDocument": { + "uri": temp_dir.url().join("file.ts").unwrap(), + "languageId": "typescript", + "version": 1, + "text": r#" + // The settings should disable the suggestion for this to be async. + function asyncLikeFunction() { + return new Promise((r) => r(null)).then((v) => v); + } + console.log(asyncLikeFunction); + + // Deprecated warnings should remain. + /** @deprecated */ + function deprecatedFunction() {} + console.log(deprecatedFunction); + + // Unused warnings should remain. + const unsusedVariable = 1; + "#, + }, + })); + assert_eq!( + json!(diagnostics.all()), + json!([ + { + "range": { + "start": { "line": 10, "character": 20 }, + "end": { "line": 10, "character": 38 }, + }, + "severity": 4, + "code": 6385, + "source": "deno-ts", + "message": "'deprecatedFunction' is deprecated.", + "relatedInformation": [ + { + "location": { + "uri": temp_dir.url().join("file.ts").unwrap(), + "range": { + "start": { "line": 8, "character": 12 }, + "end": { "line": 8, "character": 24 }, + }, + }, + "message": "The declaration was marked as deprecated here.", + }, + ], + "tags": [2], + }, + { + "range": { + "start": { "line": 13, "character": 14 }, + "end": { "line": 13, "character": 29 }, + }, + "severity": 4, + "code": 6133, + "source": "deno-ts", + "message": "'unsusedVariable' is declared but its value is never read.", + "tags": [1], + }, + ]), + ); + client.shutdown(); +} + #[test] fn lsp_workspace_disable_enable_paths() { fn run_test(use_trailing_slash: bool) {