Scry.Diagnostics (scry v0.1.22)

Copy Markdown View Source

Resolved findings → pentiment frames → Mix.Task.Compiler.Diagnostic.

Driver-side presentation: nothing here is memoized, and the query graph never renders. Each resolved finding (file + line + prose + labelled related anchors, from Scry.Analysis.analysis_diagnostics) becomes one pentiment report:

  • the primary anchor is an inline label under the code of its line, annotated with the finding's at_label. BEAM anchors are line-granular, so the span is the line's code extent (first non-blank column to the end of the trimmed line), read from the source file; a line that cannot be read degrades to column 1;
  • same-file related anchors are secondary inline labels in the same excerpt; cross-file related anchors carry source: and render as ├─[file:line:col] continuation frames against their own file;
  • detail renders as a note, help entries as help trailers.

The Mix bridge follows the roux/haruspex pattern: the Diagnostic carries a short message and an integer line position for editors, and the full rendered frame rides in detailsprint/1 puts the frame on stderr. Terminal output re-renders with colors: true (pentiment itself degrades when stderr is not a TTY); details and the persisted sidecar stay color-free.

File-level ignores apply here, at emission — an ignored file's facts still feed every cross-module analysis. Reports are suppressed, truth is not.

Summary

Types

A diagnostic paired with its ANSI rendering for terminal output.

Functions

Builds diagnostics from analysis_diagnostics values, most severe first.

Builds an infrastructure diagnostic (no source frame): souffle missing, an analysis degraded, and similar conditions that are about the run rather than the code.

Prints rendered diagnostics to stderr, frames separated by blank lines.

Relativizes an absolute path against cwd, tolerating the macOS /var/private/var symlink spelling difference.

The filtered, severity-overridden, sorted finding entries — the shared substrate for both rendering (build/3) and machine formats (Scry.Report.json/2).

Types

rendered()

@type rendered() :: %{diagnostic: Mix.Task.Compiler.Diagnostic.t(), ansi: String.t()}

A diagnostic paired with its ANSI rendering for terminal output.

Functions

build(findings_by_file, config, cwd)

@spec build(%{optional(String.t()) => [map()]}, Scry.Config.t(), String.t()) :: [
  rendered()
]

Builds diagnostics from analysis_diagnostics values, most severe first.

Paths are relativized against cwd for display; the Diagnostic keeps the absolute path.

infrastructure(severity, message)

@spec infrastructure(:error | :warning | :info, String.t()) :: rendered()

Builds an infrastructure diagnostic (no source frame): souffle missing, an analysis degraded, and similar conditions that are about the run rather than the code.

print(rendered)

@spec print([rendered()]) :: :ok

Prints rendered diagnostics to stderr, frames separated by blank lines.

relative(path, cwd)

@spec relative(String.t(), String.t()) :: String.t()

Relativizes an absolute path against cwd, tolerating the macOS /var/private/var symlink spelling difference.

resolve(findings_by_file, config, cwd)

@spec resolve(%{optional(String.t()) => [map()]}, Scry.Config.t(), String.t()) :: [
  map()
]

The filtered, severity-overridden, sorted finding entries — the shared substrate for both rendering (build/3) and machine formats (Scry.Report.json/2).

findings_by_file merges every demanded analysis's resolved map. File-level ignores drop entries here; severity overrides apply here.