1use super::spec::{DEFAULT_TOOL_TIMEOUT_SECS, LanguageSupport, ToolSpec};
11
12pub static RUFF: ToolSpec = ToolSpec {
14 name: "ruff",
15 command: &["ruff", "check", "--output-format", "json"],
16 local_paths: &["venv/bin/ruff", ".venv/bin/ruff"],
17 config_files: &["pyproject.toml", "ruff.toml", ".ruff.toml"],
18 output_format: "json",
19 diagnostics_stream: "stdout",
20 timeout_secs: DEFAULT_TOOL_TIMEOUT_SECS,
21 timeout_context: None,
22 establishes_compilation: false,
23 serial_in_repository: false,
24 accepts_files: true,
25};
26
27pub static ESLINT: ToolSpec = ToolSpec {
29 name: "eslint",
30 command: &["eslint", "--format", "json"],
31 local_paths: &["node_modules/.bin/eslint"],
32 config_files: &[
33 "eslint.config.js",
34 "eslint.config.mjs",
35 "eslint.config.cjs",
36 ".eslintrc",
37 ".eslintrc.js",
38 ".eslintrc.cjs",
39 ".eslintrc.json",
40 ".eslintrc.yml",
41 ".eslintrc.yaml",
42 ],
43 output_format: "json",
44 diagnostics_stream: "stdout",
45 timeout_secs: DEFAULT_TOOL_TIMEOUT_SECS,
46 timeout_context: None,
47 establishes_compilation: false,
48 serial_in_repository: false,
49 accepts_files: true,
50};
51
52pub static TSC: ToolSpec = ToolSpec {
54 name: "tsc",
55 command: &["tsc", "--noEmit", "--pretty", "false"],
56 local_paths: &["node_modules/.bin/tsc"],
57 config_files: &["tsconfig.json"],
58 output_format: "tsc",
59 diagnostics_stream: "stdout",
60 timeout_secs: DEFAULT_TOOL_TIMEOUT_SECS,
61 timeout_context: None,
62 establishes_compilation: true,
63 serial_in_repository: false,
64 accepts_files: false,
67};
68
69pub static GOFMT: ToolSpec = ToolSpec {
74 name: "gofmt",
75 command: &["gofmt", "-l"],
76 local_paths: &[],
77 config_files: &["go.mod"],
78 output_format: "lines",
79 diagnostics_stream: "stdout",
80 timeout_secs: DEFAULT_TOOL_TIMEOUT_SECS,
81 timeout_context: None,
82 establishes_compilation: false,
83 serial_in_repository: false,
84 accepts_files: true,
85};
86
87pub static GO_VET: ToolSpec = ToolSpec {
92 name: "go vet",
93 command: &["go", "vet"],
94 local_paths: &[],
95 config_files: &["go.mod"],
96 output_format: "position",
97 diagnostics_stream: "stderr",
98 timeout_secs: DEFAULT_TOOL_TIMEOUT_SECS,
99 timeout_context: None,
100 establishes_compilation: true,
101 serial_in_repository: false,
102 accepts_files: true,
103};
104
105pub static CLIPPY: ToolSpec = ToolSpec {
107 name: "clippy",
108 command: &["cargo", "clippy", "--message-format", "json", "--quiet"],
109 local_paths: &[],
110 config_files: &["Cargo.toml"],
111 output_format: "cargo",
112 diagnostics_stream: "stdout",
113 timeout_secs: 1_800,
117 timeout_context: Some(", including its Cargo build-lock wait"),
118 establishes_compilation: true,
119 serial_in_repository: true,
120 accepts_files: false,
123};
124
125pub static PYTHON: LanguageSupport = LanguageSupport {
127 name: "python",
128 display_name: "Python",
129 extensions: &[".py"],
130 tools: &[&RUFF],
131 conventions: &[
132 "Follows PEP 8 naming and structure",
133 "Type hints on public APIs, and correct use of Optional/None",
134 "Context managers for resources rather than manual cleanup",
135 "Mutable default arguments, and late-binding closures in loops",
136 ],
137 vendored_dirs: &["__pycache__", "venv", ".venv", "env", ".tox", ".eggs"],
138};
139
140pub static JAVASCRIPT: LanguageSupport = LanguageSupport {
142 name: "javascript",
143 display_name: "JavaScript",
144 extensions: &[".js", ".jsx", ".mjs", ".cjs"],
145 tools: &[&ESLINT],
146 conventions: &[
147 "Unhandled promise rejections and missing await",
148 "Sequential awaits in a loop where the work is independent",
149 "var versus let/const, and accidental global scope",
150 "Equality coercion (== versus ===)",
151 ],
152 vendored_dirs: &["node_modules", ".next", ".nuxt"],
153};
154
155pub static TYPESCRIPT: LanguageSupport = LanguageSupport {
157 name: "typescript",
158 display_name: "TypeScript",
159 extensions: &[".ts", ".tsx", ".mts", ".cts"],
160 tools: &[&ESLINT, &TSC],
161 conventions: &[
162 "`any` where a real type is available, and unsafe casts",
163 "Unhandled promise rejections and missing await",
164 "Non-null assertions (!) that hide a genuine null case",
165 "Sequential awaits in a loop where the work is independent",
166 ],
167 vendored_dirs: &["node_modules", ".next", ".nuxt"],
168};
169
170pub static GO: LanguageSupport = LanguageSupport {
172 name: "go",
173 display_name: "Go",
174 extensions: &[".go"],
175 tools: &[&GOFMT, &GO_VET],
176 conventions: &[
177 "Errors ignored rather than checked and wrapped",
178 "Goroutine leaks, and writes to a channel nobody reads",
179 "defer inside a loop, and defer that never runs",
180 "Data races on shared state without synchronisation",
181 ],
182 vendored_dirs: &["vendor"],
183};
184
185pub static RUST_LANG: LanguageSupport = LanguageSupport {
187 name: "rust",
188 display_name: "Rust",
189 extensions: &[".rs"],
190 tools: &[&CLIPPY],
191 conventions: &[
192 "unwrap/expect on values that can legitimately be None or Err",
193 "unsafe blocks, and whether their invariants are documented",
194 "Unnecessary clones and allocations in hot paths",
195 "Send/Sync correctness for types crossing threads",
196 ],
197 vendored_dirs: &["target"],
198};
199
200pub static ALL_LANGUAGES: &[&LanguageSupport] =
202 &[&PYTHON, &JAVASCRIPT, &TYPESCRIPT, &GO, &RUST_LANG];