monty_types/type_checking.rs
1use std::str::FromStr;
2
3use serde::{Deserialize, Serialize};
4use strum::VariantNames;
5
6/// How type-check diagnostics are rendered into text.
7///
8/// Mirrors ty's `DiagnosticFormat`. Rendering happens wherever the type checker
9/// runs (inside the worker for pool sessions), because ty's structured
10/// diagnostics borrow the salsa database and cannot cross a process boundary —
11/// so the format has to be chosen before the check, not after it.
12///
13/// Serialized into session dumps by discriminant, so new variants must be
14/// appended — inserting one shifts every later variant and silently rewrites
15/// older dumps' format (see `DUMP_VERSION` in `monty`).
16#[derive(
17 Debug,
18 Clone,
19 Copy,
20 Default,
21 PartialEq,
22 Eq,
23 Serialize,
24 Deserialize,
25 strum::Display,
26 strum::EnumString,
27 strum::VariantNames,
28)]
29#[strum(serialize_all = "lowercase", ascii_case_insensitive)]
30pub enum TypeCheckingFormat {
31 /// Human-readable diagnostics with a source snippet and carets.
32 #[default]
33 Full,
34 /// One `path:line:col: severity[rule] message` line per diagnostic.
35 Concise,
36 /// Azure Pipelines logging commands.
37 Azure,
38 /// A JSON array of diagnostic objects.
39 Json,
40 /// One JSON diagnostic object per line.
41 #[strum(to_string = "jsonlines", serialize = "json-lines")]
42 JsonLines,
43 /// Reviewdog diagnostic JSON.
44 Rdjson,
45 /// Pylint-compatible output.
46 Pylint,
47 /// GitLab Code Quality report JSON.
48 Gitlab,
49 /// GitHub Actions workflow commands.
50 Github,
51}
52
53impl TypeCheckingFormat {
54 /// Parses a format name, reporting the valid names on failure.
55 ///
56 /// Bindings take the format as a string, so the error has to be good
57 /// enough to show a user who guessed wrong.
58 pub fn from_name(name: &str) -> Result<Self, String> {
59 Self::from_str(name)
60 .map_err(|_| format!("unknown type check format '{name}', expected one of: {}", Self::names()))
61 }
62
63 /// Comma-separated list of the accepted format names.
64 #[must_use]
65 pub fn names() -> String {
66 Self::VARIANTS.join(", ")
67 }
68}
69
70/// How a type check renders whatever diagnostics it finds.
71#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
72pub struct TypeCheckingConfig {
73 /// Output format.
74 pub format: TypeCheckingFormat,
75 /// Whether to include ANSI colour escapes. Only `Full` and `Concise`
76 /// render any colour; the machine-readable formats ignore it.
77 pub color: bool,
78}
79
80/// Per-session type-check state: successfully committed snippets accumulate as
81/// stubs so later snippets can reference names defined by earlier ones.
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct TypeCheckState {
84 /// User-provided stubs plus every snippet that has completed successfully.
85 pub committed_stubs: String,
86 /// The in-flight snippet; committed on success, discarded on error.
87 pub pending_snippet: Option<String>,
88 /// How diagnostics are rendered by whoever runs the type checker.
89 pub config: TypeCheckingConfig,
90}