pub fn diagnostics<C, F>(
doc: &Document<C>,
options: DiagnosticsOptions,
hook: F,
) -> Vec<Diagnostic>Expand description
Builds diagnostics from a settled (or cancelled, or round-capped) parse.
The tree is walked from the root; every failing node is offered to hook
(unless its ancestor already failed and options.cascades is false).
The hook turns a FailedNode into a Diagnostic — or None to stay
silent, e.g. for regions whose context type makes the failure expected.
Diagnostics returned with the default (zero) range get their range filled in from the node’s span, converted with the document’s position encoding; hooks that compute their own ranges keep them.
§Examples
use increparse::{Engine, Outcome, Pass, Schedule, SerialExecutor, Span, Status};
use increparse_lsp::{diagnostics, DiagnosticsOptions, Document, PositionEncoding};
use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Uri};
#[derive(Clone, Debug, PartialEq, Eq)]
enum Ctx { File, Bad }
struct Split;
impl Pass for Split {
type Ctx = Ctx;
fn parse(&self, source: &str, span: Span, ctx: &Ctx) -> Outcome<Ctx> {
match ctx {
Ctx::File if span.len() >= 2 => Outcome::Expand(vec![(
Span::new(span.start + 1, span.end, span.rev),
Ctx::Bad,
)]),
Ctx::File => Outcome::Done,
Ctx::Bad if source[span.to_range()].contains('!') => Outcome::Failed,
Ctx::Bad => Outcome::Done,
}
}
}
let mut schedule = Schedule::new();
schedule.push(Split);
schedule.push(Split);
let engine = Engine::new(schedule);
let uri: Uri = "file:///x.txt".parse()?;
let mut doc = Document::open(uri, 1, "".into(), "ok!".into(), PositionEncoding::Utf16, Ctx::File);
doc.apply_changes(&engine, 1, &[], &SerialExecutor, &increparse::CancelToken::new());
let diags = diagnostics(&doc, DiagnosticsOptions::default(), |node| {
let _ = node.status;
Some(Diagnostic {
severity: Some(DiagnosticSeverity::ERROR),
message: "this region failed to parse".into(),
..Diagnostic::default()
})
});
assert_eq!(diags.len(), 1);
assert_eq!(diags[0].range.start, Position { line: 0, character: 1 });