diff --git a/clang-tidy/.editorconfig b/clang-tidy/.editorconfig new file mode 100644 index 000000000..19ee09eec --- /dev/null +++ b/clang-tidy/.editorconfig @@ -0,0 +1,4 @@ +# LLVM style code is 2-space indented +[*.{cc,hh}] +indent_style = space +indent_size = 2 diff --git a/clang-tidy/FixIncludes.cc b/clang-tidy/FixIncludes.cc new file mode 100644 index 000000000..8ba350243 --- /dev/null +++ b/clang-tidy/FixIncludes.cc @@ -0,0 +1,81 @@ +#include "FixIncludes.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace nix::clang_tidy { + +using namespace clang; +using namespace clang::tidy; + +class FixIncludesCallbacks : public PPCallbacks { +public: + ClangTidyCheck &Check; + Preprocessor &PP; + FixIncludesCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + +private: + bool Ignore = false; + virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID, SourceLocation Loc) override; + + virtual void InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, StringRef FileName, + bool IsAngled, CharSourceRange FilenameRange, + OptionalFileEntryRef File, + StringRef SearchPath, StringRef RelativePath, + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override; +}; + +void FixIncludesCallbacks::LexedFileChanged(FileID, LexedFileChangeReason, + SrcMgr::CharacteristicKind FileType, + FileID, SourceLocation) { + Ignore = FileType != SrcMgr::C_User; +} + +void FixIncludesCallbacks::InclusionDirective( + SourceLocation, const Token &, StringRef, bool, + CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef, + StringRef, const Module *, SrcMgr::CharacteristicKind) { + if (Ignore) + return; + + // FIXME: this is kinda evil, but this is a one-time fixup + const std::string SourceDir = "src/"; + + if (File && File->getNameAsRequested().contains(SourceDir)) { + StringRef Name = File->getNameAsRequested(); + auto Idx = Name.find(SourceDir); + assert(Idx != std::string::npos); + StringRef Suffix = Name.drop_front(Idx + SourceDir.length()); + + if (!Suffix.starts_with("lib")) { + llvm::dbgs() << "ignored: " << Suffix << "\n"; + return; + } + + auto Diag = Check.diag(FilenameRange.getBegin(), + "include needs to specify the source subdir"); + + Diag << FilenameRange + << FixItHint::CreateReplacement(FilenameRange, + ("\"" + Suffix + "\"").str()); + } +} + +void FixIncludesCheck::registerPPCallbacks(const SourceManager &, + Preprocessor *PP, Preprocessor *) { + PP->addPPCallbacks(std::make_unique(*this, *PP)); +} + +}; // namespace nix::clang_tidy diff --git a/clang-tidy/FixIncludes.hh b/clang-tidy/FixIncludes.hh new file mode 100644 index 000000000..ea890cd39 --- /dev/null +++ b/clang-tidy/FixIncludes.hh @@ -0,0 +1,21 @@ +#pragma once +///@file + +#include +#include +#include + +namespace nix::clang_tidy { + +using namespace clang; +using namespace clang::tidy; + +class FixIncludesCheck : public ClangTidyCheck { + public: + FixIncludesCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override; +}; + +}; diff --git a/clang-tidy/NixClangTidyChecks.cc b/clang-tidy/LixClangTidyChecks.cc similarity index 65% rename from clang-tidy/NixClangTidyChecks.cc rename to clang-tidy/LixClangTidyChecks.cc index 8f0309107..b3503dd3a 100644 --- a/clang-tidy/NixClangTidyChecks.cc +++ b/clang-tidy/LixClangTidyChecks.cc @@ -1,5 +1,6 @@ #include #include +#include "FixIncludes.hh" #include "HasPrefixSuffix.hh" namespace nix::clang_tidy { @@ -9,9 +10,10 @@ using namespace clang::tidy; class NixClangTidyChecks : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { - CheckFactories.registerCheck("nix-hasprefixsuffix"); + CheckFactories.registerCheck("lix-hasprefixsuffix"); + CheckFactories.registerCheck("lix-fixincludes"); } }; -static ClangTidyModuleRegistry::Add X("nix-module", "Adds nix specific checks"); +static ClangTidyModuleRegistry::Add X("lix-module", "Adds lix specific checks"); }; diff --git a/clang-tidy/meson.build b/clang-tidy/meson.build index 48770e39f..c59164a72 100644 --- a/clang-tidy/meson.build +++ b/clang-tidy/meson.build @@ -1,8 +1,13 @@ -project('nix-clang-tidy', ['cpp', 'c'], +project('lix-clang-tidy', ['cpp', 'c'], version : '0.1', default_options : ['warning_level=3', 'cpp_std=c++20']) llvm = dependency('Clang', version: '>= 14', modules: ['libclang']) -sources = ['HasPrefixSuffix.cc', 'NixClangTidyChecks.cc'] -shared_module('nix-clang-tidy', sources, +sources = files( + 'HasPrefixSuffix.cc', + 'LixClangTidyChecks.cc', + 'FixIncludes.cc', +) + +shared_module('lix-clang-tidy', sources, dependencies: llvm)