mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 20:43:21 +00:00
Warnings as hint or info
This commit is contained in:
parent
5d7974e5fb
commit
656e95211e
7 changed files with 402 additions and 13 deletions
|
@ -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<usize>,
|
||||
pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>,
|
||||
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,
|
||||
|
|
|
@ -10,6 +10,12 @@ use crate::lsp_ext;
|
|||
|
||||
pub type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct DiagnosticsConfig {
|
||||
pub warnings_as_info: Vec<String>,
|
||||
pub warnings_as_hint: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct DiagnosticCollection {
|
||||
pub native: HashMap<FileId, Vec<Diagnostic>>,
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
|
@ -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,
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
|
@ -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<DiagnosticSeverity> {
|
||||
let res = match val {
|
||||
/// Determines the LSP severity from a diagnostic
|
||||
fn map_diagnostic_to_severity(
|
||||
config: &DiagnosticsConfig,
|
||||
val: &ra_flycheck::Diagnostic,
|
||||
) -> Option<DiagnosticSeverity> {
|
||||
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<MappedRustDiagnostic> {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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": []
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue