fix(lint): fail the files whose configuration has no compile command
When GetCompileCommand threw or the std module failed to build, the lint driver cleared the configuration's command, and an empty command means "not a translation unit" (project.cpp, a header): every rule that needs an AST skipped the files quietly and the run passed them as clean. MingwSysroot made that reachable for every mingw configuration whose view cannot be made. The reason is now kept per configuration and reported as an AST failure for each of its files, which fails the run and prints it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0e69e71b11
commit
40dcf2271d
1 changed files with 16 additions and 3 deletions
|
|
@ -1149,6 +1149,10 @@ format` applies it to disk, and `crafter-build lint` reports where it would.
|
|||
// command per configuration — GetCompileCommand walks the dependency tree.
|
||||
const bool anyRuleNeedsAst = std::ranges::any_of(rules, [](const LintRule* r) { return r->needsAst; });
|
||||
std::unordered_map<const Configuration*, std::string> commands;
|
||||
// Why a configuration of the build graph has no command: its files
|
||||
// cannot be parsed, which fails the run. Cleared to nothing, the command
|
||||
// read as "not a translation unit" and every semantic rule passed them.
|
||||
std::unordered_map<const Configuration*, std::string> commandErrors;
|
||||
if (anyRuleNeedsAst && !opts.noAst) {
|
||||
for (Configuration* c : localConfigs) {
|
||||
auto ensure = [&](const Configuration& cfg) {
|
||||
|
|
@ -1166,10 +1170,14 @@ format` applies it to disk, and `crafter-build lint` reports where it would.
|
|||
Progress::Task task(std::format("Building std PCM ({}-{})", cfg.target, cfg.march));
|
||||
fs::create_directories(assembled.stdPcmDir);
|
||||
std::string error = BuildStdPcm(cfg, assembled.stdPcmDir/"std.pcm");
|
||||
if (!error.empty()) command.clear();
|
||||
if (!error.empty()) {
|
||||
command.clear();
|
||||
commandErrors.emplace(&cfg, std::format("building the std module for {}: {}", cfg.target, error));
|
||||
}
|
||||
} catch (const std::exception&) {
|
||||
command.clear(); // surfaced per file as an AST reason
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
command.clear();
|
||||
commandErrors.emplace(&cfg, std::format("assembling the compile command for {}: {}", cfg.target, e.what()));
|
||||
}
|
||||
commands.emplace(&cfg, std::move(command));
|
||||
};
|
||||
|
|
@ -1200,6 +1208,11 @@ format` applies it to disk, and `crafter-build lint` reports where it would.
|
|||
// decides what is safe to touch. Skip it and make the run fail.
|
||||
if (rule->needsAst) {
|
||||
if (opts.noAst) continue;
|
||||
if (auto failed = commandErrors.find(owner); failed != commandErrors.end()) {
|
||||
astFailures.emplace(file, failed->second);
|
||||
skippedAstRules.insert(rule->name);
|
||||
continue;
|
||||
}
|
||||
// No compile command means this file is not a translation unit
|
||||
// of the build graph — project.cpp, which LoadProject compiles
|
||||
// with its own flags, or a header. A semantic rule does not
|
||||
|
|
|
|||
Loading…
Reference in a new issue