Skip to content

Commit b8790c2

Browse files
committed
fix(language_server): output correct position for parser & semantic errors (#14010)
see oxc-project/coc-oxc#50 The "real" error should still be on the editor side.
1 parent 4d3c6e1 commit b8790c2

File tree

3 files changed

+48
-20
lines changed

3 files changed

+48
-20
lines changed

crates/oxc_language_server/src/snapshots/fixtures_linter_invalid_syntax@debugger.ts.snap

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ file: fixtures/linter/invalid_syntax/debugger.ts
88
code: ""
99
code_description.href: "None"
1010
message: "Unexpected token"
11-
range: Range { start: Position { line: 2147483647, character: 2147483647 }, end: Position { line: 2147483647, character: 2147483647 } }
12-
related_information: None
11+
range: Range { start: Position { line: 0, character: 9 }, end: Position { line: 0, character: 10 } }
12+
related_information[0].message: ""
13+
related_information[0].location.uri: "file://<variable>/fixtures/linter/invalid_syntax/debugger.ts"
14+
related_information[0].location.range: Range { start: Position { line: 0, character: 9 }, end: Position { line: 0, character: 10 } }
1315
severity: Some(Error)
1416
source: Some("oxc")
1517
tags: None

crates/oxc_linter/src/lsp.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,37 @@ pub struct MessageWithPosition<'a> {
6565
pub fixes: PossibleFixesWithPosition<'a>,
6666
}
6767

68-
impl From<OxcDiagnostic> for MessageWithPosition<'_> {
69-
fn from(from: OxcDiagnostic) -> Self {
70-
Self {
71-
message: from.message.clone(),
72-
labels: None,
73-
help: from.help.clone(),
74-
severity: from.severity,
75-
code: from.code.clone(),
76-
url: from.url.clone(),
77-
fixes: PossibleFixesWithPosition::None,
78-
}
68+
// clippy: the source field is checked and assumed to be less than 4GB, and
69+
// we assume that the fix offset will not exceed 2GB in either direction
70+
#[expect(clippy::cast_possible_truncation)]
71+
pub fn oxc_diagnostic_to_message_with_position<'a>(
72+
diagnostic: &OxcDiagnostic,
73+
source_text: &str,
74+
rope: &Rope,
75+
) -> MessageWithPosition<'a> {
76+
let labels = diagnostic.labels.as_ref().map(|labels| {
77+
labels
78+
.iter()
79+
.map(|labeled_span| {
80+
let offset = labeled_span.offset() as u32;
81+
let start_position = offset_to_position(rope, offset, source_text);
82+
let end_position =
83+
offset_to_position(rope, offset + labeled_span.len() as u32, source_text);
84+
let message = labeled_span.label().map(|label| Cow::Owned(label.to_string()));
85+
86+
SpanPositionMessage::new(start_position, end_position).with_message(message)
87+
})
88+
.collect::<Vec<_>>()
89+
});
90+
91+
MessageWithPosition {
92+
message: diagnostic.message.clone(),
93+
severity: diagnostic.severity,
94+
help: diagnostic.help.clone(),
95+
url: diagnostic.url.clone(),
96+
code: diagnostic.code.clone(),
97+
labels,
98+
fixes: PossibleFixesWithPosition::None,
7999
}
80100
}
81101

crates/oxc_linter/src/service/runtime.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,9 @@ impl Runtime {
682682

683683
use oxc_data_structures::rope::Rope;
684684

685-
use crate::lsp::message_to_message_with_position;
685+
use crate::lsp::{
686+
message_to_message_with_position, oxc_diagnostic_to_message_with_position,
687+
};
686688

687689
// Wrap allocator in `MessageCloner` so can clone `Message`s into it
688690
let message_cloner = MessageCloner::new(allocator);
@@ -715,10 +717,15 @@ impl Runtime {
715717
}
716718
Err(diagnostics) => {
717719
if !diagnostics.is_empty() {
718-
messages
719-
.lock()
720-
.unwrap()
721-
.extend(diagnostics.into_iter().map(Into::into));
720+
messages.lock().unwrap().extend(
721+
diagnostics.into_iter().map(|diagnostic| {
722+
oxc_diagnostic_to_message_with_position(
723+
&diagnostic,
724+
source_text,
725+
rope,
726+
)
727+
}),
728+
);
722729
}
723730
None
724731
}
@@ -745,8 +752,7 @@ impl Runtime {
745752
});
746753
});
747754

748-
// ToDo: oxc_diagnostic::Error is not compatible with MessageWithPosition
749-
// send use OxcDiagnostic or even better the MessageWithPosition struct
755+
// The receiving messages should be only file system reads or source type errors
750756
// while let Ok(diagnostics) = receiver.recv() {
751757
// if let Some(diagnostics) = diagnostics {
752758
// messages.lock().unwrap().extend(

0 commit comments

Comments
 (0)