Skip to content

Commit

Permalink
feat: Improve recovery from false positives caused by preprocessor
Browse files Browse the repository at this point in the history
  • Loading branch information
igor-prusov committed Nov 1, 2024
1 parent 6ed4125 commit 6d638b0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 14 deletions.
39 changes: 26 additions & 13 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,10 @@ pub struct DiagnosticExt {
pub diag: Diagnostic,
url: Url, // TODO: remove this
label: String,
parent: Option<String>,
}

fn process_node(
id: &IncludesDepot,
node: &Node,
diagnostics: &mut Vec<DiagnosticExt>,
url: &Url,
text: &str,
) {
fn process_node(node: &Node, diagnostics: &mut Vec<DiagnosticExt>, url: &Url, text: &str) {
let range = convert_range(&node.range());
let label = node.utf8_text(text.as_bytes()).unwrap();
if node.is_missing() {
Expand All @@ -24,32 +19,38 @@ fn process_node(
diag: Diagnostic::new_simple(range, msg),
label: label.to_string(),
url: url.clone(),
parent: None,
});
} else if node.is_error() && id.find_define(url, label).is_none() {
} else if node.is_error() {
// Ignore syntax errors if they are in tokens that will be replaced after preprocessing
// TODO: We should implement preprocessor pass for proper error reporting, but for now
// just trade error detection inside macros for less false-positive noise.
let parent = node
.parent()
.and_then(|x| x.utf8_text(text.as_bytes()).ok())
.map(std::string::ToString::to_string);
diagnostics.push(DiagnosticExt {
diag: Diagnostic::new_simple(range, "Syntax error".to_string()),
label: label.to_string(),
url: url.clone(),
parent,
});
}
}

pub fn gather(url: &Url, tree: &Tree, id: &IncludesDepot, text: &str) -> Vec<DiagnosticExt> {
pub fn gather(url: &Url, tree: &Tree, text: &str) -> Vec<DiagnosticExt> {
let mut diagnostics = Vec::new();
let mut it = tree.walk();
process_node(id, &it.node(), &mut diagnostics, url, text);
process_node(&it.node(), &mut diagnostics, url, text);
let mut recurse = true;

#[allow(clippy::if_same_then_else)]
loop {
if recurse && it.goto_first_child() {
process_node(id, &it.node(), &mut diagnostics, url, text);
process_node(&it.node(), &mut diagnostics, url, text);
recurse = true;
} else if it.goto_next_sibling() {
process_node(id, &it.node(), &mut diagnostics, url, text);
process_node(&it.node(), &mut diagnostics, url, text);
recurse = true;
} else if it.goto_parent() {
recurse = false;
Expand All @@ -66,6 +67,18 @@ impl DiagnosticExt {
return true;
}

id.find_define(&self.url, &self.label).is_none()
if id.find_define(&self.url, &self.label).is_some() {
return false;
}

if let Some(parent) = &self.parent {
if let Some((parent, _)) = parent.split_once('(') {
if id.find_define(&self.url, parent).is_some() {
return false;
}
}
}

true
}
}
2 changes: 1 addition & 1 deletion src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ impl Workspace {
// Currently there are too many false positives, this also means that there will be too
// much traffic towards client, making it slow when big workspace is fully scanned.
if self.config.experimental {
let mut t = diagnostics::gather(uri, &tree, &self.id, &text);
let mut t = diagnostics::gather(uri, &tree, &text);
let e = diagnostics.entry(uri.clone()).or_default();
e.append(&mut t);
}
Expand Down

0 comments on commit 6d638b0

Please sign in to comment.