Files
RedBear-OS/local/recipes/dev/libclc/source/clang-tools-extra/tool-template/ToolTemplate.cpp
T
vasilito cb424d7448 build: static patch-sanity linter (shift-left the malformed-patch class)
verify-patch-sanity.py validates every active recipe .patch has internally-
consistent hunk line counts — catching the 'malformed patch at line N' failure
at commit/CI/preflight time instead of hours into a cook. This cycle hit that
class three times (qtwaylandscanner, sddm, xwayland), each only discovered when
cookbook tried to apply the patch.

Running it across the repo found 29 latent malformed patches (validated against
GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22').
They were harmless only because they sit in vendored recipes (baked, not re-
applied) — but would fail on any version-bump re-derivation. --fix recounts the
hunk headers (body untouched) and repaired all 29.

Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test
(test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats
(empty placeholders, bare-@@ git hunks).
2026-08-01 05:13:02 +03:00

122 lines
4.4 KiB
C++

//===---- tools/extra/ToolTemplate.cpp - Template for refactoring tool ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements an empty refactoring tool using the clang tooling.
// The goal is to lower the "barrier to entry" for writing refactoring tools.
//
// Usage:
// tool-template <cmake-output-dir> <file1> <file2> ...
//
// Where <cmake-output-dir> is a CMake build directory in which a file named
// compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
// CMake to get this output).
//
// <file1> ... specify the paths of files in the CMake source tree. This path
// is looked up in the compile command database. If the path of a file is
// absolute, it needs to point into CMake's source tree. If the path is
// relative, the current working directory needs to be in the CMake source
// tree and the file must be in a subdirectory of the current working
// directory. "./" prefixes in the relative files will be automatically
// removed, but the rest of a relative path must be a suffix of a path in
// the compile command line database.
//
// For example, to use tool-template on all files in a subtree of the
// source tree, use:
//
// /path/in/subtree $ find . -name '*.cpp'|
// xargs tool-template /path/to/build
//
//===----------------------------------------------------------------------===//
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Execution.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Refactoring/AtomicChange.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace llvm;
namespace {
class ToolTemplateCallback : public MatchFinder::MatchCallback {
public:
ToolTemplateCallback(ExecutionContext &Context) : Context(Context) {}
void run(const MatchFinder::MatchResult &Result) override {
// TODO: This routine will get called for each thing that the matchers
// find.
// At this point, you can examine the match, and do whatever you want,
// including replacing the matched text with other text
auto *D = Result.Nodes.getNodeAs<NamedDecl>("decl");
assert(D);
// Use AtomicChange to get a key.
if (D->getBeginLoc().isValid()) {
AtomicChange Change(*Result.SourceManager, D->getBeginLoc());
Context.reportResult(Change.getKey(), D->getQualifiedNameAsString());
}
}
void onStartOfTranslationUnit() override {
Context.reportResult("START", "Start of TU.");
}
void onEndOfTranslationUnit() override {
Context.reportResult("END", "End of TU.");
}
private:
ExecutionContext &Context;
};
} // end anonymous namespace
// Set up the command line options
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
static cl::OptionCategory ToolTemplateCategory("tool-template options");
int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
argc, argv, ToolTemplateCategory);
if (!Executor) {
llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
return 1;
}
ast_matchers::MatchFinder Finder;
ToolTemplateCallback Callback(*Executor->get()->getExecutionContext());
// TODO: Put your matchers here.
// Use Finder.addMatcher(...) to define the patterns in the AST that you
// want to match against. You are not limited to just one matcher!
//
// This is a sample matcher:
Finder.addMatcher(
namedDecl(cxxRecordDecl(), isExpansionInMainFile()).bind("decl"),
&Callback);
auto Err = Executor->get()->execute(newFrontendActionFactory(&Finder));
if (Err) {
llvm::errs() << llvm::toString(std::move(Err)) << "\n";
}
Executor->get()->getToolResults()->forEachResult(
[](llvm::StringRef key, llvm::StringRef value) {
llvm::errs() << "----" << key.str() << "\n" << value.str() << "\n";
});
}