Skip to content

Generalize diagnostics into a parser-agnostic type (Span as shared substrate) #17

Description

@saiashirwad

Right now Span, ParseError, ParseErrorBundle, and ErrorFormatter all live inside the parser (errors.ts, error-formatter.ts) and are shaped by parser concerns — expected-token sets, parser state, single-point errors. That's fine while parsing is the only thing emitting diagnostics.

But the moment a typechecker, linter, or codegen wants to report "type string flows in here, expected int there," it either reinvents its own span/diagnostic types or reaches into the parser's internals. The dependency graph ends up pointing the wrong way: tools depend on the parser just to get a Span.

I'd like to split out a parser-agnostic diagnostic core:

type Severity = "error" | "warning" | "info"

type Diagnostic = {
  severity: Severity
  code?: string
  message: string
  primary: Span
  related?: { message: string; span: Span }[]
  fixes?: { description: string; edits: { span: Span; replacement: string }[] }[]
}

ParseError then becomes a thin parser-specific adapter that produces Diagnostics, rather than being the diagnostic type itself. The parser depends on this core; future tools depend on the same core without touching the parser.

This is the umbrella that #11 (Span shape), #13 (related spans + fixes), and #14 (formatter pipeline) feed into — but none of them addresses the ownership/decoupling question, which is what actually unblocks non-parser consumers.

Open questions:

  • Where's the line between parser-specific data (expected tokens, merge semantics from or()) and the general Diagnostic? Does ParseError keep its parser-specific fields and just expose a toDiagnostic()?
  • Does ErrorFormatter move with the core, or stay parser-side and consume a general renderer from Refactor ErrorFormatter into a unified render pipeline #14?
  • Does this become its own package, or just a clean module boundary inside the repo for now?

Non-goals:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions