* The underlying system for declaring and reporting errors . 

     Every error reported by illuaminate has an associated { ! Tag.t } , which defines the error level 
     ( error , warning , etc ... ) and gives it a friendly name . Tags can then be used to enable / disable 
     particular errors or groups of errors . 

     Errors are then reported into an error sink ( { ! t } ) , which counts errors , sorts them into files , 
     and is used to report them ( see { ! display_of_files } ) .

    Every error reported by illuaminate has an associated {!Tag.t}, which defines the error level
    (error, warning, etc...) and gives it a friendly name. Tags can then be used to enable/disable
    particular errors or groups of errors.

    Errors are then reported into an error sink ({!t}), which counts errors, sorts them into files,
    and is used to report them (see {!display_of_files}).*)

(** Attributes about an error's tag (and thus errors using that tag). *)
type attribute =
  | Default  (** This tag is enabled by default, when used in a linter. *)
  | Unused
* This tag warns about some unused node , such as an unused variable or unreachable code . 

           This maps to LSP 's " unnecessary " diagnostic tag .

          This maps to LSP's "unnecessary" diagnostic tag. *)
  | Deprecated
* This tag warns about working with a deprecated node . 

           This maps to LSP 's " deprecated " diagnostic tag .

          This maps to LSP's "deprecated" diagnostic tag. *)

(** An error reporting level *)
type level =
  | Critical  (** An error which cannot be recovered from *)
  | Error  (** A problem, which may cause problems during processing or runtime *)
  | Warning  (** A potential problem or bug. *)
  | Note  (** A minor issue. Effectively just a less major warning. *)

module Tag : sig
  (** A marker token for errors, used for filtering and classification *)
  type t = private
    { name : string;
      level : level;
      attributes : attribute list
    }

  (** Display a tag in a formatter. *)
  val pp : Format.formatter -> t -> unit

  (** Create a new error tag, and register it internally *)
  val make : attr:attribute list -> level:level -> string -> t

  (** Find a tag with a given name *)
  val find : string -> t option

* Compare two tags .
  val compare : t -> t -> int

  (** Determine if this tag has an attribute. *)
  val has : attribute -> t -> bool

  (** A predicate which determines if a tag should be reported or not. *)
  type filter = t -> bool
end

module Error : sig
  type annotation =
    | Message of unit Fmt.t
    | Annotation of Span.t * unit Fmt.t option

  (** An error reported within the system. *)
  type t = private
    { tag : Tag.t;
      span : Span.t;
      message : unit Fmt.t;
      annotations : annotation list
    }

* Compare two errors by their position . This is suitable for sorting , but obviously does not 
       determine equality .
      determine equality. *)
  val span_compare : t -> t -> int
end

(** An error reporting writer, into which errors are placed *)
type t

(** Make a new error reporter *)
val make : unit -> t

(** Report a new error at a specific position *)
val report : t -> Tag.t -> Span.t -> string -> unit

(** Report a new error at a specific position with additional details. *)
val report_detailed : t -> Tag.t -> Span.t -> unit Fmt.t -> Error.annotation list -> unit

(** Determine if the error reporter has any problems in it. *)
val has_problems : t -> bool

(** Return a sorted list of errors and their locations. *)
val errors : t -> Error.t list

(** Display any errors which occurred. This assumes files exist on disk - use {!display_of_string}
    if this is not the case. *)
val display_of_files : ?out:Format.formatter -> ?with_summary:bool -> t -> unit

(** Display any errors which occurred, with a function which maps file names to strings *)
val display_of_string :
  ?out:Format.formatter -> ?with_summary:bool -> (Span.filename -> string option) -> t -> unit

* Attributes about an error's tag (and thus errors using that tag). 
* This tag is enabled by default, when used in a linter. 
* An error reporting level 
* An error which cannot be recovered from 
* A problem, which may cause problems during processing or runtime 
* A potential problem or bug. 
* A minor issue. Effectively just a less major warning. 
* A marker token for errors, used for filtering and classification 
* Display a tag in a formatter. 
* Create a new error tag, and register it internally 
* Find a tag with a given name 
* Determine if this tag has an attribute. 
* A predicate which determines if a tag should be reported or not. 
* An error reported within the system. 
* An error reporting writer, into which errors are placed 
* Make a new error reporter 
* Report a new error at a specific position 
* Report a new error at a specific position with additional details. 
* Determine if the error reporter has any problems in it. 
* Return a sorted list of errors and their locations. 
* Display any errors which occurred. This assumes files exist on disk - use {!display_of_string}
    if this is not the case. 
* Display any errors which occurred, with a function which maps file names to strings 
* The underlying system for declaring and reporting errors . 

     Every error reported by illuaminate has an associated { ! Tag.t } , which defines the error level 
     ( error , warning , etc ... ) and gives it a friendly name . Tags can then be used to enable / disable 
     particular errors or groups of errors . 

     Errors are then reported into an error sink ( { ! t } ) , which counts errors , sorts them into files , 
     and is used to report them ( see { ! display_of_files } ) .

    Every error reported by illuaminate has an associated {!Tag.t}, which defines the error level
    (error, warning, etc...) and gives it a friendly name. Tags can then be used to enable/disable
    particular errors or groups of errors.

    Errors are then reported into an error sink ({!t}), which counts errors, sorts them into files,
    and is used to report them (see {!display_of_files}).*)

type attribute =
  | Unused
* This tag warns about some unused node , such as an unused variable or unreachable code . 

           This maps to LSP 's " unnecessary " diagnostic tag .

          This maps to LSP's "unnecessary" diagnostic tag. *)
  | Deprecated
* This tag warns about working with a deprecated node . 

           This maps to LSP 's " deprecated " diagnostic tag .

          This maps to LSP's "deprecated" diagnostic tag. *)

type level =

module Tag : sig
  type t = private
    { name : string;
      level : level;
      attributes : attribute list
    }

  val pp : Format.formatter -> t -> unit

  val make : attr:attribute list -> level:level -> string -> t

  val find : string -> t option

* Compare two tags .
  val compare : t -> t -> int

  val has : attribute -> t -> bool

  type filter = t -> bool
end

module Error : sig
  type annotation =
    | Message of unit Fmt.t
    | Annotation of Span.t * unit Fmt.t option

  type t = private
    { tag : Tag.t;
      span : Span.t;
      message : unit Fmt.t;
      annotations : annotation list
    }

* Compare two errors by their position . This is suitable for sorting , but obviously does not 
       determine equality .
      determine equality. *)
  val span_compare : t -> t -> int
end

type t

val make : unit -> t

val report : t -> Tag.t -> Span.t -> string -> unit

val report_detailed : t -> Tag.t -> Span.t -> unit Fmt.t -> Error.annotation list -> unit

val has_problems : t -> bool

val errors : t -> Error.t list

val display_of_files : ?out:Format.formatter -> ?with_summary:bool -> t -> unit

val display_of_string :
  ?out:Format.formatter -> ?with_summary:bool -> (Span.filename -> string option) -> t -> unit
