Index: clang-tools-extra/trunk/clang-tidy/utils/IncludeSorter.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/utils/IncludeSorter.cpp +++ clang-tools-extra/trunk/clang-tidy/utils/IncludeSorter.cpp @@ -61,7 +61,8 @@ : IncludeSorter::IK_CXXSystemInclude; } StringRef CanonicalInclude = MakeCanonicalName(IncludeFile, Style); - if (CanonicalFile.equals(CanonicalInclude)) { + if (CanonicalFile.endswith(CanonicalInclude) + || CanonicalInclude.endswith(CanonicalFile)) { return IncludeSorter::IK_MainTUInclude; } if (Style == IncludeSorter::IS_Google) { Index: clang-tools-extra/trunk/unittests/clang-tidy/IncludeInserterTest.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clang-tidy/IncludeInserterTest.cpp +++ clang-tools-extra/trunk/unittests/clang-tidy/IncludeInserterTest.cpp @@ -73,6 +73,17 @@ bool IsAngledInclude() const override { return false; } }; +class EarlyInAlphabetHeaderInserterCheck : public IncludeInserterCheckBase { +public: + EarlyInAlphabetHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context) + : IncludeInserterCheckBase(CheckName, Context) {} + + std::vector HeadersToInclude() const override { + return {"a/header.h"}; + } + bool IsAngledInclude() const override { return false; } +}; + class MultipleHeaderInserterCheck : public IncludeInserterCheckBase { public: MultipleHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context) @@ -114,6 +125,7 @@ "insert_includes_test_header.h", "\n"}, // Non system headers + {"a/header.h", "\n"}, {"path/to/a/header.h", "\n"}, {"path/to/z/header.h", "\n"}, {"path/to/header.h", "\n"}, @@ -522,6 +534,77 @@ "insert_includes_test_header.cc")); } +TEST(IncludeInserterTest, DontInsertDuplicateIncludeEvenIfMiscategorized) { + const char *PreCode = R"( +#include "clang_tidy/tests/insert_includes_test_header.h" + +#include +#include +#include + +#include "a/header.h" +#include "path/to/a/header.h" +#include "path/to/header.h" + +void foo() { + int a = 0; +})"; + + const char *PostCode = R"( +#include "clang_tidy/tests/insert_includes_test_header.h" + +#include +#include +#include + +#include "a/header.h" +#include "path/to/a/header.h" +#include "path/to/header.h" + +void foo() { + int a = 0; +})"; + + EXPECT_EQ(PostCode, runCheckOnCode( + PreCode, "workspace_folder/clang_tidy/tests/" + "insert_includes_test_header.cc")); +} + +TEST(IncludeInserterTest, HandleOrderInSubdirectory) { + const char *PreCode = R"( +#include "clang_tidy/tests/insert_includes_test_header.h" + +#include +#include +#include + +#include "path/to/a/header.h" +#include "path/to/header.h" + +void foo() { + int a = 0; +})"; + + const char *PostCode = R"( +#include "clang_tidy/tests/insert_includes_test_header.h" + +#include +#include +#include + +#include "a/header.h" +#include "path/to/a/header.h" +#include "path/to/header.h" + +void foo() { + int a = 0; +})"; + + EXPECT_EQ(PostCode, runCheckOnCode( + PreCode, "workspace_folder/clang_tidy/tests/" + "insert_includes_test_header.cc")); +} + } // anonymous namespace } // namespace tidy } // namespace clang