-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang-tidy] support query based custom check #131804
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang-tidy @llvm/pr-subscribers-clang-tools-extra Author: Congcong Cai (HerrCai0907) ChangesPatch is 31.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131804.diff 25 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/CMakeLists.txt b/clang-tools-extra/clang-tidy/CMakeLists.txt
index 93117cf1d6373..90efd2ef1f451 100644
--- a/clang-tools-extra/clang-tidy/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/CMakeLists.txt
@@ -58,6 +58,7 @@ add_subdirectory(bugprone)
add_subdirectory(cert)
add_subdirectory(concurrency)
add_subdirectory(cppcoreguidelines)
+add_subdirectory(custom)
add_subdirectory(darwin)
add_subdirectory(fuchsia)
add_subdirectory(google)
@@ -85,6 +86,7 @@ set(ALL_CLANG_TIDY_CHECKS
clangTidyCERTModule
clangTidyConcurrencyModule
clangTidyCppCoreGuidelinesModule
+ clangTidyCustomModule
clangTidyDarwinModule
clangTidyFuchsiaModule
clangTidyGoogleModule
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index d99847a82d168..f2a69e01a32c5 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -57,6 +57,11 @@ LLVM_INSTANTIATE_REGISTRY(clang::tidy::ClangTidyModuleRegistry)
namespace clang::tidy {
+namespace custom {
+extern void registerCustomChecks(ClangTidyOptions const &O,
+ ClangTidyCheckFactories &Factories);
+} // namespace custom
+
namespace {
#if CLANG_TIDY_ENABLE_STATIC_ANALYZER
static const char *AnalyzerCheckNamePrefix = "clang-analyzer-";
@@ -346,6 +351,7 @@ ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
: Context(Context), OverlayFS(std::move(OverlayFS)),
CheckFactories(new ClangTidyCheckFactories) {
+ custom::registerCustomChecks(Context.getOptions(), *CheckFactories);
for (ClangTidyModuleRegistry::entry E : ClangTidyModuleRegistry::entries()) {
std::unique_ptr<ClangTidyModule> Module = E.instantiate();
Module->addCheckFactories(*CheckFactories);
@@ -416,7 +422,7 @@ ClangTidyASTConsumerFactory::createASTConsumer(
.getCurrentWorkingDirectory();
if (WorkingDir)
Context.setCurrentBuildDirectory(WorkingDir.get());
-
+ custom::registerCustomChecks(Context.getOptions(), *CheckFactories);
std::vector<std::unique_ptr<ClangTidyCheck>> Checks =
CheckFactories->createChecksForLanguage(&Context);
@@ -659,6 +665,7 @@ getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) {
std::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(), Opts),
AllowEnablingAnalyzerAlphaCheckers);
ClangTidyCheckFactories Factories;
+ custom::registerCustomChecks(Context.getOptions(), Factories);
for (const ClangTidyModuleRegistry::entry &Module :
ClangTidyModuleRegistry::entries()) {
Module.instantiate()->addCheckFactories(Factories);
diff --git a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
index adde9136ff1dd..50ac6e138df18 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
@@ -54,6 +54,11 @@ extern volatile int CppCoreGuidelinesModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination =
CppCoreGuidelinesModuleAnchorSource;
+// This anchor is used to force the linker to link the CustomModule.
+extern volatile int CustomModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED CustomModuleAnchorDestination =
+ CustomModuleAnchorSource;
+
// This anchor is used to force the linker to link the DarwinModule.
extern volatile int DarwinModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED DarwinModuleAnchorDestination =
diff --git a/clang-tools-extra/clang-tidy/ClangTidyModule.h b/clang-tools-extra/clang-tidy/ClangTidyModule.h
index 28f54331755a7..6f0b2bf32a291 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyModule.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyModule.h
@@ -62,6 +62,8 @@ class ClangTidyCheckFactories {
});
}
+ void erase(llvm::StringRef CheckName) { Factories.erase(CheckName); }
+
/// Create instances of checks that are enabled.
std::vector<std::unique_ptr<ClangTidyCheck>>
createChecks(ClangTidyContext *Context) const;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index 8bac6f161fa05..acedbd8d41faa 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -8,12 +8,12 @@
#include "ClangTidyOptions.h"
#include "ClangTidyModuleRegistry.h"
+#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLTraits.h"
@@ -72,7 +72,8 @@ struct NOptionMap {
NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap) {
Options.reserve(OptionMap.size());
for (const auto &KeyValue : OptionMap)
- Options.emplace_back(std::string(KeyValue.getKey()), KeyValue.getValue().Value);
+ Options.emplace_back(std::string(KeyValue.getKey()),
+ KeyValue.getValue().Value);
}
ClangTidyOptions::OptionMap denormalize(IO &) {
ClangTidyOptions::OptionMap Map;
@@ -126,6 +127,52 @@ void yamlize(IO &IO, ClangTidyOptions::OptionMap &Val, bool,
}
}
+namespace {
+struct MultiLineString {
+ std::string &S;
+};
+} // namespace
+
+template <> struct BlockScalarTraits<MultiLineString> {
+ static void output(const MultiLineString &S, void *Ctxt, raw_ostream &OS) {
+ OS << S.S;
+ }
+ static StringRef input(StringRef Str, void *Ctxt, MultiLineString &S) {
+ S.S = Str;
+ return "";
+ }
+};
+
+template <> struct ScalarEnumerationTraits<clang::DiagnosticIDs::Level> {
+ static void enumeration(IO &IO, clang::DiagnosticIDs::Level &Level) {
+ IO.enumCase(Level, "Error", clang::DiagnosticIDs::Level::Error);
+ IO.enumCase(Level, "Warning", clang::DiagnosticIDs::Level::Warning);
+ IO.enumCase(Level, "Note", clang::DiagnosticIDs::Level::Note);
+ }
+};
+template <> struct SequenceElementTraits<ClangTidyOptions::CustomCheckDiag> {
+ static const bool flow = false;
+};
+template <> struct MappingTraits<ClangTidyOptions::CustomCheckDiag> {
+ static void mapping(IO &IO, ClangTidyOptions::CustomCheckDiag &D) {
+ IO.mapRequired("BindName", D.BindName);
+ MultiLineString MLS{D.Message};
+ IO.mapRequired("Message", MLS);
+ IO.mapOptional("Level", D.Level);
+ }
+};
+template <> struct SequenceElementTraits<ClangTidyOptions::CustomCheckValue> {
+ static const bool flow = false;
+};
+template <> struct MappingTraits<ClangTidyOptions::CustomCheckValue> {
+ static void mapping(IO &IO, ClangTidyOptions::CustomCheckValue &V) {
+ IO.mapRequired("Name", V.Name);
+ MultiLineString MLS{V.Query};
+ IO.mapRequired("Query", MLS);
+ IO.mapRequired("Diagnostic", V.Diags);
+ }
+};
+
struct ChecksVariant {
std::optional<std::string> AsString;
std::optional<std::vector<std::string>> AsVector;
@@ -181,6 +228,7 @@ template <> struct MappingTraits<ClangTidyOptions> {
IO.mapOptional("InheritParentConfig", Options.InheritParentConfig);
IO.mapOptional("UseColor", Options.UseColor);
IO.mapOptional("SystemHeaders", Options.SystemHeaders);
+ IO.mapOptional("CustomChecks", Options.CustomChecks);
}
};
@@ -249,6 +297,8 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other,
ClangTidyValue(KeyValue.getValue().Value,
KeyValue.getValue().Priority + Order));
}
+ mergeVectors(CustomChecks, Other.CustomChecks);
+
return *this;
}
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
index dd78c570d25d9..2a64ee8fdf7ea 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
@@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
+#include "clang/Basic/DiagnosticIDs.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
@@ -17,6 +18,7 @@
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <functional>
+#include <map>
#include <optional>
#include <string>
#include <system_error>
@@ -129,6 +131,19 @@ struct ClangTidyOptions {
/// Key-value mapping used to store check-specific options.
OptionMap CheckOptions;
+ struct CustomCheckDiag {
+ std::string BindName;
+ std::string Message;
+ std::optional<DiagnosticIDs::Level> Level;
+ };
+ struct CustomCheckValue {
+ std::string Name;
+ std::string Query;
+ llvm::SmallVector<CustomCheckDiag> Diags;
+ };
+ using CustomCheckValueList = llvm::SmallVector<CustomCheckValue>;
+ std::optional<CustomCheckValueList> CustomChecks;
+
using ArgList = std::vector<std::string>;
/// Add extra compilation arguments to the end of the list.
diff --git a/clang-tools-extra/clang-tidy/custom/CMakeLists.txt b/clang-tools-extra/clang-tidy/custom/CMakeLists.txt
new file mode 100644
index 0000000000000..40387b73b5253
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/custom/CMakeLists.txt
@@ -0,0 +1,20 @@
+set(LLVM_LINK_COMPONENTS
+ support
+ )
+
+add_clang_library(clangTidyCustomModule STATIC
+ CustomTidyModule.cpp
+ QueryCheck.cpp
+
+ LINK_LIBS
+ clangTidy
+ clangTidyUtils
+
+ DEPENDS
+ ClangDriverOptions
+ )
+
+clang_target_link_libraries(clangTidyCustomModule
+ PRIVATE
+ clangQuery
+ )
diff --git a/clang-tools-extra/clang-tidy/custom/CustomTidyModule.cpp b/clang-tools-extra/clang-tidy/custom/CustomTidyModule.cpp
new file mode 100644
index 0000000000000..e11a39f1a4ccf
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/custom/CustomTidyModule.cpp
@@ -0,0 +1,50 @@
+#include "../ClangTidy.h"
+#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+#include "../ClangTidyOptions.h"
+#include "QueryCheck.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace clang::tidy {
+namespace custom {
+
+class CustomModule : public ClangTidyModule {
+public:
+ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {}
+};
+
+// FIXME: could be clearer to add parameter of addCheckFactories to pass
+// Options?
+extern void registerCustomChecks(ClangTidyOptions const &Options,
+ ClangTidyCheckFactories &Factories) {
+ static llvm::SmallSet<llvm::SmallString<32>, 8> CustomCheckNames{};
+ if (!Options.CustomChecks.has_value() || Options.CustomChecks->empty())
+ return;
+ for (llvm::SmallString<32> const &Name : CustomCheckNames)
+ Factories.erase(Name);
+ for (const ClangTidyOptions::CustomCheckValue &V :
+ Options.CustomChecks.value()) {
+ llvm::SmallString<32> Name = llvm::StringRef{"custom-" + V.Name};
+ Factories.registerCheckFactory(
+ // add custom- prefix to avoid conflicts with builtin checks
+ Name, [&V](llvm::StringRef Name, ClangTidyContext *Context) {
+ return std::make_unique<custom::QueryCheck>(Name, V, Context);
+ });
+ CustomCheckNames.insert(std::move(Name));
+ }
+}
+
+} // namespace custom
+
+// Register the AlteraTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<custom::CustomModule>
+ X("custom-module", "Adds custom query lint checks.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the AlteraModule.
+volatile int CustomModuleAnchorSource = 0;
+
+} // namespace clang::tidy
diff --git a/clang-tools-extra/clang-tidy/custom/QueryCheck.cpp b/clang-tools-extra/clang-tidy/custom/QueryCheck.cpp
new file mode 100644
index 0000000000000..c69e76918f7ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/custom/QueryCheck.cpp
@@ -0,0 +1,102 @@
+//===--- QueryCheck.cpp - clang-tidy --------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "QueryCheck.h"
+#include "../../clang-query/Query.h"
+#include "../../clang-query/QueryParser.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::custom {
+
+QueryCheck::QueryCheck(llvm::StringRef Name,
+ const ClangTidyOptions::CustomCheckValue &V,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {
+ for (const ClangTidyOptions::CustomCheckDiag &D : V.Diags) {
+ auto DiagnosticIdIt =
+ Diags
+ .try_emplace(D.Level.value_or(DiagnosticIDs::Warning),
+ llvm::StringMap<llvm::SmallVector<std::string>>{})
+ .first;
+ auto DiagMessageIt =
+ DiagnosticIdIt->getSecond()
+ .try_emplace(D.BindName, llvm::SmallVector<std::string>{})
+ .first;
+ DiagMessageIt->second.emplace_back(D.Message);
+ }
+
+ clang::query::QuerySession QS({});
+ llvm::StringRef QueryStringRef{V.Query};
+ while (!QueryStringRef.empty()) {
+ query::QueryRef Q = query::QueryParser::parse(QueryStringRef, QS);
+ switch (Q->Kind) {
+ case query::QK_Match: {
+ const auto &MatchQuerry = llvm::cast<query::MatchQuery>(*Q);
+ Matchers.push_back(MatchQuerry.Matcher);
+ break;
+ }
+ case query::QK_Let: {
+ const auto &LetQuerry = llvm::cast<query::LetQuery>(*Q);
+ LetQuerry.run(llvm::errs(), QS);
+ break;
+ }
+ case query::QK_Invalid: {
+ const auto &InvalidQuerry = llvm::cast<query::InvalidQuery>(*Q);
+ Context->configurationDiag(InvalidQuerry.ErrStr);
+ break;
+ }
+ // FIXME: TODO
+ case query::QK_File:
+ case query::QK_DisableOutputKind:
+ case query::QK_EnableOutputKind:
+ case query::QK_SetOutputKind:
+ case query::QK_SetTraversalKind:
+ case query::QK_Help:
+ case query::QK_NoOp:
+ case query::QK_Quit:
+ case query::QK_SetBool: {
+ Context->configurationDiag("unsupported querry kind");
+ }
+ }
+ QueryStringRef = Q->RemainingContent;
+ }
+}
+
+void QueryCheck::registerMatchers(MatchFinder *Finder) {
+ for (const ast_matchers::dynamic::DynTypedMatcher &M : Matchers)
+ Finder->addDynamicMatcher(M, this);
+}
+
+void QueryCheck::check(const MatchFinder::MatchResult &Result) {
+ auto Emit = [this](DiagMaps const &DiagMaps, std::string const &BindName,
+ DynTypedNode const &Node, DiagnosticIDs::Level Level) {
+ if (!DiagMaps.contains(Level))
+ return;
+ auto &DiagMap = DiagMaps.at(Level);
+ if (!DiagMap.contains(BindName))
+ return;
+ for (const std::string &Message : DiagMap.at(BindName)) {
+ diag(Node.getSourceRange().getBegin(), Message, Level);
+ }
+ };
+ for (auto &[Name, Node] : Result.Nodes.getMap())
+ Emit(Diags, Name, Node, DiagnosticIDs::Error);
+ for (auto &[Name, Node] : Result.Nodes.getMap())
+ Emit(Diags, Name, Node, DiagnosticIDs::Warning);
+ // place Note last, otherwise it will not be emitted
+ for (auto &[Name, Node] : Result.Nodes.getMap())
+ Emit(Diags, Name, Node, DiagnosticIDs::Note);
+}
+} // namespace clang::tidy::custom
diff --git a/clang-tools-extra/clang-tidy/custom/QueryCheck.h b/clang-tools-extra/clang-tidy/custom/QueryCheck.h
new file mode 100644
index 0000000000000..ded4cad4e3459
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/custom/QueryCheck.h
@@ -0,0 +1,42 @@
+//===--- QueryCheck.h - clang-tidy ------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CUSTOM_QUERYCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CUSTOM_QUERYCHECK_H
+
+#include "../ClangTidyCheck.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang::tidy::custom {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/custom/query.html
+class QueryCheck : public ClangTidyCheck {
+public:
+ QueryCheck(llvm::StringRef Name, const ClangTidyOptions::CustomCheckValue &V,
+ ClangTidyContext *Context);
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ llvm::SmallVector<ast_matchers::dynamic::DynTypedMatcher> Matchers{};
+ using DiagMaps =
+ llvm::DenseMap<DiagnosticIDs::Level,
+ llvm::StringMap<llvm::SmallVector<std::string>>>;
+ DiagMaps Diags;
+};
+
+} // namespace clang::tidy::custom
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CUSTOM_QUERYCHECK_H
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index fa8887e4639b4..5784b05d2281d 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -60,6 +60,8 @@ Configuration files:
Checks - Same as '--checks'. Additionally, the list of
globs can be specified as a list instead of a
string.
+ CustomChecks - Array of user defined checks based on
+ clang-query syntax.
ExcludeHeaderFilterRegex - Same as '--exclude-header-filter'.
ExtraArgs - Same as '--extra-arg'.
ExtraArgsBefore - Same as '--extra-arg-before'.
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 2252efb498c2c..6d22f83f2248b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -96,6 +96,9 @@ Improvements to clang-tidy
`SystemHeaders` option is enabled.
Note: this may lead to false negatives; downstream users may need to adjust
their checks to preserve existing behavior.
+- :program:`clang-tidy` now supports query based custom checks by `CustomChecks`
+ configuration option.
+ :doc:`Query Based Custom Check Document <clang-tidy/QueryBasedCustomChecks>`
New checks
^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/QueryBasedCustomChecks.rst b/clang-tools-extra/docs/clang-tidy/QueryBasedCustomChecks.rst
new file mode 100644
index 0000000000000..6efd8fe6797df
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/QueryBasedCustomChecks.rst
@@ -0,0 +1,57 @@
+====================================
+Query Based Custom Clang-Tidy Checks
+====================================
+
+Introduction
+============
+
+This page provides examples of how to add query based custom checks for
+:program:`clang-tidy`.
+
+Custom checks are based on clang-query syntax. Every custom checks will be
+registered in `custom` module to avoid name conflict. They can be enabled or
+disabled by the checks option like the builtin checks.
+
+Custom checks support inheritance from parent configurations like other
+configuration items.
+
+Configuration
+=============
+
+`CustomChecks` is a list of custom checks. Each check must contain
+ - Name: check name can been used in `-checks` option.
+ - Query: query string
+ - Diagnostic: list of diagnostics to be reported.
+ - BindName: name of the node to be bound in `Query`.
+ - Message: message to be reported.
+ - Level: severity of the diagnostic, the possible val...
[truncated]
|
c6e485e
to
64c45dc
Compare
--dump-config will create incorrect YAML due to #131694. |
clang-tools-extra/test/clang-tidy/infrastructure/Inputs/custom-query-check/empty-clang-tidy.yml
Outdated
Show resolved
Hide resolved
Co-authored-by: Baranov Victor <[email protected]>
Sorry for being late for the review. This is a major new feature of clang-tidy, so I believe it would be good to have an RFC before looking at the detailed implementation. What problem does it solve, why should clang-tidy solve it, what the API towards the user should be, etc. Should we do that? |
@carlosgalvezp Hi, I tried to explain everything here: #107680 |
823b423
to
b2cecb8
Compare
…s/ccc/clang-tidy/query-check
There are 2 kinds of stability here:
|
ping @PiotrZSL @vbvictor @carlosgalvezp |
Co-authored-by: Baranov Victor <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly docs suggestions. I like this approach with config file, but don't have a strong opinion for now, so LGTM without explicit approval.
// FIXME: TODO | ||
case query::QK_File: { | ||
emitConfigurationDiag(Context, "unsupported query kind 'File'", V.Name); | ||
return {}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could these repetitive switch-cases optimized a little?
We could create a mapping of QueryKind
and its' readable-name and here just find string-name by enum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we should support them one by one, I think the unsupported query kind will not be so much. creating mapping will make things more complex.
Co-authored-by: Baranov Victor <[email protected]>
summary
Design for Compatibility
For new field design
For large project integration (3rd party)
2.For clang-query, if there are some break change, since the query will be parsed at check time, the user can disable the check and it will not damage the whole clang-tidy
Inherit from #123734
RFC: https://discourse.llvm.org/t/support-query-based-clang-tidy-external-check/85331
this patch introduce query based custom check by
CustomChecks
options.The major improvement compared with #123734:
InheritFromParantConfig
is same as other config.example:
To make this PR don't do too much things that hard to review, here are some possible features not included in this PR