Parse children
from cargo check
output to provide hints
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
a85e400b35
commit
adeea9da66
1 changed files with 73 additions and 9 deletions
|
@ -31,10 +31,11 @@ mod rust {
|
|||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CompilerMessage {
|
||||
code: ErrorCode,
|
||||
code: Option<ErrorCode>,
|
||||
spans: Vec<Span>,
|
||||
message: String,
|
||||
level: ErrorLevel,
|
||||
children: Vec<CompilerMessage>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
@ -43,6 +44,8 @@ mod rust {
|
|||
Warning,
|
||||
#[serde(rename = "error")]
|
||||
Error,
|
||||
#[serde(rename = "help")]
|
||||
Help,
|
||||
#[serde(rename = "note")]
|
||||
Note,
|
||||
}
|
||||
|
@ -52,24 +55,30 @@ mod rust {
|
|||
code: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct Span {
|
||||
is_primary: bool,
|
||||
file_name: PathBuf,
|
||||
byte_start: usize,
|
||||
byte_end: usize,
|
||||
expansion: Option<Box<Expansion>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct Expansion {
|
||||
span: Span,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl language::DiagnosticProvider for DiagnosticProvider {
|
||||
async fn diagnose(
|
||||
&self,
|
||||
path: Arc<Path>,
|
||||
root_path: Arc<Path>,
|
||||
) -> Result<HashMap<Arc<Path>, Vec<DiagnosticEntry<usize>>>> {
|
||||
let output = Command::new("cargo")
|
||||
.arg("check")
|
||||
.args(["--message-format", "json"])
|
||||
.current_dir(&path)
|
||||
.current_dir(&root_path)
|
||||
.output()
|
||||
.await?;
|
||||
|
||||
|
@ -80,13 +89,21 @@ mod rust {
|
|||
Deserializer::from_slice(&output.stdout).into_iter::<&serde_json::value::RawValue>()
|
||||
{
|
||||
if let Ok(check) = serde_json::from_str::<Check>(value?.get()) {
|
||||
let severity = match check.message.level {
|
||||
let check_severity = match check.message.level {
|
||||
ErrorLevel::Warning => DiagnosticSeverity::WARNING,
|
||||
ErrorLevel::Error => DiagnosticSeverity::ERROR,
|
||||
ErrorLevel::Help => DiagnosticSeverity::HINT,
|
||||
ErrorLevel::Note => DiagnosticSeverity::INFORMATION,
|
||||
};
|
||||
for span in check.message.spans {
|
||||
let span_path: Arc<Path> = span.file_name.into();
|
||||
|
||||
let mut primary_span = None;
|
||||
for mut span in check.message.spans {
|
||||
if let Some(mut expansion) = span.expansion {
|
||||
expansion.span.is_primary = span.is_primary;
|
||||
span = expansion.span;
|
||||
}
|
||||
|
||||
let span_path: Arc<Path> = span.file_name.as_path().into();
|
||||
new_reported_paths.insert(span_path.clone());
|
||||
diagnostics_by_path
|
||||
.entry(span_path)
|
||||
|
@ -94,8 +111,8 @@ mod rust {
|
|||
.push(DiagnosticEntry {
|
||||
range: span.byte_start..span.byte_end,
|
||||
diagnostic: Diagnostic {
|
||||
code: Some(check.message.code.code.clone()),
|
||||
severity,
|
||||
code: check.message.code.as_ref().map(|c| c.code.clone()),
|
||||
severity: check_severity,
|
||||
message: check.message.message.clone(),
|
||||
group_id,
|
||||
is_valid: true,
|
||||
|
@ -103,7 +120,54 @@ mod rust {
|
|||
is_disk_based: true,
|
||||
},
|
||||
});
|
||||
|
||||
if span.is_primary {
|
||||
primary_span = Some(span);
|
||||
}
|
||||
}
|
||||
|
||||
for mut child in check.message.children {
|
||||
if child.spans.is_empty() {
|
||||
if let Some(primary_span) = primary_span.clone() {
|
||||
child.spans.push(primary_span);
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
continue;
|
||||
}
|
||||
|
||||
let child_severity = match child.level {
|
||||
ErrorLevel::Warning => DiagnosticSeverity::WARNING,
|
||||
ErrorLevel::Error => DiagnosticSeverity::ERROR,
|
||||
ErrorLevel::Help => DiagnosticSeverity::HINT,
|
||||
ErrorLevel::Note => DiagnosticSeverity::INFORMATION,
|
||||
};
|
||||
|
||||
for mut span in child.spans {
|
||||
if let Some(expansion) = span.expansion {
|
||||
span = expansion.span;
|
||||
}
|
||||
|
||||
let span_path: Arc<Path> = span.file_name.as_path().into();
|
||||
new_reported_paths.insert(span_path.clone());
|
||||
diagnostics_by_path
|
||||
.entry(span_path)
|
||||
.or_insert(Vec::new())
|
||||
.push(DiagnosticEntry {
|
||||
range: span.byte_start..span.byte_end,
|
||||
diagnostic: Diagnostic {
|
||||
code: child.code.as_ref().map(|c| c.code.clone()),
|
||||
severity: child_severity,
|
||||
message: child.message.clone(),
|
||||
group_id,
|
||||
is_valid: true,
|
||||
is_primary: false,
|
||||
is_disk_based: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
group_id += 1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue