From 1513a9f4b0b9284981cda72a5f68c94c0cb5d54e Mon Sep 17 00:00:00 2001 From: Sysix <3897725+Sysix@users.noreply.github.com> Date: Sun, 5 Apr 2026 13:32:23 +0000 Subject: [PATCH] feat(oxlint/lsp): show note field for lsp diagnostic (#20983) closes https://github.com/oxc-project/oxc-intellij-plugin/issues/423 Screenshot: grafik --- apps/oxlint/src/lsp/error_with_position.rs | 29 +++++++++++-------- .../fixtures_lsp_cross_module@dep-a.ts.snap | 2 +- ...cross_module_extended_config@dep-a.ts.snap | 2 +- ...nfig@dep-a.ts_folder__folder-dep-a.ts.snap | 2 +- ...lsp_ts_path_alias@deep__src__dep-a.ts.snap | 2 +- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/oxlint/src/lsp/error_with_position.rs b/apps/oxlint/src/lsp/error_with_position.rs index 6ebbc5160dc5c..650f07b96a1d2 100644 --- a/apps/oxlint/src/lsp/error_with_position.rs +++ b/apps/oxlint/src/lsp/error_with_position.rs @@ -93,23 +93,28 @@ pub fn message_to_lsp_diagnostic( .and_then(|url| url.parse().ok()) .map(|href| CodeDescription { href }); - let diagnostic_message = match &message.error.help { - Some(help) => { - let main_msg = &message.error.message; - let mut msg = String::with_capacity(main_msg.len() + help.len() + 7); - msg.push_str(main_msg); - msg.push_str("\nhelp: "); - msg.push_str(help); - msg - } - None => message.error.message.to_string(), - }; + let mut diagnostic_message = String::with_capacity( + message.error.message.len() + + message.error.help.as_ref().map_or(0, |h| h.len() + 7) // "help: " prefix + + message.error.note.as_ref().map_or(0, |n| n.len() + 7), // "note: " prefix + ); + + diagnostic_message.push_str(&message.error.message); + if let Some(help) = &message.error.help { + diagnostic_message.push_str("\nhelp: "); + diagnostic_message.push_str(help); + } + + if let Some(note) = &message.error.note { + diagnostic_message.push_str("\nnote: "); + diagnostic_message.push_str(note); + } // 1) Use `fixed_content.message` if it exists // 2) Try to parse the report diagnostic message // 3) Fallback to "Fix this problem" let alternative_fix_title: Cow<'static, str> = - if let Some(code) = diagnostic_message.split(':').next() { + if let Some(code) = message.error.message.split(':').next() { format!("Fix this {code} problem").into() } else { std::borrow::Cow::Borrowed("Fix this problem") diff --git a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module@dep-a.ts.snap b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module@dep-a.ts.snap index 8edad88f859d3..e87b85fc07b68 100644 --- a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module@dep-a.ts.snap +++ b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module@dep-a.ts.snap @@ -9,7 +9,7 @@ File URI: file:///fixtures/lsp/cross_module/dep-a.ts code: "eslint-plugin-import(no-cycle)" code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html" -message: "Dependency cycle detected\nhelp: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import." +message: "Dependency cycle detected\nhelp: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import.\nnote: These paths form a cycle:\n╭──▶ ./dep-b.ts (fixtures/lsp/cross_module/dep-b.ts)\n│ ⬇ imports\n│ ./dep-a.ts (fixtures/lsp/cross_module/dep-a.ts)\n╰─────────╯ imports the current file" range: Range { start: Position { line: 1, character: 18 }, end: Position { line: 1, character: 30 } } related_information[0].message: "" related_information[0].location.uri: "file:///fixtures/lsp/cross_module/dep-a.ts" diff --git a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module_extended_config@dep-a.ts.snap b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module_extended_config@dep-a.ts.snap index dd83909e929ad..bdde16d1c06da 100644 --- a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module_extended_config@dep-a.ts.snap +++ b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module_extended_config@dep-a.ts.snap @@ -9,7 +9,7 @@ File URI: file:///fixtures/lsp/cross_module_extended_config/dep-a.ts code: "eslint-plugin-import(no-cycle)" code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html" -message: "Dependency cycle detected\nhelp: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import." +message: "Dependency cycle detected\nhelp: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import.\nnote: These paths form a cycle:\n╭──▶ ./dep-b.ts (fixtures/lsp/cross_module_extended_config/dep-b.ts)\n│ ⬇ imports\n│ ./dep-a.ts (fixtures/lsp/cross_module_extended_config/dep-a.ts)\n╰─────────╯ imports the current file" range: Range { start: Position { line: 1, character: 18 }, end: Position { line: 1, character: 30 } } related_information[0].message: "" related_information[0].location.uri: "file:///fixtures/lsp/cross_module_extended_config/dep-a.ts" diff --git a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module_nested_config@dep-a.ts_folder__folder-dep-a.ts.snap b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module_nested_config@dep-a.ts_folder__folder-dep-a.ts.snap index edee751b77d7b..fd2623a9d8f28 100644 --- a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module_nested_config@dep-a.ts_folder__folder-dep-a.ts.snap +++ b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_cross_module_nested_config@dep-a.ts_folder__folder-dep-a.ts.snap @@ -19,7 +19,7 @@ File URI: file:///fixtures/lsp/cross_module_nested_config/folder/folde code: "eslint-plugin-import(no-cycle)" code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html" -message: "Dependency cycle detected\nhelp: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import." +message: "Dependency cycle detected\nhelp: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import.\nnote: These paths form a cycle:\n╭──▶ ./folder-dep-b.ts (fixtures/lsp/cross_module_nested_config/folder/folder-dep-b.ts)\n│ ⬇ imports\n│ ./folder-dep-a.ts (fixtures/lsp/cross_module_nested_config/folder/folder-dep-a.ts)\n╰─────────╯ imports the current file" range: Range { start: Position { line: 1, character: 18 }, end: Position { line: 1, character: 37 } } related_information[0].message: "" related_information[0].location.uri: "file:///fixtures/lsp/cross_module_nested_config/folder/folder-dep-a.ts" diff --git a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_ts_path_alias@deep__src__dep-a.ts.snap b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_ts_path_alias@deep__src__dep-a.ts.snap index 790f8d33c5669..2a9758979fa9e 100644 --- a/apps/oxlint/src/lsp/snapshots/fixtures_lsp_ts_path_alias@deep__src__dep-a.ts.snap +++ b/apps/oxlint/src/lsp/snapshots/fixtures_lsp_ts_path_alias@deep__src__dep-a.ts.snap @@ -9,7 +9,7 @@ File URI: file:///fixtures/lsp/ts_path_alias/deep/src/dep-a.ts code: "eslint-plugin-import(no-cycle)" code_description.href: "https://oxc.rs/docs/guide/usage/linter/rules/import/no-cycle.html" -message: "Dependency cycle detected\nhelp: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import." +message: "Dependency cycle detected\nhelp: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import.\nnote: These paths form a cycle:\n╭──▶ @/dep-b (fixtures/lsp/ts_path_alias/deep/src/dep-b.ts)\n│ ⬇ imports\n│ ./dep-a.ts (fixtures/lsp/ts_path_alias/deep/src/dep-a.ts)\n╰─────────╯ imports the current file" range: Range { start: Position { line: 1, character: 18 }, end: Position { line: 1, character: 27 } } related_information[0].message: "" related_information[0].location.uri: "file:///fixtures/lsp/ts_path_alias/deep/src/dep-a.ts"