use strum::{EnumIter, EnumMessage, IntoStaticStr};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Topic {
pub label: &'static str,
pub parent: Option<&'static Self>,
pub description: &'static str,
pub scope_note: &'static str,
pub synonyms: &'static [&'static str],
}
impl Topic {
pub(crate) const NAMING: Self = Self {
label: "naming",
parent: None,
description: "How identifiers are named.",
scope_note: "Identifier names. Not string contents, file names, formatting or layout.",
synonyms: &[],
};
pub(crate) const ABBREVIATED_NAMES: Self = Self {
label: "abbreviated-names",
parent: Some(&Self::NAMING),
description: "Too short or cryptic names: abbreviations and single letters.",
scope_note: "Abbreviations and single-letter identifiers. Not type or unit suffixes.",
synonyms: &[],
};
pub(crate) const TYPE_ENCODED_NAMES: Self = Self {
label: "type-encoded-names",
parent: Some(&Self::NAMING),
description: "Names encoding a type, container or unit.",
scope_note: "Type, container or unit encoded in the name (`users_dict`, `timeout_secs`). \
Not names that are just short.",
synonyms: &[],
};
pub(crate) const TESTING: Self = Self {
label: "testing",
parent: None,
description: "Practices specific to test code.",
scope_note: "How test code is structured and written. Not production code, even when \
tested.",
synonyms: &[],
};
pub(crate) const TEST_ASSERTIONS: Self = Self {
label: "test-assertions",
parent: Some(&Self::TESTING),
description: "Count, shape and granularity of test assertions.",
scope_note: "Number and shape of test assertions. Not production `assert` or what the \
test exercises.",
synonyms: &[],
};
pub(crate) const TEST_DOUBLES: Self = Self {
label: "test-doubles",
parent: Some(&Self::TESTING),
description: "Mocks, fakes, stubs, spies and monkeypatching.",
scope_note: "Replacing collaborators in tests and asserting on those replacements. Not \
fixtures that only build data.",
synonyms: &[],
};
pub(crate) const TEST_TIMING: Self = Self {
label: "test-timing",
parent: Some(&Self::TESTING),
description: "Sleeps, clocks and timeouts in tests.",
scope_note: "Sleeping or waiting in tests. Not production retries or duration \
representation (see `durations`).",
synonyms: &[],
};
pub(crate) const STATIC_TYPING: Self = Self {
label: "static-typing",
parent: None,
description: "What the static type checker can see and verify.",
scope_note: "What static type checking can prove. Not runtime validation or dataclass \
mutability (see `record-types`).",
synonyms: &[],
};
pub(crate) const TYPE_CHECKER_BYPASS: Self = Self {
label: "type-checker-bypass",
parent: Some(&Self::STATIC_TYPING),
description: "Code that overrides or routes around the type checker.",
scope_note: "Casts and dynamic access (`cast`, `getattr`) that hide types from the \
checker. Not `omni:` directives.",
synonyms: &[],
};
pub(crate) const POSITIONAL_MEANING: Self = Self {
label: "positional-meaning",
parent: None,
description: "Meaning carried by position instead of a name.",
scope_note: "Meaning carried by argument order or tuple position instead of a name. Not \
named-field access.",
synonyms: &[],
};
pub(crate) const POSITIONAL_INDEXING: Self = Self {
label: "positional-indexing",
parent: Some(&Self::POSITIONAL_MEANING),
description: "Reading sequence elements by literal index instead of unpacking.",
scope_note: "Access by literal index (`t[0]`) where destructuring would name the parts. \
Not loops over indices or slicing.",
synonyms: &[],
};
pub(crate) const VCS: Self = Self {
label: "vcs",
parent: None,
description: "Version-control operations and history.",
scope_note: "Commands and workflows of any version-control system. Not CI or code review.",
synonyms: &["version-control"],
};
pub(crate) const JJ: Self = Self {
label: "jj",
parent: Some(&Self::VCS),
description: "Rules specific to Jujutsu.",
scope_note: "Commands and workflows specific to Jujutsu. Not generic VCS behaviour.",
synonyms: &["jujutsu"],
};
pub(crate) const DURATIONS: Self = Self {
label: "durations",
parent: None,
description: "How spans of time are represented.",
scope_note: "Representing lengths of time and their units. Not sleeping/waiting (see \
`test-timing`) or wall-clock dates.",
synonyms: &[],
};
pub(crate) const RECORD_TYPES: Self = Self {
label: "record-types",
parent: None,
description: "Declaring named records (`dataclass`, `NamedTuple`, `struct`).",
scope_note: "Field-bundle declarations, mutability and slots. Not enums or protocols.",
synonyms: &[],
};
pub(crate) const LITERALS: Self = Self {
label: "literals",
parent: None,
description: "How literal values are written in code.",
scope_note: "Writing string and number literals (multiline strings, format placeholders, \
magic numbers). Not identifiers or logging calls (see `logging`).",
synonyms: &[],
};
pub(crate) const NESTING: Self = Self {
label: "nesting",
parent: None,
description: "Nesting depth and scope structure of code units.",
scope_note: "Nested functions, closures and scope depth. Not naming or \"readability\" \
in general.",
synonyms: &[],
};
pub(crate) const GLOBAL_STATE: Self = Self {
label: "global-state",
parent: None,
description: "Process-wide state read or written implicitly.",
scope_note: "Reading or writing ambient process-wide state (environment variables, \
globals). Not file or network I/O.",
synonyms: &[],
};
pub(crate) const ERROR_HANDLING: Self = Self {
label: "error-handling",
parent: None,
description: "Raising, catching, swallowing and reporting errors.",
scope_note: "Exceptions and `Result`s, including `contextlib.suppress`. Not `omni:` \
directives (see `suppression-directives`).",
synonyms: &[],
};
pub(crate) const LOGGING: Self = Self {
label: "logging",
parent: None,
description: "Use of logging APIs.",
scope_note: "Log calls and their arguments. Not `print` or metrics.",
synonyms: &[],
};
pub(crate) const CONCURRENCY: Self = Self {
label: "concurrency",
parent: None,
description: "Concurrent execution: coroutines, tasks and threads.",
scope_note: "Spawning, awaiting and joining concurrent work and its lifetimes. Not \
sleeping or waiting in tests (see `test-timing`).",
synonyms: &[],
};
pub(crate) const SUPPRESSION_DIRECTIVES: Self = Self {
label: "suppression-directives",
parent: None,
description: "Hygiene of suppression directives.",
scope_note: "`omni:` directives that silence Omni, and the reasons given on third-party \
Python ones (`# noqa`, `# type: ignore`, ...). Not `contextlib.suppress` \
(see `error-handling`).",
synonyms: &[],
};
pub(crate) const DECLARATION_ORDER: Self = Self {
label: "declaration-order",
parent: None,
description: "Order in which declarations appear in a scope.",
scope_note: "Ordering of functions, methods and items within a module or class. Not \
nesting depth (see `nesting`) or naming.",
synonyms: &[],
};
pub(crate) const DOCSTRINGS: Self = Self {
label: "docstrings",
parent: None,
description: "Presence, content and sections of docstrings.",
scope_note: "Whether a docstring is present, what it says and how its Google-style \
sections (`Args:`, `Returns:`, `Attributes:`) are written. Not comments or \
`omni:` directives.",
synonyms: &["documentation"],
};
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, EnumIter, IntoStaticStr, EnumMessage,
)]
#[strum(serialize_all = "kebab-case")]
pub enum Precision {
Exact,
Heuristic,
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, EnumIter, IntoStaticStr, EnumMessage,
)]
#[strum(serialize_all = "kebab-case")]
pub enum Consensus {
Opinionated,
Unopinionated,
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, EnumIter, IntoStaticStr, EnumMessage,
)]
#[strum(serialize_all = "kebab-case")]
pub enum ImpactedQuality {
Reliability,
Maintainability,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Classification {
pub topics: &'static [Topic],
pub precision: Precision,
pub consensus: Consensus,
pub impacted_quality: ImpactedQuality,
}