This commit is contained in:
parent
a25b0a1ded
commit
8892154b28
70 changed files with 2780 additions and 596 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue