lint rules lite
This commit is contained in:
parent
e906f797da
commit
42a27016e3
4 changed files with 213 additions and 111 deletions
|
|
@ -9,8 +9,10 @@ using namespace Crafter;
|
|||
|
||||
// Validates the house-style ruleset — the transforms and reports every repo
|
||||
// that imports Crafter.LintRules relies on. Each case writes a scratch file,
|
||||
// runs ONE rule via the glob filter, and asserts the findings and/or
|
||||
// rewritten bytes.
|
||||
// runs ONE rule via the glob filter (or all of them, for the cases about the
|
||||
// ruleset as a whole), and asserts the findings and/or rewritten bytes. The
|
||||
// lite cases pin AddLiteRules to AddRules minus the style rules: a style rule
|
||||
// leaking into lite, or a core rule falling out of either set, fails them.
|
||||
namespace {
|
||||
std::int32_t Failures = 0;
|
||||
|
||||
|
|
@ -26,7 +28,7 @@ namespace {
|
|||
std::string text; // file content after the run
|
||||
};
|
||||
|
||||
RuleRun RunRule(std::string_view content, std::string_view rule, LintMode mode) {
|
||||
RuleRun RunRule(std::string_view content, std::string_view rule, LintMode mode, void (*addRules)(Configuration&) = LintRules::AddRules) {
|
||||
static std::int32_t Counter = 0;
|
||||
fs::path dir = fs::temp_directory_path() / "crafter-build-house-rules" / std::format("case-{}", Counter++);
|
||||
fs::remove_all(dir);
|
||||
|
|
@ -43,7 +45,7 @@ namespace {
|
|||
std::array<fs::path, 0> ifaces = {};
|
||||
std::array<fs::path, 1> impls = { "f" };
|
||||
cfg.GetInterfacesAndImplementations(ifaces, impls);
|
||||
LintRules::AddRules(cfg);
|
||||
addRules(cfg);
|
||||
RunLintOptions opts;
|
||||
opts.mode = mode;
|
||||
opts.globs = { std::string(rule) };
|
||||
|
|
@ -534,6 +536,67 @@ int main() {
|
|||
Check(!HasFinding(r.summary, "'already'"), "constexpr: an existing constexpr is not re-reported");
|
||||
}
|
||||
|
||||
// AddLiteRules is AddRules minus the style rules — the rest unchanged and
|
||||
// in the same order, so reports still run before every transform. Both
|
||||
// lists are spelled out: the full one so a rule lost while regrouping
|
||||
// fails here, the lite one so a style rule slipping into a core group
|
||||
// does.
|
||||
{
|
||||
auto namesOf = [](void (*addRules)(Configuration&)) {
|
||||
Configuration cfg;
|
||||
addRules(cfg);
|
||||
std::vector<std::string> names;
|
||||
for (const LintRule& rule : cfg.lintRules) names.push_back(rule.name);
|
||||
return names;
|
||||
};
|
||||
std::vector<std::string> lite = namesOf(LintRules::AddLiteRules);
|
||||
std::vector<std::string> full = namesOf(LintRules::AddRules);
|
||||
std::vector<std::string> expectedLite = {
|
||||
"spdx-header", "enum-class", "no-iostream-print", "no-char-pointer", "const-local", "constexpr-constant",
|
||||
"format-concat", "fixed-width-types",
|
||||
};
|
||||
std::vector<std::string> expectedFull = {
|
||||
"spdx-header", "enum-class", "no-iostream-print", "no-char-pointer", "const-local", "constexpr-constant",
|
||||
"no-tabs", "naming",
|
||||
"format-concat", "fixed-width-types",
|
||||
"single-declaration", "brace-style", "if-single-line", "wrap-join", "paren-spacing", "trim-trailing-ws", "final-newline",
|
||||
};
|
||||
Check(lite == expectedLite, std::format("lite: exactly the non-style rules, in order (got {})", lite));
|
||||
Check(full == expectedFull, std::format("full: all 17 rules, reports before transforms (got {})", full));
|
||||
}
|
||||
|
||||
// The same file through both entry points. It breaks the style rules — an
|
||||
// Allman brace, tabs, snake_case functions, a wrapped call padded inside
|
||||
// its parens, trailing whitespace, no final newline — and two core ones:
|
||||
// a plain enum, which lite reports, and an `int`, which lite rewrites.
|
||||
// Lite must do exactly that and leave every other byte alone. The full run
|
||||
// is the control: it shows this fixture really does trip the style rules,
|
||||
// which is what makes lite leaving them alone mean something.
|
||||
{
|
||||
std::string_view source = "// SPDX-License-Identifier: MIT\n"
|
||||
"// SPDX-FileCopyrightText: Copyright (C) 2026 Fixture\n"
|
||||
"\n"
|
||||
"#include <cstdint>\n"
|
||||
"enum Color { Red };\n"
|
||||
"void call_me(bool alpha, bool beta);\n"
|
||||
"int snake_case_fn(bool alpha, bool beta)\n"
|
||||
"{\n"
|
||||
"\tcall_me( alpha,\n"
|
||||
"\t beta ); \n"
|
||||
"\treturn 0;\n"
|
||||
"}";
|
||||
std::string expected(source);
|
||||
expected.replace(expected.find("int snake_case_fn"), 3, "std::int32_t");
|
||||
RuleRun lite = RunRule(source, "*", LintMode::Apply, LintRules::AddLiteRules);
|
||||
Check(lite.text == expected, "lite: rewrites the int and leaves every style violation byte for byte");
|
||||
Check(lite.summary.errors == 0, "lite: every rule ran, the AST ones included");
|
||||
Check(lite.summary.findings.size() == 1 && lite.summary.findings[0].rule == "enum-class", std::format("lite: the plain enum is the only finding ({} found)", lite.summary.findings.size()));
|
||||
RuleRun full = RunRule(source, "*", LintMode::Apply);
|
||||
Check(full.text != lite.text, "full: the style transforms rewrite the same file further");
|
||||
Check(HasFinding(full.summary, "should be PascalCase"), "full: naming reports the same file");
|
||||
Check(HasFinding(full.summary, "tab character"), "full: no-tabs reports the same file");
|
||||
}
|
||||
|
||||
if (Failures > 0) {
|
||||
std::println(std::cerr, "{} assertions failed", Failures);
|
||||
return 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue