fix(vscode): report problem more accurately (#1681)

Closed https://github.com/oxc-project/oxc/issues/1674
This commit is contained in:
IWANABETHATGUY 2023-12-18 10:59:51 +08:00 committed by GitHub
parent 8f296dfb7a
commit ef08892027
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -19,7 +19,9 @@ use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder; use oxc_semantic::SemanticBuilder;
use oxc_span::{SourceType, VALID_EXTENSIONS}; use oxc_span::{SourceType, VALID_EXTENSIONS};
use ropey::Rope; use ropey::Rope;
use tower_lsp::lsp_types::{self, Position, Range, Url}; use tower_lsp::lsp_types::{
self, DiagnosticRelatedInformation, DiagnosticSeverity, Position, Range, Url,
};
#[derive(Debug)] #[derive(Debug)]
struct ErrorWithPosition { struct ErrorWithPosition {
@ -40,7 +42,6 @@ struct LabeledSpanWithPosition {
impl ErrorWithPosition { impl ErrorWithPosition {
pub fn new(error: Error, text: &str, fixed_content: Option<FixedContent>) -> Self { pub fn new(error: Error, text: &str, fixed_content: Option<FixedContent>) -> Self {
let labels = error.labels().map_or(vec![], Iterator::collect); let labels = error.labels().map_or(vec![], Iterator::collect);
let labels_with_pos: Vec<LabeledSpanWithPosition> = labels let labels_with_pos: Vec<LabeledSpanWithPosition> = labels
.iter() .iter()
.map(|labeled_span| LabeledSpanWithPosition { .map(|labeled_span| LabeledSpanWithPosition {
@ -60,10 +61,8 @@ impl ErrorWithPosition {
fn to_lsp_diagnostic(&self, path: &PathBuf) -> lsp_types::Diagnostic { fn to_lsp_diagnostic(&self, path: &PathBuf) -> lsp_types::Diagnostic {
let severity = match self.miette_err.severity() { let severity = match self.miette_err.severity() {
Some(Severity::Error) => Some(lsp_types::DiagnosticSeverity::ERROR), Some(Severity::Error) => Some(lsp_types::DiagnosticSeverity::ERROR),
Some(Severity::Warning) => Some(lsp_types::DiagnosticSeverity::WARNING), _ => Some(lsp_types::DiagnosticSeverity::WARNING),
_ => Some(lsp_types::DiagnosticSeverity::INFORMATION),
}; };
let related_information = Some( let related_information = Some(
self.labels_with_pos self.labels_with_pos
.iter() .iter()
@ -85,6 +84,21 @@ impl ErrorWithPosition {
}) })
.collect(), .collect(),
); );
let range = related_information.as_ref().map_or(
Range { start: self.start_pos, end: self.end_pos },
|infos: &Vec<DiagnosticRelatedInformation>| {
let mut ret_range = Range {
start: Position { line: u32::MAX, character: u32::MAX },
end: Position { line: u32::MAX, character: u32::MAX },
};
for info in infos {
if cmp_range(&ret_range, &info.location.range) == std::cmp::Ordering::Greater {
ret_range = info.location.range;
}
}
ret_range
},
);
let message = self.miette_err.help().map_or_else( let message = self.miette_err.help().map_or_else(
|| self.miette_err.to_string(), || self.miette_err.to_string(),
@ -92,7 +106,7 @@ impl ErrorWithPosition {
); );
lsp_types::Diagnostic { lsp_types::Diagnostic {
range: Range { start: self.start_pos, end: self.end_pos }, range,
severity, severity,
code: None, code: None,
message, message,
@ -117,7 +131,6 @@ pub struct DiagnosticReport {
pub diagnostic: lsp_types::Diagnostic, pub diagnostic: lsp_types::Diagnostic,
pub fixed_content: Option<FixedContent>, pub fixed_content: Option<FixedContent>,
} }
#[derive(Debug)] #[derive(Debug)]
struct ErrorReport { struct ErrorReport {
pub error: Error, pub error: Error,
@ -161,14 +174,49 @@ impl IsolatedLintHandler {
content: Option<String>, content: Option<String>,
) -> Option<Vec<DiagnosticReport>> { ) -> Option<Vec<DiagnosticReport>> {
if Self::is_wanted_ext(path) { if Self::is_wanted_ext(path) {
Some( Some(Self::lint_path(&self.linter, path, Arc::clone(&self.plugin), content).map_or(
Self::lint_path(&self.linter, path, Arc::clone(&self.plugin), content).map_or( vec![],
vec![], |(p, errors)| {
|(p, errors)| { let mut diagnostics: Vec<DiagnosticReport> =
errors.into_iter().map(|e| e.into_diagnostic_report(&p)).collect() errors.into_iter().map(|e| e.into_diagnostic_report(&p)).collect();
}, // a diagnostics connected from related_info to original diagnostic
), let mut inverted_diagnostics = vec![];
) for d in &diagnostics {
let Some(ref related_info) = d.diagnostic.related_information else {
continue;
};
let related_information = Some(vec![DiagnosticRelatedInformation {
location: lsp_types::Location {
uri: lsp_types::Url::from_file_path(path).unwrap(),
range: d.diagnostic.range,
},
message: "original diagnostic".to_string(),
}]);
for r in related_info {
if r.location.range == d.diagnostic.range {
continue;
}
inverted_diagnostics.push(DiagnosticReport {
diagnostic: lsp_types::Diagnostic {
range: r.location.range,
severity: Some(DiagnosticSeverity::HINT),
code: None,
message: r.message.clone(),
source: Some("oxc".into()),
code_description: None,
related_information: related_information.clone(),
tags: None,
data: None,
},
fixed_content: None,
});
}
}
diagnostics.append(&mut inverted_diagnostics);
diagnostics
},
))
} else { } else {
None None
} }
@ -411,3 +459,10 @@ impl ServerLinter {
.run_single(&uri.to_file_path().unwrap(), content) .run_single(&uri.to_file_path().unwrap(), content)
} }
} }
fn cmp_range(first: &Range, other: &Range) -> std::cmp::Ordering {
match first.start.cmp(&other.start) {
std::cmp::Ordering::Equal => first.end.cmp(&other.end),
o => o,
}
}