|
| 1 | +# clang-tidy config for cforge itself. |
| 2 | +# Project-only — does not propagate to user projects. |
| 3 | +# |
| 4 | +# Apply with: |
| 5 | +# cforge lint # report only |
| 6 | +# cforge lint --fix # rewrite source in place |
| 7 | +# cforge lint --checks='readability-identifier-naming' --fix # naming only |
| 8 | +# |
| 9 | +# Naming convention summary: |
| 10 | +# namespaces, classes, structs, enums, functions, methods, |
| 11 | +# variables, parameters, member variables → snake_case |
| 12 | +# non-static member variables → m_ prefix |
| 13 | +# static member variables → s_ prefix |
| 14 | +# constexpr variables (file/global scope) → k prefix |
| 15 | +# enum constants → UPPER_CASE |
| 16 | +# macros → UPPER_CASE |
| 17 | +# template parameters → CamelCase (convention even |
| 18 | +# in snake_case |
| 19 | +# codebases — TIdx, |
| 20 | +# T, U, etc.) |
| 21 | +# |
| 22 | +# Exceptions: |
| 23 | +# - C ABI types in core/types.h (cforge_int_t, cforge_size_t, etc.) are |
| 24 | +# "lower_case" by accident — they match snake_case rules naturally so |
| 25 | +# they're not renamed. |
| 26 | +# - extern "C" `cforge_cmd_*` / `cforge_print_*` / `cforge_main*` entry |
| 27 | +# points are likewise snake_case and require no exception. |
| 28 | +# - Macros from third-party headers (fmt, toml++) are filtered via |
| 29 | +# HeaderFilterRegex below. |
| 30 | + |
| 31 | +--- |
| 32 | +# Restrict checks to *our* source. Without this, every <vector>/<string>/fmt |
| 33 | +# header pulled in gets the same name-style audit and the output is unusable. |
| 34 | +HeaderFilterRegex: '^(src|include)/' |
| 35 | + |
| 36 | +# Treat all enabled checks as warnings (not errors) by default. Build pipelines |
| 37 | +# that want to fail on lint can pass --warnings-as-errors=* themselves. |
| 38 | +WarningsAsErrors: '' |
| 39 | + |
| 40 | +# ── Checks ──────────────────────────────────────────────────────────────── |
| 41 | +# Phase 1 baseline: naming + the cheapest "almost always wrong" patterns. |
| 42 | +# Modernize/perf checks are deliberately OFF here; Phase 3 will enable them |
| 43 | +# one at a time so the diff stays reviewable. |
| 44 | +Checks: > |
| 45 | + -*, |
| 46 | + readability-identifier-naming, |
| 47 | + bugprone-*, |
| 48 | + -bugprone-easily-swappable-parameters, |
| 49 | + -bugprone-narrowing-conversions |
| 50 | +
|
| 51 | +# ── readability-identifier-naming options ───────────────────────────────── |
| 52 | +CheckOptions: |
| 53 | + # ── Types ── |
| 54 | + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } |
| 55 | + - { key: readability-identifier-naming.ClassCase, value: lower_case } |
| 56 | + - { key: readability-identifier-naming.StructCase, value: lower_case } |
| 57 | + - { key: readability-identifier-naming.UnionCase, value: lower_case } |
| 58 | + - { key: readability-identifier-naming.EnumCase, value: lower_case } |
| 59 | + - { key: readability-identifier-naming.TypedefCase, value: lower_case } |
| 60 | + - { key: readability-identifier-naming.TypeAliasCase, value: lower_case } |
| 61 | + - { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase } |
| 62 | + - { key: readability-identifier-naming.TypeTemplateParameterCase, value: CamelCase } |
| 63 | + - { key: readability-identifier-naming.ValueTemplateParameterCase, value: CamelCase } |
| 64 | + - { key: readability-identifier-naming.TemplateTemplateParameterCase, value: CamelCase } |
| 65 | + |
| 66 | + # ── Functions / methods ── |
| 67 | + - { key: readability-identifier-naming.FunctionCase, value: lower_case } |
| 68 | + - { key: readability-identifier-naming.MethodCase, value: lower_case } |
| 69 | + - { key: readability-identifier-naming.VirtualMethodCase, value: lower_case } |
| 70 | + - { key: readability-identifier-naming.ClassMethodCase, value: lower_case } |
| 71 | + - { key: readability-identifier-naming.GlobalFunctionCase, value: lower_case } |
| 72 | + - { key: readability-identifier-naming.PrivateMethodCase, value: lower_case } |
| 73 | + - { key: readability-identifier-naming.ProtectedMethodCase, value: lower_case } |
| 74 | + - { key: readability-identifier-naming.PublicMethodCase, value: lower_case } |
| 75 | + |
| 76 | + # ── Variables / parameters ── |
| 77 | + - { key: readability-identifier-naming.VariableCase, value: lower_case } |
| 78 | + - { key: readability-identifier-naming.ParameterCase, value: lower_case } |
| 79 | + - { key: readability-identifier-naming.LocalVariableCase, value: lower_case } |
| 80 | + - { key: readability-identifier-naming.LocalConstantCase, value: lower_case } |
| 81 | + - { key: readability-identifier-naming.LocalConstantPointerCase, value: lower_case } |
| 82 | + - { key: readability-identifier-naming.LocalPointerCase, value: lower_case } |
| 83 | + |
| 84 | + # ── Class members ── |
| 85 | + - { key: readability-identifier-naming.ClassMemberCase, value: lower_case } |
| 86 | + - { key: readability-identifier-naming.ClassConstantCase, value: UPPER_CASE } |
| 87 | + - { key: readability-identifier-naming.MemberCase, value: lower_case } |
| 88 | + - { key: readability-identifier-naming.PrivateMemberCase, value: lower_case } |
| 89 | + - { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ } |
| 90 | + - { key: readability-identifier-naming.ProtectedMemberCase, value: lower_case } |
| 91 | + - { key: readability-identifier-naming.ProtectedMemberPrefix, value: m_ } |
| 92 | + - { key: readability-identifier-naming.PublicMemberCase, value: lower_case } |
| 93 | + # NB: PublicMemberPrefix intentionally NOT set — POD-style structs (token, |
| 94 | + # diagnostic, locked_dependency, etc.) have public bare members in |
| 95 | + # cforge, and prefixing them with m_ would just be noise. |
| 96 | + |
| 97 | + # ── Static class members ── |
| 98 | + - { key: readability-identifier-naming.StaticVariableCase, value: lower_case } |
| 99 | + - { key: readability-identifier-naming.StaticVariablePrefix, value: s_ } |
| 100 | + - { key: readability-identifier-naming.ClassMethodCase, value: lower_case } |
| 101 | + |
| 102 | + # ── Globals / constants ── |
| 103 | + # clang-tidy lumps file-scope `static T name;` and namespace-scope globals |
| 104 | + # under the same "GlobalVariable" rule, but cforge distinguishes them in |
| 105 | + # practice: `g_` for true globals visible across TUs (signal handlers like |
| 106 | + # g_should_exit, OS handles like g_host_proc_handle), `s_` for file-scope |
| 107 | + # statics (s_progress_initialized, regex caches). We can't enforce that |
| 108 | + # distinction without two separate clang-tidy passes, so the rule below |
| 109 | + # accepts either prefix (and demands lower_case for the rest). |
| 110 | + - { key: readability-identifier-naming.GlobalVariableCase, value: lower_case } |
| 111 | + - { key: readability-identifier-naming.GlobalVariableIgnoredRegexp, |
| 112 | + value: '^(WINAPI|APIENTRY|CALLBACK|[gs]_[a-z][a-z0-9_]*)$' } |
| 113 | + - { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE } |
| 114 | + - { key: readability-identifier-naming.GlobalConstantPointerCase, value: UPPER_CASE } |
| 115 | + - { key: readability-identifier-naming.GlobalPointerCase, value: lower_case } |
| 116 | + # Same dual-prefix tolerance for global pointers. |
| 117 | + - { key: readability-identifier-naming.GlobalPointerIgnoredRegexp, |
| 118 | + value: '^([gs]_[a-z][a-z0-9_]*)$' } |
| 119 | + |
| 120 | + # ── Constexpr ── |
| 121 | + # File/class-scope constexpr: UPPER_CASE (matches cforge's existing |
| 122 | + # STATUS_WIDTH, FNV_PRIME, FNV_OFFSET_BASIS, etc. — they read as |
| 123 | + # compile-time constants alongside macros). |
| 124 | + # Function-local constexpr stays lower_case (it's just a `const` with |
| 125 | + # extra steps). |
| 126 | + - { key: readability-identifier-naming.ConstexprVariableCase, value: UPPER_CASE } |
| 127 | + - { key: readability-identifier-naming.ConstexprMethodCase, value: lower_case } |
| 128 | + - { key: readability-identifier-naming.ConstexprFunctionCase, value: lower_case } |
| 129 | + - { key: readability-identifier-naming.LocalConstantCase, value: lower_case } |
| 130 | + |
| 131 | + # ── Enum constants ── |
| 132 | + - { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE } |
| 133 | + # Allow scoped-enum members to skip the UPPER_CASE rule if they're |
| 134 | + # already typed (e.g. `style::CARGO` vs `style::cargo`). cforge already |
| 135 | + # uses UPPER_CASE for scoped enums so this is fine; if you ever want |
| 136 | + # lower_case scoped enums, change ScopedEnumConstantCase below. |
| 137 | + - { key: readability-identifier-naming.ScopedEnumConstantCase, value: UPPER_CASE } |
| 138 | + |
| 139 | + # ── Macros ── |
| 140 | + - { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE } |
| 141 | + |
| 142 | + # ── Length / numeric thresholds ── |
| 143 | + # Catch one-letter parameter names except a handful of allowed math ones. |
| 144 | + - { key: readability-identifier-naming.ParameterIgnoredRegexp, |
| 145 | + value: '^(i|j|k|n|x|y|z|p|t|r|c|s|e|a|b|f|m)$' } |
| 146 | + |
| 147 | + # ── Win32 false positives ── |
| 148 | + # WINAPI/APIENTRY/CALLBACK are already excluded via GlobalVariableIgnoredRegexp |
| 149 | + # above. These keys catch Hungarian-notation parameter names from the |
| 150 | + # Windows SDK (dwMode, lpReserved, hInstance, etc.) — we don't rename |
| 151 | + # them because they're dictated by Microsoft headers. |
| 152 | + - { key: readability-identifier-naming.LocalVariableIgnoredRegexp, |
| 153 | + value: '^(dw|lp|cb|sz|wc|h|n)[A-Z].*$' } |
| 154 | + |
| 155 | + # ── Allow our C ABI prefix as-is ── |
| 156 | + # cforge_X identifiers naturally match snake_case; no exception needed. |
0 commit comments