From ba3ea9c60f0f259f0ccc47e47daf8253a5885531 Mon Sep 17 00:00:00 2001 From: Nathan James Date: Fri, 12 Feb 2021 16:55:44 +0000 Subject: [PATCH] [clangd] Fix clang tidy provider when multiple config files exist in directory tree Currently Clang tidy provider searches from the root directory up to the target directory, this is the opposite of how clang-tidy searches for config files. The result of this is .clang-tidy files are ignored in any subdirectory of a directory containing a .clang-tidy file. Reviewed By: sammccall Differential Revision: https://reviews.llvm.org/D96204 --- clang-tools-extra/clangd/TidyProvider.cpp | 2 +- clang-tools-extra/clangd/unittests/CMakeLists.txt | 1 + .../clangd/unittests/TidyProviderTests.cpp | 60 ++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 clang-tools-extra/clangd/unittests/TidyProviderTests.cpp diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp index c26c59f..bcf1cd5 100644 --- a/clang-tools-extra/clangd/TidyProvider.cpp +++ b/clang-tools-extra/clangd/TidyProvider.cpp @@ -106,7 +106,7 @@ public: llvm::SmallVector Caches; { std::lock_guard Lock(Mu); - for (auto I = path::begin(Parent), E = path::end(Parent); I != E; ++I) { + for (auto I = path::rbegin(Parent), E = path::rend(Parent); I != E; ++I) { assert(I->end() >= Parent.begin() && I->end() <= Parent.end() && "Canonical path components should be substrings"); llvm::StringRef Ancestor(Parent.begin(), I->end() - Parent.begin()); diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index adf4ac8..f4d36472 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -93,6 +93,7 @@ add_unittest(ClangdUnitTests ClangdTests TestIndex.cpp TestTU.cpp TestWorkspace.cpp + TidyProviderTests.cpp TypeHierarchyTests.cpp URITests.cpp XRefsTests.cpp diff --git a/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp b/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp new file mode 100644 index 0000000..a16c874 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp @@ -0,0 +1,60 @@ +//===-- TidyProviderTests.cpp - Clang tidy configuration provider tests ---===// +// +// 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 "TestFS.h" +#include "TidyProvider.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { + +namespace { + +TEST(TidyProvider, NestedDirectories) { + MockFS FS; + FS.Files[testPath(".clang-tidy")] = R"yaml( + Checks: 'llvm-*' + CheckOptions: + - key: TestKey + value: 1 +)yaml"; + FS.Files[testPath("sub1/.clang-tidy")] = R"yaml( + Checks: 'misc-*' + CheckOptions: + - key: TestKey + value: 2 +)yaml"; + FS.Files[testPath("sub1/sub2/.clang-tidy")] = R"yaml( + Checks: 'bugprone-*' + CheckOptions: + - key: TestKey + value: 3 + InheritParentConfig: true +)yaml"; + + TidyProvider Provider = provideClangTidyFiles(FS); + + auto BaseOptions = getTidyOptionsForFile(Provider, testPath("File.cpp")); + ASSERT_TRUE(BaseOptions.Checks.hasValue()); + EXPECT_EQ(*BaseOptions.Checks, "llvm-*"); + EXPECT_EQ(BaseOptions.CheckOptions.lookup("TestKey").Value, "1"); + + auto Sub1Options = getTidyOptionsForFile(Provider, testPath("sub1/File.cpp")); + ASSERT_TRUE(Sub1Options.Checks.hasValue()); + EXPECT_EQ(*Sub1Options.Checks, "misc-*"); + EXPECT_EQ(Sub1Options.CheckOptions.lookup("TestKey").Value, "2"); + + auto Sub2Options = + getTidyOptionsForFile(Provider, testPath("sub1/sub2/File.cpp")); + ASSERT_TRUE(Sub2Options.Checks.hasValue()); + EXPECT_EQ(*Sub2Options.Checks, "misc-*,bugprone-*"); + EXPECT_EQ(Sub2Options.CheckOptions.lookup("TestKey").Value, "3"); +} +} // namespace +} // namespace clangd +} // namespace clang -- 2.7.4