1use std::path::PathBuf;
2
3use clap::Parser;
4use clap::Subcommand;
5use clap::ValueEnum;
6use serde::Serialize;
7
8#[derive(Debug, Clone, Parser)]
9#[command(name = "sc-lint")]
10#[command(about = "Stable top-level CLI for the sc-lint tool family")]
11#[command(disable_version_flag = true)]
12pub struct Cli {
13 #[arg(long, global = true)]
14 pub json: bool,
15 #[arg(long, global = true, value_name = "path")]
16 pub root: Option<PathBuf>,
17 #[arg(long, global = true, value_name = "path")]
18 pub config: Option<PathBuf>,
19 #[arg(long, global = true, value_name = "path")]
20 pub log_root: Option<PathBuf>,
21 #[arg(long, global = true)]
22 pub log_console: bool,
23 #[command(subcommand)]
24 pub(crate) command: Command,
25}
26
27#[derive(Debug, Clone, Subcommand)]
28pub enum Command {
29 Lint {
30 #[arg(value_enum)]
31 target: LintTarget,
32 },
33 View {
34 #[arg(value_enum)]
35 target: ViewTarget,
36 },
37 Check {
38 #[arg(value_enum)]
39 target: CheckTarget,
40 },
41 Clippy {
42 #[arg(value_enum)]
43 target: ClippyTarget,
44 },
45 Version,
46 Ci,
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, ValueEnum)]
50#[serde(rename_all = "snake_case")]
51pub enum LintProfile {
52 Fast,
53 Full,
54 Ci,
55}
56
57impl LintProfile {
58 pub const fn command_suffix(self) -> &'static str {
59 match self {
60 Self::Fast => "fast",
61 Self::Full => "full",
62 Self::Ci => "ci",
63 }
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
68#[serde(rename_all = "snake_case")]
69pub enum OutputMode {
70 Human,
71 Json,
72}
73
74impl OutputMode {
75 pub const fn from_json_flag(json: bool) -> Self {
76 if json { Self::Json } else { Self::Human }
77 }
78
79 pub const fn is_json(self) -> bool {
80 matches!(self, Self::Json)
81 }
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
85pub enum LintTarget {
86 #[value(name = "sc-boundary")]
87 ScBoundary,
88 #[value(name = "sc-portability")]
89 ScPortability,
90 #[value(name = "sc-runtime")]
91 ScRuntime,
92 #[value(name = "line-counts")]
93 LineCounts,
94 #[value(name = "identity-literals")]
95 IdentityLiterals,
96 #[value(name = "fast")]
97 Fast,
98 #[value(name = "full")]
99 Full,
100 #[value(name = "ci")]
101 Ci,
102}
103
104impl LintTarget {
105 pub const fn command_suffix(self) -> &'static str {
106 match self {
107 Self::ScBoundary => "sc-boundary",
108 Self::ScPortability => "sc-portability",
109 Self::ScRuntime => "sc-runtime",
110 Self::LineCounts => "line-counts",
111 Self::IdentityLiterals => "identity-literals",
112 Self::Fast => "fast",
113 Self::Full => "full",
114 Self::Ci => "ci",
115 }
116 }
117
118 pub const fn profile(self) -> Option<LintProfile> {
119 match self {
120 Self::Fast => Some(LintProfile::Fast),
121 Self::Full => Some(LintProfile::Full),
122 Self::Ci => Some(LintProfile::Ci),
123 Self::ScBoundary
124 | Self::ScPortability
125 | Self::ScRuntime
126 | Self::LineCounts
127 | Self::IdentityLiterals => None,
128 }
129 }
130}
131
132#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
133pub enum ViewTarget {
134 #[value(name = "graph")]
135 Graph,
136 #[value(name = "findings")]
137 Findings,
138}
139
140impl ViewTarget {}
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
143pub enum CheckTarget {
144 #[value(name = "native")]
145 Native,
146 #[value(name = "xwin")]
147 Xwin,
148}
149
150impl CheckTarget {
151 pub const fn command_suffix(self) -> &'static str {
152 match self {
153 Self::Native => "native",
154 Self::Xwin => "xwin",
155 }
156 }
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
160pub enum ClippyTarget {
161 #[value(name = "native")]
162 Native,
163 #[value(name = "xwin")]
164 Xwin,
165}
166
167impl ClippyTarget {
168 pub const fn command_suffix(self) -> &'static str {
169 match self {
170 Self::Native => "native",
171 Self::Xwin => "xwin",
172 }
173 }
174}