[clang-tools-extra] dea4807 - [clangd] Land D110386 again
Kirill Bobyrev via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 30 05:42:39 PDT 2021
Author: Kirill Bobyrev
Date: 2021-09-30T14:41:27+02:00
New Revision: dea48079b90d40f2087435b778544dffb0ab1793
URL: https://github.com/llvm/llvm-project/commit/dea48079b90d40f2087435b778544dffb0ab1793
DIFF: https://github.com/llvm/llvm-project/commit/dea48079b90d40f2087435b778544dffb0ab1793.diff
LOG: [clangd] Land D110386 again
This time, use llvm::sys::fs::UniqueID instead of unstable
FileEntry::getName(), this should solve the problems on Windows and
elsewhere.
Added:
Modified:
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/Headers.cpp
clang-tools-extra/clangd/Headers.h
clang-tools-extra/clangd/unittests/HeadersTests.cpp
clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 69338814ebdd2..512959316e18e 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1379,14 +1379,17 @@ class CodeCompleteFlow {
FileDistanceOptions ProxOpts{}; // Use defaults.
const auto &SM = Recorder->CCSema->getSourceManager();
llvm::StringMap<SourceParams> ProxSources;
- for (auto &Entry : Includes.includeDepth(
- SM.getFileEntryForID(SM.getMainFileID())->getName())) {
- auto &Source = ProxSources[Entry.getKey()];
- Source.Cost = Entry.getValue() * ProxOpts.IncludeCost;
+ auto MainFileID =
+ Includes.getID(SM.getFileEntryForID(SM.getMainFileID()), SM);
+ assert(MainFileID);
+ for (auto &HeaderIDAndDepth : Includes.includeDepth(*MainFileID)) {
+ auto &Source =
+ ProxSources[Includes.getRealPath(HeaderIDAndDepth.getFirst())];
+ Source.Cost = HeaderIDAndDepth.getSecond() * ProxOpts.IncludeCost;
// Symbols near our transitive includes are good, but only consider
// things in the same directory or below it. Otherwise there can be
// many false positives.
- if (Entry.getValue() > 0)
+ if (HeaderIDAndDepth.getSecond() > 0)
Source.MaxUpTraversals = 1;
}
FileProximity.emplace(ProxSources, ProxOpts);
diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp
index 111b05849b81b..ea07e050e9383 100644
--- a/clang-tools-extra/clangd/Headers.cpp
+++ b/clang-tools-extra/clangd/Headers.cpp
@@ -67,8 +67,9 @@ class RecordHeaders : public PPCallbacks {
// Treat as if included from the main file.
IncludingFileEntry = SM.getFileEntryForID(MainFID);
}
- Out->recordInclude(IncludingFileEntry->getName(), File->getName(),
- File->tryGetRealPathName());
+ auto IncludingID = Out->getOrCreateID(IncludingFileEntry, SM),
+ IncludedID = Out->getOrCreateID(File, SM);
+ Out->IncludeChildren[IncludingID].push_back(IncludedID);
}
}
@@ -154,38 +155,52 @@ collectIncludeStructureCallback(const SourceManager &SM,
return std::make_unique<RecordHeaders>(SM, Out);
}
-void IncludeStructure::recordInclude(llvm::StringRef IncludingName,
- llvm::StringRef IncludedName,
- llvm::StringRef IncludedRealName) {
- auto Child = fileIndex(IncludedName);
- if (!IncludedRealName.empty() && RealPathNames[Child].empty())
- RealPathNames[Child] = std::string(IncludedRealName);
- auto Parent = fileIndex(IncludingName);
- IncludeChildren[Parent].push_back(Child);
+llvm::Optional<IncludeStructure::HeaderID>
+IncludeStructure::getID(const FileEntry *Entry,
+ const SourceManager &SM) const {
+ // HeaderID of the main file is always 0;
+ if (SM.getMainFileID() == SM.translateFile(Entry)) {
+ return static_cast<IncludeStructure::HeaderID>(0u);
+ }
+ auto It = UIDToIndex.find(Entry->getUniqueID());
+ if (It == UIDToIndex.end())
+ return llvm::None;
+ return It->second;
}
-unsigned IncludeStructure::fileIndex(llvm::StringRef Name) {
- auto R = NameToIndex.try_emplace(Name, RealPathNames.size());
+IncludeStructure::HeaderID
+IncludeStructure::getOrCreateID(const FileEntry *Entry,
+ const SourceManager &SM) {
+ // Main file's FileID was not known at IncludeStructure creation time.
+ if (SM.getMainFileID() == SM.translateFile(Entry)) {
+ UIDToIndex[Entry->getUniqueID()] =
+ static_cast<IncludeStructure::HeaderID>(0u);
+ }
+ auto R = UIDToIndex.try_emplace(
+ Entry->getUniqueID(),
+ static_cast<IncludeStructure::HeaderID>(RealPathNames.size()));
if (R.second)
RealPathNames.emplace_back();
- return R.first->getValue();
+ IncludeStructure::HeaderID Result = R.first->getSecond();
+ std::string &RealPathName = RealPathNames[static_cast<unsigned>(Result)];
+ if (RealPathName.empty())
+ RealPathName = Entry->tryGetRealPathName().str();
+ return Result;
}
-llvm::StringMap<unsigned>
-IncludeStructure::includeDepth(llvm::StringRef Root) const {
+llvm::DenseMap<IncludeStructure::HeaderID, unsigned>
+IncludeStructure::includeDepth(HeaderID Root) const {
// Include depth 0 is the main file only.
- llvm::StringMap<unsigned> Result;
+ llvm::DenseMap<HeaderID, unsigned> Result;
+ assert(static_cast<unsigned>(Root) < RealPathNames.size());
Result[Root] = 0;
- std::vector<unsigned> CurrentLevel;
- llvm::DenseSet<unsigned> Seen;
- auto It = NameToIndex.find(Root);
- if (It != NameToIndex.end()) {
- CurrentLevel.push_back(It->second);
- Seen.insert(It->second);
- }
+ std::vector<IncludeStructure::HeaderID> CurrentLevel;
+ CurrentLevel.push_back(Root);
+ llvm::DenseSet<IncludeStructure::HeaderID> Seen;
+ Seen.insert(Root);
// Each round of BFS traversal finds the next depth level.
- std::vector<unsigned> PreviousLevel;
+ std::vector<IncludeStructure::HeaderID> PreviousLevel;
for (unsigned Level = 1; !CurrentLevel.empty(); ++Level) {
PreviousLevel.clear();
PreviousLevel.swap(CurrentLevel);
@@ -193,10 +208,7 @@ IncludeStructure::includeDepth(llvm::StringRef Root) const {
for (const auto &Child : IncludeChildren.lookup(Parent)) {
if (Seen.insert(Child).second) {
CurrentLevel.push_back(Child);
- const auto &Name = RealPathNames[Child];
- // Can't include files if we don't have their real path.
- if (!Name.empty())
- Result[Name] = Level;
+ Result[Child] = Level;
}
}
}
diff --git a/clang-tools-extra/clangd/Headers.h b/clang-tools-extra/clangd/Headers.h
index f4ca364880c41..fa24d43e9bff1 100644
--- a/clang-tools-extra/clangd/Headers.h
+++ b/clang-tools-extra/clangd/Headers.h
@@ -12,6 +12,7 @@
#include "Protocol.h"
#include "SourceCode.h"
#include "index/Symbol.h"
+#include "support/Logger.h"
#include "support/Path.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Format/Format.h"
@@ -22,6 +23,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem/UniqueID.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <string>
@@ -62,7 +64,7 @@ struct Inclusion {
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Inclusion &);
bool operator==(const Inclusion &LHS, const Inclusion &RHS);
-// Contains information about one file in the build grpah and its direct
+// Contains information about one file in the build graph and its direct
// dependencies. Doesn't own the strings it references (IncludeGraph is
// self-contained).
struct IncludeGraphNode {
@@ -112,7 +114,25 @@ operator|=(IncludeGraphNode::SourceFlag &A, IncludeGraphNode::SourceFlag B) {
// in any non-preamble inclusions.
class IncludeStructure {
public:
- std::vector<Inclusion> MainFileIncludes;
+ IncludeStructure() {
+ // Reserve HeaderID = 0 for the main file.
+ RealPathNames.emplace_back();
+ }
+
+ // HeaderID identifies file in the include graph. It corresponds to a
+ // FileEntry rather than a FileID, but stays stable across preamble & main
+ // file builds.
+ enum class HeaderID : unsigned {};
+
+ llvm::Optional<HeaderID> getID(const FileEntry *Entry,
+ const SourceManager &SM) const;
+ HeaderID getOrCreateID(const FileEntry *Entry,
+ const SourceManager &SM);
+
+ StringRef getRealPath(HeaderID ID) const {
+ assert(static_cast<unsigned>(ID) <= RealPathNames.size());
+ return RealPathNames[static_cast<unsigned>(ID)];
+ }
// Return all transitively reachable files.
llvm::ArrayRef<std::string> allHeaders() const { return RealPathNames; }
@@ -120,26 +140,27 @@ class IncludeStructure {
// Return all transitively reachable files, and their minimum include depth.
// All transitive includes (absolute paths), with their minimum include depth.
// Root --> 0, #included file --> 1, etc.
- // Root is clang's name for a file, which may not be absolute.
- // Usually it should be SM.getFileEntryForID(SM.getMainFileID())->getName().
- llvm::StringMap<unsigned> includeDepth(llvm::StringRef Root) const;
+ // Root is the ID of the header being visited first.
+ // Usually it is getID(SM.getFileEntryForID(SM.getMainFileID())->getName()).
+ llvm::DenseMap<HeaderID, unsigned> includeDepth(HeaderID Root) const;
- // This updates IncludeDepth(), but not MainFileIncludes.
- void recordInclude(llvm::StringRef IncludingName,
- llvm::StringRef IncludedName,
- llvm::StringRef IncludedRealName);
+ // Maps HeaderID to the ids of the files included from it.
+ llvm::DenseMap<HeaderID, SmallVector<HeaderID>> IncludeChildren;
+
+ std::vector<Inclusion> MainFileIncludes;
private:
+ std::vector<std::string> RealPathNames; // In HeaderID order.
+ // HeaderID maps the FileEntry::UniqueID to the internal representation.
// Identifying files in a way that persists from preamble build to subsequent
- // builds is surprisingly hard. FileID is unavailable in InclusionDirective(),
- // and RealPathName and UniqueID are not preserved in the preamble.
- // We use the FileEntry::Name, which is stable, interned into a "file index".
- // The paths we want to expose are the RealPathName, so store those too.
- std::vector<std::string> RealPathNames; // In file index order.
- unsigned fileIndex(llvm::StringRef Name);
- llvm::StringMap<unsigned> NameToIndex; // Values are file indexes.
- // Maps a file's index to that of the files it includes.
- llvm::DenseMap<unsigned, llvm::SmallVector<unsigned>> IncludeChildren;
+ // builds is surprisingly hard. FileID is unavailable in
+ // InclusionDirective(), and RealPathName and UniqueID are not preserved in
+ // the preamble.
+ //
+ // We reserve 0 to the main file and will manually check for that in getID
+ // and getOrCreateID because llvm::sys::fs::UniqueID is not stable when their
+ // content of the main file changes.
+ llvm::DenseMap<llvm::sys::fs::UniqueID, HeaderID> UIDToIndex;
};
/// Returns a PPCallback that visits all inclusions in the main file.
@@ -205,4 +226,55 @@ class IncludeInserter {
} // namespace clangd
} // namespace clang
+namespace llvm {
+
+// Support Tokens as DenseMap keys.
+template <> struct DenseMapInfo<clang::clangd::IncludeStructure::HeaderID> {
+ static inline clang::clangd::IncludeStructure::HeaderID getEmptyKey() {
+ return static_cast<clang::clangd::IncludeStructure::HeaderID>(
+ DenseMapInfo<unsigned>::getEmptyKey());
+ }
+
+ static inline clang::clangd::IncludeStructure::HeaderID getTombstoneKey() {
+ return static_cast<clang::clangd::IncludeStructure::HeaderID>(
+ DenseMapInfo<unsigned>::getTombstoneKey());
+ }
+
+ static unsigned
+ getHashValue(const clang::clangd::IncludeStructure::HeaderID &Tag) {
+ return hash_value(static_cast<unsigned>(Tag));
+ }
+
+ static bool isEqual(const clang::clangd::IncludeStructure::HeaderID &LHS,
+ const clang::clangd::IncludeStructure::HeaderID &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Support Tokens as DenseMap keys.
+template <> struct DenseMapInfo<llvm::sys::fs::UniqueID> {
+ static inline llvm::sys::fs::UniqueID getEmptyKey() {
+ auto EmptyKey = DenseMapInfo<std::pair<unsigned, unsigned>>::getEmptyKey();
+ return {EmptyKey.first, EmptyKey.second};
+ }
+
+ static inline llvm::sys::fs::UniqueID getTombstoneKey() {
+ auto TombstoneKey =
+ DenseMapInfo<std::pair<unsigned, unsigned>>::getTombstoneKey();
+ return {TombstoneKey.first, TombstoneKey.second};
+ }
+
+ static unsigned getHashValue(const llvm::sys::fs::UniqueID &Tag) {
+ return hash_value(
+ std::pair<unsigned, unsigned>(Tag.getDevice(), Tag.getFile()));
+ }
+
+ static bool isEqual(const llvm::sys::fs::UniqueID &LHS,
+ const llvm::sys::fs::UniqueID &RHS) {
+ return LHS == RHS;
+ }
+};
+
+} // namespace llvm
+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H
diff --git a/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
index 13babb89a3ee3..bee3d181cf80d 100644
--- a/clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -17,6 +17,7 @@
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "gmock/gmock.h"
@@ -29,8 +30,10 @@ namespace {
using ::testing::AllOf;
using ::testing::Contains;
using ::testing::ElementsAre;
+using ::testing::IsEmpty;
using ::testing::Not;
using ::testing::UnorderedElementsAre;
+using ::testing::UnorderedElementsAreArray;
class HeadersTest : public ::testing::Test {
public:
@@ -64,8 +67,16 @@ class HeadersTest : public ::testing::Test {
}
protected:
+ IncludeStructure::HeaderID getID(StringRef Filename,
+ IncludeStructure &Includes) {
+ auto &SM = Clang->getSourceManager();
+ auto Entry = SM.getFileManager().getFile(Filename);
+ EXPECT_TRUE(Entry);
+ return Includes.getOrCreateID(*Entry, SM);
+ }
+
IncludeStructure collectIncludes() {
- auto Clang = setupClang();
+ Clang = setupClang();
PreprocessOnlyAction Action;
EXPECT_TRUE(
Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]));
@@ -81,7 +92,7 @@ class HeadersTest : public ::testing::Test {
// inserted.
std::string calculate(PathRef Original, PathRef Preferred = "",
const std::vector<Inclusion> &Inclusions = {}) {
- auto Clang = setupClang();
+ Clang = setupClang();
PreprocessOnlyAction Action;
EXPECT_TRUE(
Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]));
@@ -107,7 +118,7 @@ class HeadersTest : public ::testing::Test {
}
llvm::Optional<TextEdit> insert(llvm::StringRef VerbatimHeader) {
- auto Clang = setupClang();
+ Clang = setupClang();
PreprocessOnlyAction Action;
EXPECT_TRUE(
Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]));
@@ -126,6 +137,7 @@ class HeadersTest : public ::testing::Test {
std::string Subdir = testPath("sub");
std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str();
IgnoringDiagConsumer IgnoreDiags;
+ std::unique_ptr<CompilerInstance> Clang;
};
MATCHER_P(Written, Name, "") { return arg.Written == Name; }
@@ -134,11 +146,11 @@ MATCHER_P(IncludeLine, N, "") { return arg.HashLine == N; }
MATCHER_P(Directive, D, "") { return arg.Directive == D; }
MATCHER_P2(Distance, File, D, "") {
- if (arg.getKey() != File)
- *result_listener << "file =" << arg.getKey().str();
- if (arg.getValue() != D)
- *result_listener << "distance =" << arg.getValue();
- return arg.getKey() == File && arg.getValue() == D;
+ if (arg.getFirst() != File)
+ *result_listener << "file =" << static_cast<unsigned>(arg.getFirst());
+ if (arg.getSecond() != D)
+ *result_listener << "distance =" << arg.getSecond();
+ return arg.getFirst() == File && arg.getSecond() == D;
}
TEST_F(HeadersTest, CollectRewrittenAndResolved) {
@@ -148,12 +160,13 @@ TEST_F(HeadersTest, CollectRewrittenAndResolved) {
std::string BarHeader = testPath("sub/bar.h");
FS.Files[BarHeader] = "";
- EXPECT_THAT(collectIncludes().MainFileIncludes,
+ auto Includes = collectIncludes();
+ EXPECT_THAT(Includes.MainFileIncludes,
UnorderedElementsAre(
AllOf(Written("\"sub/bar.h\""), Resolved(BarHeader))));
- EXPECT_THAT(collectIncludes().includeDepth(MainFile),
- UnorderedElementsAre(Distance(MainFile, 0u),
- Distance(testPath("sub/bar.h"), 1u)));
+ EXPECT_THAT(Includes.includeDepth(getID(MainFile, Includes)),
+ UnorderedElementsAre(Distance(getID(MainFile, Includes), 0u),
+ Distance(getID(BarHeader, Includes), 1u)));
}
TEST_F(HeadersTest, OnlyCollectInclusionsInMain) {
@@ -166,17 +179,18 @@ TEST_F(HeadersTest, OnlyCollectInclusionsInMain) {
FS.Files[MainFile] = R"cpp(
#include "bar.h"
)cpp";
- EXPECT_THAT(
- collectIncludes().MainFileIncludes,
- UnorderedElementsAre(AllOf(Written("\"bar.h\""), Resolved(BarHeader))));
- EXPECT_THAT(collectIncludes().includeDepth(MainFile),
- UnorderedElementsAre(Distance(MainFile, 0u),
- Distance(testPath("sub/bar.h"), 1u),
- Distance(testPath("sub/baz.h"), 2u)));
+ auto Includes = collectIncludes();
+ EXPECT_THAT(Includes.MainFileIncludes,
+ UnorderedElementsAre(
+ AllOf(Written("\"bar.h\""), Resolved(BarHeader))));
+ EXPECT_THAT(Includes.includeDepth(getID(MainFile, Includes)),
+ UnorderedElementsAre(Distance(getID(MainFile, Includes), 0u),
+ Distance(getID(BarHeader, Includes), 1u),
+ Distance(getID(BazHeader, Includes), 2u)));
// includeDepth() also works for non-main files.
- EXPECT_THAT(collectIncludes().includeDepth(testPath("sub/bar.h")),
- UnorderedElementsAre(Distance(testPath("sub/bar.h"), 0u),
- Distance(testPath("sub/baz.h"), 1u)));
+ EXPECT_THAT(Includes.includeDepth(getID(BarHeader, Includes)),
+ UnorderedElementsAre(Distance(getID(BarHeader, Includes), 0u),
+ Distance(getID(BazHeader, Includes), 1u)));
}
TEST_F(HeadersTest, PreambleIncludesPresentOnce) {
@@ -202,8 +216,32 @@ TEST_F(HeadersTest, UnResolvedInclusion) {
EXPECT_THAT(collectIncludes().MainFileIncludes,
UnorderedElementsAre(AllOf(Written("\"foo.h\""), Resolved(""))));
- EXPECT_THAT(collectIncludes().includeDepth(MainFile),
- UnorderedElementsAre(Distance(MainFile, 0u)));
+ EXPECT_THAT(collectIncludes().IncludeChildren, IsEmpty());
+}
+
+TEST_F(HeadersTest, IncludedFilesGraph) {
+ FS.Files[MainFile] = R"cpp(
+#include "bar.h"
+#include "foo.h"
+)cpp";
+ std::string BarHeader = testPath("bar.h");
+ FS.Files[BarHeader] = "";
+ std::string FooHeader = testPath("foo.h");
+ FS.Files[FooHeader] = R"cpp(
+#include "bar.h"
+#include "baz.h"
+)cpp";
+ std::string BazHeader = testPath("baz.h");
+ FS.Files[BazHeader] = "";
+
+ auto Includes = collectIncludes();
+ llvm::DenseMap<IncludeStructure::HeaderID,
+ SmallVector<IncludeStructure::HeaderID>>
+ Expected = {{getID(MainFile, Includes),
+ {getID(BarHeader, Includes), getID(FooHeader, Includes)}},
+ {getID(FooHeader, Includes),
+ {getID(BarHeader, Includes), getID(BazHeader, Includes)}}};
+ EXPECT_EQ(Includes.IncludeChildren, Expected);
}
TEST_F(HeadersTest, IncludeDirective) {
diff --git a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
index 7288acbcd4697..67cd18ab01157 100644
--- a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -44,9 +44,11 @@ namespace clangd {
namespace {
using ::testing::AllOf;
+using ::testing::Contains;
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::IsEmpty;
+using ::testing::UnorderedElementsAreArray;
MATCHER_P(DeclNamed, Name, "") {
if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
@@ -493,7 +495,7 @@ TEST(ParsedASTTest, PatchesAdditionalIncludes) {
auto EmptyPreamble =
buildPreamble(testPath("foo.cpp"), *CI, Inputs, true, nullptr);
ASSERT_TRUE(EmptyPreamble);
- EXPECT_THAT(EmptyPreamble->Includes.MainFileIncludes, testing::IsEmpty());
+ EXPECT_THAT(EmptyPreamble->Includes.MainFileIncludes, IsEmpty());
// Now build an AST using empty preamble and ensure patched includes worked.
TU.Code = ModifiedContents.str();
@@ -507,18 +509,18 @@ TEST(ParsedASTTest, PatchesAdditionalIncludes) {
EXPECT_THAT(PatchedAST->getIncludeStructure().MainFileIncludes,
testing::Pointwise(
EqInc(), ExpectedAST.getIncludeStructure().MainFileIncludes));
- auto StringMapToVector = [](const llvm::StringMap<unsigned> SM) {
- std::vector<std::pair<std::string, unsigned>> Res;
- for (const auto &E : SM)
- Res.push_back({E.first().str(), E.second});
- llvm::sort(Res);
- return Res;
- };
// Ensure file proximity signals are correct.
- EXPECT_EQ(StringMapToVector(PatchedAST->getIncludeStructure().includeDepth(
- testPath("foo.cpp"))),
- StringMapToVector(ExpectedAST.getIncludeStructure().includeDepth(
- testPath("foo.cpp"))));
+ auto &SM = PatchedAST->getSourceManager();
+ auto &FM = SM.getFileManager();
+ // Copy so that we can use operator[] to get the children.
+ IncludeStructure Includes = PatchedAST->getIncludeStructure();
+ auto MainFE = FM.getFile(testPath("foo.cpp"));
+ ASSERT_TRUE(MainFE);
+ auto MainID = Includes.getID(*MainFE, SM);
+ auto AuxFE = FM.getFile(testPath("sub/aux.h"));
+ ASSERT_TRUE(AuxFE);
+ auto AuxID = Includes.getID(*AuxFE, SM);
+ EXPECT_THAT(Includes.IncludeChildren[*MainID], Contains(*AuxID));
}
TEST(ParsedASTTest, PatchesDeletedIncludes) {
@@ -551,18 +553,21 @@ TEST(ParsedASTTest, PatchesDeletedIncludes) {
EXPECT_THAT(PatchedAST->getIncludeStructure().MainFileIncludes,
testing::Pointwise(
EqInc(), ExpectedAST.getIncludeStructure().MainFileIncludes));
- auto StringMapToVector = [](const llvm::StringMap<unsigned> SM) {
- std::vector<std::pair<std::string, unsigned>> Res;
- for (const auto &E : SM)
- Res.push_back({E.first().str(), E.second});
- llvm::sort(Res);
- return Res;
- };
// Ensure file proximity signals are correct.
- EXPECT_EQ(StringMapToVector(PatchedAST->getIncludeStructure().includeDepth(
- testPath("foo.cpp"))),
- StringMapToVector(ExpectedAST.getIncludeStructure().includeDepth(
- testPath("foo.cpp"))));
+ auto &SM = ExpectedAST.getSourceManager();
+ auto &FM = SM.getFileManager();
+ // Copy so that we can getOrCreateID().
+ IncludeStructure Includes = ExpectedAST.getIncludeStructure();
+ auto MainFE = FM.getFile(testPath("foo.cpp"));
+ ASSERT_TRUE(MainFE);
+ auto MainID = Includes.getOrCreateID(*MainFE, SM);
+ auto &PatchedFM = PatchedAST->getSourceManager().getFileManager();
+ IncludeStructure PatchedIncludes = PatchedAST->getIncludeStructure();
+ auto PatchedMainFE = PatchedFM.getFile(testPath("foo.cpp"));
+ ASSERT_TRUE(PatchedMainFE);
+ auto PatchedMainID = PatchedIncludes.getOrCreateID(*PatchedMainFE, SM);
+ EXPECT_EQ(Includes.includeDepth(MainID)[MainID],
+ PatchedIncludes.includeDepth(PatchedMainID)[PatchedMainID]);
}
// Returns Code guarded by #ifndef guards
More information about the cfe-commits
mailing list