diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 40996bfd73..a547c5a205 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -3,7 +3,7 @@ use std::{ sync::Arc, }; -use ra_editor::{self, find_node_at_offset, FileSymbol, LineIndex, LocalEdit}; +use ra_editor::{self, find_node_at_offset, FileSymbol, LineIndex, LocalEdit, Severity}; use ra_syntax::{ ast::{self, ArgListOwner, Expr, NameOwner, FnDef}, algo::find_covering_node, @@ -365,6 +365,7 @@ impl AnalysisImpl { .map(|d| Diagnostic { range: d.range, message: d.msg, + severity: d.severity, fix: None, }) .collect::>(); @@ -386,6 +387,7 @@ impl AnalysisImpl { Diagnostic { range: name_node.range(), message: "unresolved module".to_string(), + severity: Severity::Error, fix: Some(fix), } } @@ -408,6 +410,7 @@ impl AnalysisImpl { Diagnostic { range: name_node.range(), message: "can't declare module at this location".to_string(), + severity: Severity::Error, fix: Some(fix), } } diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 8308981405..a029f66b42 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -29,11 +29,10 @@ use crate::{ symbol_index::SymbolIndex, }; -pub use crate::{ - completion::{CompletionItem, CompletionItemKind, InsertText}, -}; +pub use crate::completion::{CompletionItem, CompletionItemKind, InsertText}; pub use ra_editor::{ FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode, + Severity }; pub use hir::FnSignatureInfo; @@ -198,6 +197,7 @@ pub struct Diagnostic { pub message: String, pub range: TextRange, pub fix: Option, + pub severity: Severity, } #[derive(Debug)] diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs index 7cbdfb9530..5ce2aa2b47 100644 --- a/crates/ra_analysis/src/mock_analysis.rs +++ b/crates/ra_analysis/src/mock_analysis.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use relative_path::{RelativePathBuf}; +use relative_path::RelativePathBuf; use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; use ra_db::mock::FileMap; diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 938ca797a2..210fa2a135 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs @@ -82,7 +82,8 @@ fn test_unresolved_module_diagnostic() { label: "create module", source_file_edits: [], file_system_edits: [CreateFile { source_root: SourceRootId(0), path: "foo.rs" }], - cursor_position: None }) }]"#, + cursor_position: None }), + severity: Error }]"#, &diagnostics, ); } diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index 7b63b9a88d..7a689b0f25 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs @@ -31,10 +31,17 @@ pub struct HighlightedRange { pub tag: &'static str, } +#[derive(Debug, Copy, Clone)] +pub enum Severity { + Error, + WeakWarning, +} + #[derive(Debug)] pub struct Diagnostic { pub range: TextRange, pub msg: String, + pub severity: Severity, } #[derive(Debug)] @@ -97,13 +104,37 @@ pub fn diagnostics(file: &SourceFileNode) -> Vec { } } - file.errors() + let mut errors: Vec = file + .errors() .into_iter() .map(|err| Diagnostic { range: location_to_range(err.location()), msg: format!("Syntax Error: {}", err), + severity: Severity::Error, }) - .collect() + .collect(); + + let warnings = check_unnecessary_braces_in_use_statement(file); + + errors.extend(warnings); + errors +} + +fn check_unnecessary_braces_in_use_statement(file: &SourceFileNode) -> Vec { + let mut diagnostics = Vec::new(); + for node in file.syntax().descendants() { + if let Some(use_tree_list) = ast::UseTreeList::cast(node) { + if use_tree_list.use_trees().count() <= 1 { + diagnostics.push(Diagnostic { + range: use_tree_list.syntax().range(), + msg: format!("Unnecessary braces in use statement"), + severity: Severity::WeakWarning, + }) + } + } + } + + diagnostics } pub fn syntax_tree(file: &SourceFileNode) -> String { @@ -204,4 +235,25 @@ fn test_foo() {} do_check("struct Foo { a: i32, }<|>", "struct Foo <|>{ a: i32, }"); } + + #[test] + fn test_check_unnecessary_braces_in_use_statement() { + let file = SourceFileNode::parse( + r#" +use a; +use {b}; +use a::{c}; +use a::{c, d::e}; +use a::{c, d::{e}}; +fn main() {} +"#, + ); + let diagnostics = check_unnecessary_braces_in_use_statement(&file); + assert_eq_dbg( + r#"[Diagnostic { range: [12; 15), msg: "Unnecessary braces in use statement", severity: WeakWarning }, + Diagnostic { range: [24; 27), msg: "Unnecessary braces in use statement", severity: WeakWarning }, + Diagnostic { range: [61; 64), msg: "Unnecessary braces in use statement", severity: WeakWarning }]"#, + &diagnostics, + ) + } } diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index a5a2b5eec3..60f13267c2 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -13,7 +13,7 @@ use gen_lsp_server::{ }; use languageserver_types::NumberOrString; use ra_analysis::{Canceled, FileId, LibraryData}; -use ra_vfs::{VfsTask}; +use ra_vfs::VfsTask; use rayon; use threadpool::ThreadPool; use rustc_hash::FxHashSet; @@ -23,7 +23,7 @@ use failure_derive::Fail; use crate::{ main_loop::subscriptions::Subscriptions, - project_model::{workspace_loader}, + project_model::workspace_loader, req, server_world::{ServerWorld, ServerWorldState}, Result, diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 252d1ba3ea..658d169cda 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -8,7 +8,7 @@ use languageserver_types::{ PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover, HoverContents, }; -use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition}; +use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition, Severity}; use ra_syntax::{TextUnit, text_utils::intersect}; use ra_text_edit::text_utils::contains_offset_nonstrict; use rustc_hash::FxHashMap; @@ -650,7 +650,7 @@ pub fn publish_diagnostics( .into_iter() .map(|d| Diagnostic { range: d.range.conv_with(&line_index), - severity: Some(DiagnosticSeverity::Error), + severity: Some(to_diagnostic_severity(d.severity)), code: None, source: Some("rust-analyzer".to_string()), message: d.message, @@ -684,3 +684,14 @@ fn highlight(world: &ServerWorld, file_id: FileId) -> Result> { .collect(); Ok(res) } + +fn to_diagnostic_severity(severity: Severity) -> DiagnosticSeverity { + use ra_analysis::Severity::*; + + match severity { + Error => DiagnosticSeverity::Error, + Warning => DiagnosticSeverity::Warning, + Information => DiagnosticSeverity::Information, + Hint => DiagnosticSeverity::Hint, + } +}