diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.h b/clang-tools-extra/clang-tidy/utils/IncludeSorter.h --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.h +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.h @@ -31,7 +31,8 @@ IK_CSystemInclude = 1, ///< e.g. ``#include `` IK_CXXSystemInclude = 2, ///< e.g. ``#include `` IK_NonSystemInclude = 3, ///< e.g. ``#include "bar.h"`` - IK_InvalidInclude = 4 ///< total number of valid ``IncludeKind``s + IK_GeneratedInclude = 4, ///< e.g. ``#include "bar.proto.h"`` + IK_InvalidInclude = 5 ///< total number of valid ``IncludeKind``s }; /// ``IncludeSorter`` constructor; takes the FileID and name of the file to be diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp @@ -91,6 +91,12 @@ return IncludeSorter::IK_MainTUInclude; } } + if (Style == IncludeSorter::IS_Google_ObjC) { + if (IncludeFile.endswith(".generated.h") || + IncludeFile.endswith(".proto.h") || IncludeFile.endswith(".pbobjc.h")) { + return IncludeSorter::IK_GeneratedInclude; + } + } return IncludeSorter::IK_NonSystemInclude; } diff --git a/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp b/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp --- a/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp @@ -137,6 +137,18 @@ } }; +class ObjCGeneratedHeaderInserterCheck : public IncludeInserterCheckBase { +public: + ObjCGeneratedHeaderInserterCheck(StringRef CheckName, + ClangTidyContext *Context) + : IncludeInserterCheckBase(CheckName, Context, + utils::IncludeSorter::IS_Google_ObjC) {} + + std::vector headersToInclude() const override { + return {"clang_tidy/tests/generated_file.proto.h"}; + } +}; + template std::string runCheckOnCode(StringRef Code, StringRef Filename) { std::vector Errors; @@ -156,6 +168,9 @@ {"path/to/z/header.h", "\n"}, {"path/to/header.h", "\n"}, {"path/to/header2.h", "\n"}, + // Generated headers + {"clang_tidy/tests/" + "generated_file.proto.h", "\n"}, // Fake system headers. {"stdlib.h", "\n"}, {"unistd.h", "\n"}, @@ -706,6 +721,37 @@ "insert_includes_test_header.mm")); } +TEST(IncludeInserterTest, InsertGeneratedHeaderObjectiveC) { + const char *PreCode = R"( +#import "clang_tidy/tests/insert_includes_test_header.h" + +#include +#include + +#include "path/to/a/header.h" + +void foo() { + int a = 0; +})"; + const char *PostCode = R"( +#import "clang_tidy/tests/insert_includes_test_header.h" + +#include +#include + +#include "path/to/a/header.h" + +#import "clang_tidy/tests/generated_file.proto.h" + +void foo() { + int a = 0; +})"; + + EXPECT_EQ(PostCode, runCheckOnCode( + PreCode, "devtools/cymbal/clang_tidy/tests/" + "insert_includes_test_header.mm")); +} + } // anonymous namespace } // namespace tidy } // namespace clang