feat(lint): naming reads the AST, deleting the scope heuristic
The rule was 125 lines: four std::regex, a hand-rolled {/} scope stack, a
cumulative paren-depth counter so a wrapped parameter list would not look like
a declaration, a 40-entry keyword denylist, and a "function-shaped line" guess
whose own comment conceded it was heuristic. Storage class came from
lineStr.contains("static "). It is now ~55 lines that ask clang what kind of
declaration each thing is and what encloses it.
The three regressions the old version carried special cases for — a call with
an inline lambda argument, a bare statement call, a one-liner method — need no
handling at all, because a call is not a declaration. Their tests pass
unchanged.
On this repository the exact version found 42 violations the heuristic had
never been able to see, all real:
- 37 members of the libclang function-pointer table added two commits ago
were PascalCase. The old varDecl regex could not match a declaration whose
type is decltype(&f), so they were silently skipped. Renamed to camelCase,
which mirrors clang_createIndex -> createIndex more closely anyway.
- Crafter.Build-Shader.cpp had a snake_case local, file_name_list, invisible
to the heuristic for the same reason (it declares a const char* array).
- Four extern "C" declarations of libc functions in tests were reported as
badly-named functions. Those are named by the C library, so C language
linkage is now an exemption — the same principled test no-char-pointer
uses, rather than another denylist entry.
New tests cover what the line-based version structurally could not reach: a
signature wrapped over several lines, `static` on its own line above the
declaration it applies to, and a member versus a local inside a method.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
91e4f59a94
commit
d55657b7ce
4 changed files with 227 additions and 255 deletions
|
|
@ -327,6 +327,42 @@ int main() {
|
|||
Check(HasFinding(r.summary, "'raw'"), "no-char-pointer: a deduced char* local is still ours");
|
||||
}
|
||||
|
||||
// Cases the line-based heuristic structurally could not see. It only looked
|
||||
// at declarations starting at cumulative paren depth 0 and inferred scope
|
||||
// from a running {/} count, so a wrapped signature, a specifier split over
|
||||
// two lines, or a local shadowing a member all escaped it.
|
||||
{
|
||||
RuleRun r = RunRule("#include <string>\n"
|
||||
"namespace Outer {\n"
|
||||
" int wrapped_function(\n"
|
||||
" int first,\n"
|
||||
" int second) { return first + second; }\n"
|
||||
" static\n"
|
||||
" int splitStatic = 1;\n"
|
||||
" struct Holder {\n"
|
||||
" int Member = 0;\n"
|
||||
" void Method() {\n"
|
||||
" int Local = 1;\n"
|
||||
" (void)Local;\n"
|
||||
" }\n"
|
||||
" };\n"
|
||||
"}\n"
|
||||
"extern \"C\" int c_api_entry(const char* name);\n",
|
||||
"naming", LintMode::Report);
|
||||
// A signature wrapped over lines is still a function declaration.
|
||||
Check(HasFinding(r.summary, "'wrapped_function' should be PascalCase"), "naming: wrapped signature is seen");
|
||||
// `static` on its own line still applies to the declaration below it.
|
||||
Check(HasFinding(r.summary, "'splitStatic' should be PascalCase"), "naming: split specifier is seen");
|
||||
// Members are camelCase; the enclosing kind decides, not a brace count.
|
||||
Check(HasFinding(r.summary, "'Member' should be camelCase"), "naming: member is checked as a member");
|
||||
// A local inside a method is a local, not a member and not a global.
|
||||
Check(HasFinding(r.summary, "'Local' should be camelCase"), "naming: local inside a method is a local");
|
||||
// Named by libc, not by us.
|
||||
Check(!HasFinding(r.summary, "c_api_entry"), "naming: extern \"C\" declaration is exempt");
|
||||
Check(!HasFinding(r.summary, "'Method'"), "naming: PascalCase method passes");
|
||||
Check(!HasFinding(r.summary, "'Holder'"), "naming: PascalCase type passes");
|
||||
}
|
||||
|
||||
if (Failures > 0) {
|
||||
std::println(std::cerr, "{} assertions failed", Failures);
|
||||
return 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue