linting
Some checks failed
CI / build-test-release (push) Failing after 7m15s

This commit is contained in:
Jorijn van der Graaf 2026-07-23 01:24:42 +02:00
commit 8892154b28
70 changed files with 2780 additions and 596 deletions

View file

@ -1,5 +1,5 @@
//SPDX-License-Identifier: LGPL-3.0-only
//SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
// SPDX-License-Identifier: LGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
module;
#include "Crafter.Build-Api.h"
@ -96,12 +96,91 @@ export namespace Crafter {
struct TestResult {
std::string name;
TestOutcome outcome = TestOutcome::Pass;
int exitCode = 0;
int signal = 0;
std::int32_t exitCode = 0;
std::int32_t signal = 0;
std::chrono::milliseconds duration{0};
std::string output;
};
// One lint diagnostic. Produced by LintContext::Report — or derived by
// the driver when a transform rule's SetContent output differs from the
// file on disk ("would reformat") — collected and printed compiler-style
// by RunLint (Crafter.Build:Lint):
// <file>:<line>: warning: <message> [<rule>]
struct LintFinding {
fs::path file;
std::size_t line = 0; // 1-based; 0 = whole-file finding
std::string rule; // name of the rule that produced it
std::string message;
};
// Parsed `// lint-disable-*` suppression directives for one file (see
// LintContext::Suppressed). Line keys are 1-based and refer to the line a
// next-line directive TARGETS (the line after the comment).
struct LintSuppressions {
bool fileAll = false;
std::unordered_set<std::string> fileRules;
std::unordered_set<std::size_t> lineAll;
std::unordered_map<std::size_t, std::unordered_set<std::string>> lineRules;
};
// Per-file view handed to each LintRule's check callback. Every member
// function is out-of-line and CRAFTER_API (defined in Crafter.Build:Lint's
// implementation unit) because rule lambdas execute from the user's
// project DLL on Windows — clang does not emit module-attached in-class
// inline bodies into consumers (see ArgQuery below).
struct LintContext {
fs::path file; // absolute path of the file under lint
std::string content; // whole file as read from disk
std::vector<std::string_view> lines; // views into `content`, one per line, no '\n'
CRAFTER_API std::string Extension() const; // ".cppm", ".cpp", ".h", ...
CRAFTER_API std::string_view Line(std::size_t n) const; // 1-based; empty if out of range
// `content` with //-comments, /*...*/ comments and string/char literal
// bodies blanked to spaces, newlines preserved — offsets and line
// numbers stay valid. Built on first call, cached per file. Raw string
// literals are not recognized (v1 limitation).
CRAFTER_API const std::string& CommentStripped();
// Record a finding at `line` (1-based; pass 0 for a whole-file finding).
CRAFTER_API void Report(std::size_t line, std::string message);
// Replace the file's content. Makes this rule a *transform*:
// `crafter-build format` writes the result back to disk; `lint`
// derives would-reformat findings from it (dry — never writes).
// `lines` is re-split and CommentStripped() re-derives on next call;
// string_views taken before this call are invalidated. Recommended
// pattern: build the new string, call SetContent once at the end. Do
// not assign `content` directly — that bypasses the re-split. May be
// combined with Report() in the same rule.
CRAFTER_API void SetContent(std::string newContent);
// True when `rule` is suppressed at `line` (1-based; 0 = whole-file,
// which only file-level directives cover) by a suppression comment:
// // lint-disable-next-line [rules...] applies to the following line
// // lint-disable-file [rules...] applies to the whole file
// Rule names are space- or comma-separated; none = all rules. The
// driver already filters Report()
// findings and reverts line-preserving transform edits on suppressed
// lines; a transform that MERGES or SPLITS lines must consult this
// itself for every line its edit touches (the driver cannot map lines
// across a count-changing rewrite). Parsed lazily from the raw lines;
// re-parsed after SetContent.
CRAFTER_API bool Suppressed(std::string_view rule, std::size_t line);
// Driver wiring — set by RunLint before each check call. Not for rules.
std::string activeRule;
std::vector<LintFinding>* sink = nullptr;
std::optional<std::string> commentStrippedCache;
std::optional<LintSuppressions> suppressionsCache;
};
// A named lint rule: `check` runs once per (rule, file) over the project's
// own sources. Rules self-filter by ctx.Extension() / ctx.file. A rule
// that calls ctx.SetContent is a transform — defined once, it both gates
// `crafter-build lint` and fixes under `crafter-build format`.
struct LintRule {
std::string name;
std::function<void(LintContext&)> check;
};
// The host target triple, detected once per process by running
// `clang++ -print-target-triple` and cached. Used as the default for
// Configuration::target so projects don't have to hardcode it for the
@ -172,6 +251,8 @@ export namespace Crafter {
// wasmVariants instead.
std::vector<std::string> wasmVariantFlags;
std::vector<Test> tests;
// Lint rules for `crafter-build lint`. Populate via AddLintRule.
std::vector<LintRule> lintRules;
CRAFTER_API void GetInterfacesAndImplementations(std::span<fs::path> interfaces, std::span<fs::path> implementations);
// Declare a test. Sources default to `tests/<name>/main.cpp` resolved
// against this Configuration's path; target/march/mtune/sysroot/debug
@ -188,9 +269,14 @@ export namespace Crafter {
// `tests/<name>/main.cpp` source and the same interface set, each
// compiled with the tier's `-march`/`-mtune`. Test names are
// `<name>-<march>`.
CRAFTER_API void AddMarchVariants(std::string_view name,
std::span<fs::path> interfaces,
std::span<const struct MarchTier> tiers);
CRAFTER_API void AddMarchVariants(std::string_view name, std::span<fs::path> interfaces, std::span<const struct MarchTier> tiers);
// Register a lint rule for `crafter-build lint` / `format`. Rules
// registered on any Configuration whose path lies inside the project
// root are collected (deduplicated by name, root-first) — attach them
// to the lib or the exe config, either works. Rules that call
// ctx.SetContent are transforms (see LintContext::SetContent).
// Defined in Crafter.Build:Lint.
CRAFTER_API void AddLintRule(std::string name, std::function<void(LintContext&)> check);
// Suffix that uniquely identifies this Configuration's compile state.
// target+march+mtune are spelled out for readability; the rest
// (type, debug, sysroot, defines, compileFlags) collapse into a short
@ -198,7 +284,7 @@ export namespace Crafter {
// compile state can't clobber each other's outputs.
std::string VariantId() const {
std::string compileKey;
compileKey += std::to_string(static_cast<int>(type));
compileKey += std::to_string(static_cast<std::int32_t>(type));
compileKey += '|';
compileKey += debug ? '1' : '0';
compileKey += '|';
@ -297,4 +383,4 @@ export namespace Crafter {
// can query their own flags (`--timing`, ...) without re-rolling the
// for-arg-in-args loop.
CRAFTER_API ArgQuery ApplyStandardArgs(Configuration& cfg, std::span<const std::string_view> args);
}
}