From 2fa0b20ce05a1d6b8f9bf0f0d9f1dfb15b84fb9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 16 Jun 2020 21:28:57 +0300 Subject: Remove debugging code for incremental sync --- crates/rust-analyzer/src/main_loop.rs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index cc9bb1726..887253d5b 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -669,14 +669,11 @@ fn apply_document_changes( mut line_index: Cow<'_, LineIndex>, content_changes: Vec, ) { - // Remove when https://github.com/rust-analyzer/rust-analyzer/issues/4263 is fixed. - let backup_text = old_text.clone(); - let backup_changes = content_changes.clone(); - // The changes we got must be applied sequentially, but can cross lines so we // have to keep our line index updated. // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we // remember the last valid line in the index and only rebuild it if needed. + // The VFS will normalize the end of lines to `\n`. enum IndexValid { All, UpToLineExclusive(u64), @@ -700,19 +697,7 @@ fn apply_document_changes( } index_valid = IndexValid::UpToLineExclusive(range.start.line); let range = from_proto::text_range(&line_index, range); - let mut text = old_text.to_owned(); - match std::panic::catch_unwind(move || { - text.replace_range(Range::::from(range), &change.text); - text - }) { - Ok(t) => *old_text = t, - Err(e) => { - eprintln!("Bug in incremental text synchronization. Please report the following output on https://github.com/rust-analyzer/rust-analyzer/issues/4263"); - dbg!(&backup_text); - dbg!(&backup_changes); - std::panic::resume_unwind(e); - } - } + old_text.replace_range(Range::::from(range), &change.text); } None => { *old_text = change.text; -- cgit v1.2.3 From 8ff91cf6b649ea241e886726df91d9bcb6b6c7cb Mon Sep 17 00:00:00 2001 From: Leander Tentrup Date: Tue, 16 Jun 2020 23:03:59 +0200 Subject: Inspect markdown code fences to determine whether to apply syntax highlighting --- crates/ra_ide/src/snapshots/highlight_doctest.html | 6 +++++- crates/ra_ide/src/syntax_highlighting/injection.rs | 14 ++++++++++++-- crates/ra_ide/src/syntax_highlighting/tests.rs | 6 +++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/src/snapshots/highlight_doctest.html index 5228df267..13a5d1b12 100644 --- a/crates/ra_ide/src/snapshots/highlight_doctest.html +++ b/crates/ra_ide/src/snapshots/highlight_doctest.html @@ -73,9 +73,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd /// /// ``` /// - /// ``` + /// ```rust,no_run /// let foobar = Foo::new().bar(); /// ``` + /// + /// ```sh + /// echo 1 + /// ``` pub fn foo(&self) -> bool { true } diff --git a/crates/ra_ide/src/syntax_highlighting/injection.rs b/crates/ra_ide/src/syntax_highlighting/injection.rs index a02ffe59e..929a5cc5c 100644 --- a/crates/ra_ide/src/syntax_highlighting/injection.rs +++ b/crates/ra_ide/src/syntax_highlighting/injection.rs @@ -53,6 +53,10 @@ pub(super) fn highlight_injection( /// Mapping from extracted documentation code to original code type RangesMap = BTreeMap; +const RUSTDOC_FENCE: &'static str = "```"; +const RUSTDOC_FENCE_TOKENS: &[&'static str] = + &["", "rust", "should_panic", "ignore", "no_run", "compile_fail", "edition2015", "edition2018"]; + /// Extracts Rust code from documentation comments as well as a mapping from /// the extracted source code back to the original source ranges. /// Lastly, a vector of new comment highlight ranges (spanning only the @@ -67,6 +71,7 @@ pub(super) fn extract_doc_comments( // Mapping from extracted documentation code to original code let mut range_mapping: RangesMap = BTreeMap::new(); let mut line_start = TextSize::try_from(prefix.len()).unwrap(); + let mut is_codeblock = false; let mut is_doctest = false; // Replace the original, line-spanning comment ranges by new, only comment-prefix // spanning comment ranges. @@ -76,8 +81,13 @@ pub(super) fn extract_doc_comments( .filter_map(|el| el.into_token().and_then(ast::Comment::cast)) .filter(|comment| comment.kind().doc.is_some()) .filter(|comment| { - if comment.text().contains("```") { - is_doctest = !is_doctest; + if let Some(idx) = comment.text().find(RUSTDOC_FENCE) { + is_codeblock = !is_codeblock; + // Check whether code is rust by inspecting fence guards + let guards = &comment.text()[idx + RUSTDOC_FENCE.len()..]; + let is_rust = + guards.split(',').all(|sub| RUSTDOC_FENCE_TOKENS.contains(&sub.trim())); + is_doctest = is_codeblock && is_rust; false } else { is_doctest diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index 062b3ff4a..ebf5b50ac 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs @@ -329,9 +329,13 @@ impl Foo { /// /// ``` /// - /// ``` + /// ```rust,no_run /// let foobar = Foo::new().bar(); /// ``` + /// + /// ```sh + /// echo 1 + /// ``` pub fn foo(&self) -> bool { true } -- cgit v1.2.3 From 656e95211edf26bd82bd66f53ca3bcdfb7296e81 Mon Sep 17 00:00:00 2001 From: Gabriel Valfridsson Date: Tue, 16 Jun 2020 22:26:33 +0200 Subject: Warnings as hint or info --- crates/rust-analyzer/src/config.rs | 5 + crates/rust-analyzer/src/diagnostics.rs | 6 + ..._tests__snap_rustc_unused_variable_as_hint.snap | 86 +++++++++ ..._tests__snap_rustc_unused_variable_as_info.snap | 86 +++++++++ crates/rust-analyzer/src/diagnostics/to_proto.rs | 213 +++++++++++++++++++-- crates/rust-analyzer/src/main_loop.rs | 1 + editors/code/package.json | 18 ++ 7 files changed, 402 insertions(+), 13 deletions(-) create mode 100644 crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap create mode 100644 crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 0e7a937a0..0df7427cb 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -9,6 +9,7 @@ use std::{ffi::OsString, path::PathBuf}; +use crate::diagnostics::DiagnosticsConfig; use lsp_types::ClientCapabilities; use ra_flycheck::FlycheckConfig; use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; @@ -20,6 +21,7 @@ pub struct Config { pub client_caps: ClientCapsConfig, pub publish_diagnostics: bool, + pub diagnostics: DiagnosticsConfig, pub lru_capacity: Option, pub proc_macro_srv: Option<(PathBuf, Vec)>, pub files: FilesConfig, @@ -136,6 +138,7 @@ impl Default for Config { with_sysroot: true, publish_diagnostics: true, + diagnostics: DiagnosticsConfig::default(), lru_capacity: None, proc_macro_srv: None, files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, @@ -184,6 +187,8 @@ impl Config { set(value, "/withSysroot", &mut self.with_sysroot); set(value, "/diagnostics/enable", &mut self.publish_diagnostics); + set(value, "/diagnostics/warningsAsInfo", &mut self.diagnostics.warnings_as_info); + set(value, "/diagnostics/warningsAsHint", &mut self.diagnostics.warnings_as_hint); set(value, "/lruCapacity", &mut self.lru_capacity); self.files.watcher = match get(value, "/files/watcher") { Some("client") => FilesWatcher::Client, diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index 25856c543..290609e7f 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -10,6 +10,12 @@ use crate::lsp_ext; pub type CheckFixes = Arc>>; +#[derive(Debug, Default, Clone)] +pub struct DiagnosticsConfig { + pub warnings_as_info: Vec, + pub warnings_as_hint: Vec, +} + #[derive(Debug, Default, Clone)] pub struct DiagnosticCollection { pub native: HashMap>, diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap new file mode 100644 index 000000000..f0273315e --- /dev/null +++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_hint.snap @@ -0,0 +1,86 @@ +--- +source: crates/rust-analyzer/src/diagnostics/to_proto.rs +expression: diag +--- +[ + MappedRustDiagnostic { + location: Location { + uri: "file:///test/driver/subcommand/repl.rs", + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + }, + diagnostic: Diagnostic { + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + severity: Some( + Hint, + ), + code: Some( + String( + "unused_variables", + ), + ), + source: Some( + "rustc", + ), + message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", + related_information: None, + tags: Some( + [ + Unnecessary, + ], + ), + }, + fixes: [ + CodeAction { + title: "consider prefixing with an underscore", + id: None, + group: None, + kind: Some( + "quickfix", + ), + command: None, + edit: Some( + SnippetWorkspaceEdit { + changes: Some( + { + "file:///test/driver/subcommand/repl.rs": [ + TextEdit { + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + new_text: "_foo", + }, + ], + }, + ), + document_changes: None, + }, + ), + }, + ], + }, +] diff --git a/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap new file mode 100644 index 000000000..85fd050fd --- /dev/null +++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable_as_info.snap @@ -0,0 +1,86 @@ +--- +source: crates/rust-analyzer/src/diagnostics/to_proto.rs +expression: diag +--- +[ + MappedRustDiagnostic { + location: Location { + uri: "file:///test/driver/subcommand/repl.rs", + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + }, + diagnostic: Diagnostic { + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + severity: Some( + Information, + ), + code: Some( + String( + "unused_variables", + ), + ), + source: Some( + "rustc", + ), + message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", + related_information: None, + tags: Some( + [ + Unnecessary, + ], + ), + }, + fixes: [ + CodeAction { + title: "consider prefixing with an underscore", + id: None, + group: None, + kind: Some( + "quickfix", + ), + command: None, + edit: Some( + SnippetWorkspaceEdit { + changes: Some( + { + "file:///test/driver/subcommand/repl.rs": [ + TextEdit { + range: Range { + start: Position { + line: 290, + character: 8, + }, + end: Position { + line: 290, + character: 11, + }, + }, + new_text: "_foo", + }, + ], + }, + ), + document_changes: None, + }, + ), + }, + ], + }, +] diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index 24ff9b280..ba74f15f3 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -9,14 +9,24 @@ use lsp_types::{ use ra_flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion}; use stdx::format_to; +use super::DiagnosticsConfig; use crate::{lsp_ext, to_proto::url_from_abs_path}; -/// Converts a Rust level string to a LSP severity -fn map_level_to_severity(val: DiagnosticLevel) -> Option { - let res = match val { +/// Determines the LSP severity from a diagnostic +fn map_diagnostic_to_severity( + config: &DiagnosticsConfig, + val: &ra_flycheck::Diagnostic, +) -> Option { + let res = match val.level { DiagnosticLevel::Ice => DiagnosticSeverity::Error, DiagnosticLevel::Error => DiagnosticSeverity::Error, - DiagnosticLevel::Warning => DiagnosticSeverity::Warning, + DiagnosticLevel::Warning => match &val.code { + Some(code) if config.warnings_as_hint.contains(&code.code) => DiagnosticSeverity::Hint, + Some(code) if config.warnings_as_info.contains(&code.code) => { + DiagnosticSeverity::Information + } + _ => DiagnosticSeverity::Warning, + }, DiagnosticLevel::Note => DiagnosticSeverity::Information, DiagnosticLevel::Help => DiagnosticSeverity::Hint, DiagnosticLevel::Unknown => return None, @@ -172,6 +182,7 @@ pub(crate) struct MappedRustDiagnostic { /// /// If the diagnostic has no primary span this will return `None` pub(crate) fn map_rust_diagnostic_to_lsp( + config: &DiagnosticsConfig, rd: &ra_flycheck::Diagnostic, workspace_root: &Path, ) -> Vec { @@ -180,7 +191,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( return Vec::new(); } - let severity = map_level_to_severity(rd.level); + let severity = map_diagnostic_to_severity(config, rd); let mut source = String::from("rustc"); let mut code = rd.code.as_ref().map(|c| c.code.clone()); @@ -328,7 +339,7 @@ mod tests { ); let workspace_root = Path::new("/test/"); - let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); + let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); insta::assert_debug_snapshot!(diag); } @@ -410,7 +421,183 @@ mod tests { ); let workspace_root = Path::new("/test/"); - let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); + let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); + insta::assert_debug_snapshot!(diag); + } + + #[test] + #[cfg(not(windows))] + fn snap_rustc_unused_variable_as_info() { + let diag = parse_diagnostic( + r##"{ + "message": "unused variable: `foo`", + "code": { + "code": "unused_variables", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "driver/subcommand/repl.rs", + "byte_start": 9228, + "byte_end": 9231, + "line_start": 291, + "line_end": 291, + "column_start": 9, + "column_end": 12, + "is_primary": true, + "text": [ + { + "text": " let foo = 42;", + "highlight_start": 9, + "highlight_end": 12 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "#[warn(unused_variables)] on by default", + "code": null, + "level": "note", + "spans": [], + "children": [], + "rendered": null + }, + { + "message": "consider prefixing with an underscore", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "driver/subcommand/repl.rs", + "byte_start": 9228, + "byte_end": 9231, + "line_start": 291, + "line_end": 291, + "column_start": 9, + "column_end": 12, + "is_primary": true, + "text": [ + { + "text": " let foo = 42;", + "highlight_start": 9, + "highlight_end": 12 + } + ], + "label": null, + "suggested_replacement": "_foo", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n" + }"##, + ); + + let config = DiagnosticsConfig { + warnings_as_info: vec!["unused_variables".to_string()], + ..DiagnosticsConfig::default() + }; + + let workspace_root = Path::new("/test/"); + let diag = map_rust_diagnostic_to_lsp(&config, &diag, workspace_root); + insta::assert_debug_snapshot!(diag); + } + + #[test] + #[cfg(not(windows))] + fn snap_rustc_unused_variable_as_hint() { + let diag = parse_diagnostic( + r##"{ + "message": "unused variable: `foo`", + "code": { + "code": "unused_variables", + "explanation": null + }, + "level": "warning", + "spans": [ + { + "file_name": "driver/subcommand/repl.rs", + "byte_start": 9228, + "byte_end": 9231, + "line_start": 291, + "line_end": 291, + "column_start": 9, + "column_end": 12, + "is_primary": true, + "text": [ + { + "text": " let foo = 42;", + "highlight_start": 9, + "highlight_end": 12 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "#[warn(unused_variables)] on by default", + "code": null, + "level": "note", + "spans": [], + "children": [], + "rendered": null + }, + { + "message": "consider prefixing with an underscore", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "driver/subcommand/repl.rs", + "byte_start": 9228, + "byte_end": 9231, + "line_start": 291, + "line_end": 291, + "column_start": 9, + "column_end": 12, + "is_primary": true, + "text": [ + { + "text": " let foo = 42;", + "highlight_start": 9, + "highlight_end": 12 + } + ], + "label": null, + "suggested_replacement": "_foo", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + "rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n" + }"##, + ); + + let config = DiagnosticsConfig { + warnings_as_hint: vec!["unused_variables".to_string()], + ..DiagnosticsConfig::default() + }; + + let workspace_root = Path::new("/test/"); + let diag = map_rust_diagnostic_to_lsp(&config, &diag, workspace_root); insta::assert_debug_snapshot!(diag); } @@ -534,7 +721,7 @@ mod tests { ); let workspace_root = Path::new("/test/"); - let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); + let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); insta::assert_debug_snapshot!(diag); } @@ -654,7 +841,7 @@ mod tests { ); let workspace_root = Path::new("/test/"); - let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); + let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); insta::assert_debug_snapshot!(diag); } @@ -697,7 +884,7 @@ mod tests { ); let workspace_root = Path::new("/test/"); - let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); + let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); insta::assert_debug_snapshot!(diag); } @@ -968,7 +1155,7 @@ mod tests { ); let workspace_root = Path::new("/test/"); - let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); + let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); insta::assert_debug_snapshot!(diag); } @@ -1197,7 +1384,7 @@ mod tests { ); let workspace_root = Path::new("/test/"); - let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); + let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); insta::assert_debug_snapshot!(diag); } @@ -1330,7 +1517,7 @@ mod tests { ); let workspace_root = Path::new("/test/"); - let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root); + let diag = map_rust_diagnostic_to_lsp(&DiagnosticsConfig::default(), &diag, workspace_root); insta::assert_debug_snapshot!(diag); } } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index cc9bb1726..534d9f223 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -734,6 +734,7 @@ fn on_check_task( CheckTask::AddDiagnostic { workspace_root, diagnostic } => { let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( + &global_state.config.diagnostics, &diagnostic, &workspace_root, ); diff --git a/editors/code/package.json b/editors/code/package.json index e2027970d..3acc375f6 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -525,6 +525,24 @@ "markdownDescription": "Internal config for debugging, disables loading of sysroot crates", "type": "boolean", "default": true + }, + "rust-analyzer.diagnostics.warningsAsInfo": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + }, + "description": "List of warnings that should be displayed with info severity.\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the problems panel.", + "default": [] + }, + "rust-analyzer.diagnostics.warningsAsHint": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + }, + "description": "List of warnings warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in te problems panel.", + "default": [] } } }, -- cgit v1.2.3