feat(lint): no-char-pointer reads the AST, retiring the interop denylist
The rule was `\bchar\s*\*` over the text minus a substring denylist — argv, getenv, setenv, dlerror, c_str, .data(, reinterpret_cast, extern ". Every entry was a patch for one interop site, the list could only grow as libraries arrived, and each entry disabled the rule for the whole LINE it appeared on. It now walks declarations and asks the question the denylist was approximating: whose header dictates this spelling? A declaration with C language linkage, or one whose initialiser binds to an entity declared outside the project root, is somebody else's API and keeps its spelling. getenv, c_str and friends are exempt because of where they are declared, not because they are named here, so a new external library needs no new entry. Two bugs found while testing this, both of which had made the rule silently pass over the entire repository: clang_getCursorLanguage cannot be used to detect extern "C". Its default answer is CXLanguage_C for a plain function, variable or parameter even in a C++ translation unit, so isExternC was true almost everywhere and exempted everything. Replaced by tracking CXCursor_LinkageSpec depth during the walk, reading the extent text to tell extern "C" from extern "C++". Attributing any foreign reference in a subtree to the enclosing declaration was too broad: a function that merely touched libc++ somewhere in its body would exempt its own signature. Narrowed to initialiser contexts — a variable, field or parameter — which is where a binding to a foreign API actually occurs. Also: functions now carry their RESULT type rather than the whole function type, since the parameters arrive as their own declarations and would otherwise be reported twice. main's parameters are exempt structurally, its signature being fixed by the language rather than chosen here. Two sites keep an explicit lint-disable, both Crafter::Run taking main's argv verbatim. That is two visible, reasoned suppressions in place of a denylist that silently disabled the rule for every line mentioning one of eight tokens. ExternalCloneDir and ExternalIncludeFlags are now exposed from :External, so a source that includes an external dependency's headers can be parsed without running a build to discover where they are. BuildExternal derives its own working directory through the same function, so the two cannot drift. Crafter.Build-Shader.cpp needed this to parse at all. A file with no compile command — project.cpp, which LoadProject builds with its own flags — is not a translation unit of the build graph, so AST rules skip it the way a rule self-filters by extension. That is distinct from a file that should have parsed and did not, which stays an error. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
29888fc5ba
commit
91e4f59a94
7 changed files with 209 additions and 40 deletions
|
|
@ -536,6 +536,12 @@ export namespace Crafter {
|
|||
std::string userFlags;
|
||||
std::string ltoCompileFlags;
|
||||
std::string ltoLinkFlags;
|
||||
// -I flags from external dependencies' declared includeDirs, for this
|
||||
// configuration and its dependencies. Deliberately NOT folded into
|
||||
// `command`: Build appends the authoritative set from the external build
|
||||
// results instead. Exposed for callers that only PARSE sources and so
|
||||
// cannot wait for a build to tell them where the headers are.
|
||||
std::string externalIncludeFlags;
|
||||
// ThinLTO is on: objects hold bitcode, so archiving needs llvm-ar.
|
||||
bool useLto = false;
|
||||
fs::path stdPcmDir;
|
||||
|
|
@ -545,6 +551,9 @@ export namespace Crafter {
|
|||
|
||||
CRAFTER_API BuildResult Build(Configuration& config, std::unordered_map<fs::path, std::shared_future<BuildResult>>& depResults, std::mutex& depMutex);
|
||||
|
||||
// Takes main's argv verbatim so the CLI entry point is a one-liner;
|
||||
// the shape is inherited from the language, not chosen here.
|
||||
// lint-disable-next-line no-char-pointer
|
||||
CRAFTER_API int Run(int argc, char** argv);
|
||||
|
||||
// Delete the bin/ and build/ trees beside `projectFile`, returning the paths
|
||||
|
|
|
|||
Loading…
Reference in a new issue