diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs index 831ad9b292..9a1a2d5077 100644 --- a/cli/lsp/analysis.rs +++ b/cli/lsp/analysis.rs @@ -60,6 +60,7 @@ lazy_static::lazy_static! { /// Category of self-generated diagnostic messages (those not coming from) /// TypeScript. +#[derive(Debug, PartialEq, Eq)] pub enum Category { /// A lint diagnostic, where the first element is the message. Lint { @@ -70,6 +71,7 @@ pub enum Category { } /// A structure to hold a reference to a diagnostic message. +#[derive(Debug, PartialEq, Eq)] pub struct Reference { category: Category, range: Range, @@ -78,13 +80,24 @@ pub struct Reference { impl Reference { pub fn to_diagnostic(&self) -> lsp::Diagnostic { match &self.category { - Category::Lint { message, code, .. } => lsp::Diagnostic { + Category::Lint { + message, + code, + hint, + } => lsp::Diagnostic { range: self.range, severity: Some(lsp::DiagnosticSeverity::Warning), code: Some(lsp::NumberOrString::String(code.to_string())), code_description: None, source: Some("deno-lint".to_string()), - message: message.to_string(), + message: { + let mut msg = message.to_string(); + if let Some(hint) = hint { + msg.push('\n'); + msg.push_str(hint); + } + msg + }, related_information: None, tags: None, // we should tag unused code data: None, @@ -702,6 +715,64 @@ mod tests { use super::*; use deno_core::resolve_url; + #[test] + fn test_reference_to_diagnostic() { + let range = Range { + start: Position { + line: 1, + character: 1, + }, + end: Position { + line: 2, + character: 2, + }, + }; + + let test_cases = [ + ( + Reference { + category: Category::Lint { + message: "message1".to_string(), + code: "code1".to_string(), + hint: None, + }, + range, + }, + lsp::Diagnostic { + range, + severity: Some(lsp::DiagnosticSeverity::Warning), + code: Some(lsp::NumberOrString::String("code1".to_string())), + source: Some("deno-lint".to_string()), + message: "message1".to_string(), + ..Default::default() + }, + ), + ( + Reference { + category: Category::Lint { + message: "message2".to_string(), + code: "code2".to_string(), + hint: Some("hint2".to_string()), + }, + range, + }, + lsp::Diagnostic { + range, + severity: Some(lsp::DiagnosticSeverity::Warning), + code: Some(lsp::NumberOrString::String("code2".to_string())), + source: Some("deno-lint".to_string()), + message: "message2\nhint2".to_string(), + ..Default::default() + }, + ), + ]; + + for (input, expected) in test_cases.iter() { + let actual = input.to_diagnostic(); + assert_eq!(&actual, expected); + } + } + #[test] fn test_as_lsp_range() { let fixture = deno_lint::diagnostic::Range { @@ -732,6 +803,38 @@ mod tests { ); } + #[test] + fn test_get_lint_references() { + let specifier = resolve_url("file:///a.ts").expect("bad specifier"); + let source = "const foo = 42;"; + let actual = + get_lint_references(&specifier, &MediaType::TypeScript, source).unwrap(); + + assert_eq!( + actual, + vec![Reference { + category: Category::Lint { + message: "`foo` is never used".to_string(), + code: "no-unused-vars".to_string(), + hint: Some( + "If this is intentional, prefix it with an underscore like `_foo`" + .to_string() + ), + }, + range: Range { + start: Position { + line: 0, + character: 6, + }, + end: Position { + line: 0, + character: 9, + } + } + }] + ); + } + #[test] fn test_analyze_dependencies() { let specifier = resolve_url("file:///a.ts").expect("bad specifier");