[clang-tools-extra] fae01d1 - [clangd] Fix bugs in main-file include patching for stale preambles
Kadir Cetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 13 00:49:41 PST 2023
Author: Kadir Cetinkaya
Date: 2023-02-13T09:49:13+01:00
New Revision: fae01d175a29270ec01211d3988c7ae57ddabfd3
URL: https://github.com/llvm/llvm-project/commit/fae01d175a29270ec01211d3988c7ae57ddabfd3
DIFF: https://github.com/llvm/llvm-project/commit/fae01d175a29270ec01211d3988c7ae57ddabfd3.diff
LOG: [clangd] Fix bugs in main-file include patching for stale preambles
- Make sure main file includes are present even when they're not patched
(because they didn't change or we're explicitly not patching them).
- Populate extra fields for includes, which can be used by include-cleaner.
Differential Revision: https://reviews.llvm.org/D143197
Added:
Modified:
clang-tools-extra/clangd/Preamble.cpp
clang-tools-extra/clangd/unittests/PreambleTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp
index 15eea9bb036bd..cdb8db14722d2 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -671,10 +671,10 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
// We are only interested in newly added includes, record the ones in
// Baseline for exclusion.
llvm::DenseMap<std::pair<tok::PPKeywordKind, llvm::StringRef>,
- /*Resolved=*/llvm::StringRef>
+ const Inclusion *>
ExistingIncludes;
for (const auto &Inc : Baseline.Includes.MainFileIncludes)
- ExistingIncludes[{Inc.Directive, Inc.Written}] = Inc.Resolved;
+ ExistingIncludes[{Inc.Directive, Inc.Written}] = &Inc;
// There might be includes coming from disabled regions, record these for
// exclusion too. note that we don't have resolved paths for those.
for (const auto &Inc : BaselineScan->Includes)
@@ -685,8 +685,13 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
// Include already present in the baseline preamble. Set resolved path and
// put into preamble includes.
if (It != ExistingIncludes.end()) {
- Inc.Resolved = It->second.str();
- PP.PreambleIncludes.push_back(Inc);
+ auto &PatchedInc = PP.PreambleIncludes.emplace_back();
+ // Copy everything from existing include, apart from the location, when
+ // it's coming from baseline preamble.
+ if (It->second)
+ PatchedInc = *It->second;
+ PatchedInc.HashLine = Inc.HashLine;
+ PatchedInc.HashOffset = Inc.HashOffset;
continue;
}
// Include is new in the modified preamble. Inject it into the patch and
@@ -696,6 +701,11 @@ PreamblePatch PreamblePatch::create(llvm::StringRef FileName,
Patch << llvm::formatv(
"#{0} {1}\n", spellingForIncDirective(Inc.Directive), Inc.Written);
}
+ } else {
+ // Make sure we have the full set of includes available even when we're not
+ // patching. As these are used by features we provide afterwards like hover,
+ // go-to-def or include-cleaner when preamble is stale.
+ PP.PreambleIncludes = Baseline.Includes.MainFileIncludes;
}
if (DirectivesChanged) {
diff --git a/clang-tools-extra/clangd/unittests/PreambleTests.cpp b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
index 1e95b62884f69..ac46bfd06a138 100644
--- a/clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -15,6 +15,7 @@
#include "TestFS.h"
#include "TestTU.h"
#include "XRefs.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/PrecompiledPreamble.h"
@@ -23,6 +24,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "gmock/gmock.h"
+#include "gtest/gtest-matchers.h"
#include "gtest/gtest.h"
#include <memory>
#include <optional>
@@ -166,7 +168,7 @@ TEST(PreamblePatchTest, PatchesPreambleIncludes) {
MockFS FS;
IgnoreDiagnostics Diags;
auto TU = TestTU::withCode(R"cpp(
- #include "a.h"
+ #include "a.h" // IWYU pragma: keep
#include "c.h"
)cpp");
TU.AdditionalFiles["a.h"] = "#include \"b.h\"";
@@ -185,9 +187,14 @@ TEST(PreamblePatchTest, PatchesPreambleIncludes) {
*BaselinePreamble);
// Only a.h should exists in the preamble, as c.h has been dropped and b.h was
// newly introduced.
- EXPECT_THAT(PP.preambleIncludes(),
- ElementsAre(AllOf(Field(&Inclusion::Written, "\"a.h\""),
- Field(&Inclusion::Resolved, testPath("a.h")))));
+ EXPECT_THAT(
+ PP.preambleIncludes(),
+ ElementsAre(AllOf(
+ Field(&Inclusion::Written, "\"a.h\""),
+ Field(&Inclusion::Resolved, testPath("a.h")),
+ Field(&Inclusion::HeaderID, testing::Not(testing::Eq(std::nullopt))),
+ Field(&Inclusion::BehindPragmaKeep, true),
+ Field(&Inclusion::FileKind, SrcMgr::CharacteristicKind::C_User))));
}
std::optional<ParsedAST> createPatchedAST(llvm::StringRef Baseline,
@@ -225,6 +232,26 @@ std::string getPreamblePatch(llvm::StringRef Baseline,
.str();
}
+TEST(PreamblePatchTest, IncludesArePreserved) {
+ llvm::StringLiteral Baseline = R"(//error-ok
+#include <foo>
+#include <bar>
+)";
+ llvm::StringLiteral Modified = R"(//error-ok
+#include <foo>
+#include <bar>
+#define FOO)";
+
+ auto Includes = createPatchedAST(Baseline, Modified.str())
+ ->getIncludeStructure()
+ .MainFileIncludes;
+ EXPECT_TRUE(!Includes.empty());
+ EXPECT_EQ(Includes, TestTU::withCode(Baseline)
+ .build()
+ .getIncludeStructure()
+ .MainFileIncludes);
+}
+
TEST(PreamblePatchTest, Define) {
// BAR should be defined while parsing the AST.
struct {
More information about the cfe-commits
mailing list