sammccall created this revision.
sammccall added reviewers: ilya-biryukov, klimek.
Herald added subscribers: cfe-commits, kadircet, ioeric.
Herald added a project: clang.
Use cases:
- a tool that dumps the heuristic used for each header in a project can be used
to evaluate changes to the heuristic
- we want to expose this information to users in clangd as it affects
accuracy/reliability of editor features
- express interpolation tests more directly
Repository:
rC Clang
https://reviews.llvm.org/D60194
Files:
include/clang/Tooling/CompilationDatabase.h
lib/Tooling/InterpolatingCompilationDatabase.cpp
unittests/Tooling/CompilationDatabaseTest.cpp
Index: unittests/Tooling/CompilationDatabaseTest.cpp
===================================================================
--- unittests/Tooling/CompilationDatabaseTest.cpp
+++ unittests/Tooling/CompilationDatabaseTest.cpp
@@ -673,6 +673,27 @@
return llvm::join(Results[0].CommandLine, " ");
}
+ // Parse the file whose command was used out of the Heuristic string.
+ std::string getProxy(llvm::StringRef F) {
+ auto Results =
+ inferMissingCompileCommands(llvm::make_unique<MemCDB>(Entries))
+ ->getCompileCommands(path(F));
+ if (Results.empty())
+ return "none";
+ StringRef Proxy = Results.front().Heuristic;
+ if (!Proxy.consume_front("inferred from "))
+ return "";
+ // We have a proxy file, convert back to a unix relative path.
+ // This is a bit messy, but we do need to test these strings somehow...
+ llvm::SmallString<32> TempDir;
+ llvm::sys::path::system_temp_directory(false, TempDir);
+ Proxy.consume_front(TempDir);
+ Proxy.consume_front(llvm::sys::path::get_separator());
+ llvm::SmallString<32> Result = Proxy;
+ llvm::sys::path::native(Result, llvm::sys::path::Style::posix);
+ return Result.str();
+ }
+
MemCDB::EntryMap Entries;
};
@@ -682,18 +703,16 @@
add("an/other/foo.cpp");
// great: dir and name both match (prefix or full, case insensitive)
- EXPECT_EQ(getCommand("dir/f.cpp"), "clang -D dir/foo.cpp");
- EXPECT_EQ(getCommand("dir/FOO.cpp"), "clang -D dir/foo.cpp");
+ EXPECT_EQ(getProxy("dir/f.cpp"), "dir/foo.cpp");
+ EXPECT_EQ(getProxy("dir/FOO.cpp"), "dir/foo.cpp");
// no name match. prefer matching dir, break ties by alpha
- EXPECT_EQ(getCommand("dir/a.cpp"), "clang -D dir/bar.cpp");
+ EXPECT_EQ(getProxy("dir/a.cpp"), "dir/bar.cpp");
// an exact name match beats one segment of directory match
- EXPECT_EQ(getCommand("some/other/bar.h"),
- "clang -D dir/bar.cpp -x c++-header");
+ EXPECT_EQ(getProxy("some/other/bar.h"), "dir/bar.cpp");
// two segments of directory match beat a prefix name match
- EXPECT_EQ(getCommand("an/other/b.cpp"), "clang -D an/other/foo.cpp");
+ EXPECT_EQ(getProxy("an/other/b.cpp"), "an/other/foo.cpp");
// if nothing matches at all, we still get the closest alpha match
- EXPECT_EQ(getCommand("below/some/obscure/path.cpp"),
- "clang -D an/other/foo.cpp");
+ EXPECT_EQ(getProxy("below/some/obscure/path.cpp"), "an/other/foo.cpp");
}
TEST_F(InterpolateTest, Language) {
@@ -727,7 +746,7 @@
add("FOO/BAR/BAZ/SHOUT.cc");
add("foo/bar/baz/quiet.cc");
// Case mismatches are completely ignored, so we choose the name match.
- EXPECT_EQ(getCommand("foo/bar/baz/shout.C"), "clang -D
FOO/BAR/BAZ/SHOUT.cc");
+ EXPECT_EQ(getProxy("foo/bar/baz/shout.C"), "FOO/BAR/BAZ/SHOUT.cc");
}
TEST_F(InterpolateTest, Aliasing) {
Index: lib/Tooling/InterpolatingCompilationDatabase.cpp
===================================================================
--- lib/Tooling/InterpolatingCompilationDatabase.cpp
+++ lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -226,6 +226,7 @@
LangStandard::getLangStandardForKind(Std).getName()).str());
}
Result.CommandLine.push_back(Filename);
+ Result.Heuristic = "inferred from " + Cmd.Filename;
return Result;
}
Index: include/clang/Tooling/CompilationDatabase.h
===================================================================
--- include/clang/Tooling/CompilationDatabase.h
+++ include/clang/Tooling/CompilationDatabase.h
@@ -59,9 +59,15 @@
/// The output file associated with the command.
std::string Output;
+ /// If this compile command was guessed rather than read from an
authoritative
+ /// source, a short human-readable explanation.
+ /// e.g. "inferred from foo/bar.h".
+ std::string Heuristic;
+
friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS)
{
return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
- LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output;
+ LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output &&
+ LHS.Heuristic == RHS.Heuristic;
}
friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS)
{
Index: unittests/Tooling/CompilationDatabaseTest.cpp
===================================================================
--- unittests/Tooling/CompilationDatabaseTest.cpp
+++ unittests/Tooling/CompilationDatabaseTest.cpp
@@ -673,6 +673,27 @@
return llvm::join(Results[0].CommandLine, " ");
}
+ // Parse the file whose command was used out of the Heuristic string.
+ std::string getProxy(llvm::StringRef F) {
+ auto Results =
+ inferMissingCompileCommands(llvm::make_unique<MemCDB>(Entries))
+ ->getCompileCommands(path(F));
+ if (Results.empty())
+ return "none";
+ StringRef Proxy = Results.front().Heuristic;
+ if (!Proxy.consume_front("inferred from "))
+ return "";
+ // We have a proxy file, convert back to a unix relative path.
+ // This is a bit messy, but we do need to test these strings somehow...
+ llvm::SmallString<32> TempDir;
+ llvm::sys::path::system_temp_directory(false, TempDir);
+ Proxy.consume_front(TempDir);
+ Proxy.consume_front(llvm::sys::path::get_separator());
+ llvm::SmallString<32> Result = Proxy;
+ llvm::sys::path::native(Result, llvm::sys::path::Style::posix);
+ return Result.str();
+ }
+
MemCDB::EntryMap Entries;
};
@@ -682,18 +703,16 @@
add("an/other/foo.cpp");
// great: dir and name both match (prefix or full, case insensitive)
- EXPECT_EQ(getCommand("dir/f.cpp"), "clang -D dir/foo.cpp");
- EXPECT_EQ(getCommand("dir/FOO.cpp"), "clang -D dir/foo.cpp");
+ EXPECT_EQ(getProxy("dir/f.cpp"), "dir/foo.cpp");
+ EXPECT_EQ(getProxy("dir/FOO.cpp"), "dir/foo.cpp");
// no name match. prefer matching dir, break ties by alpha
- EXPECT_EQ(getCommand("dir/a.cpp"), "clang -D dir/bar.cpp");
+ EXPECT_EQ(getProxy("dir/a.cpp"), "dir/bar.cpp");
// an exact name match beats one segment of directory match
- EXPECT_EQ(getCommand("some/other/bar.h"),
- "clang -D dir/bar.cpp -x c++-header");
+ EXPECT_EQ(getProxy("some/other/bar.h"), "dir/bar.cpp");
// two segments of directory match beat a prefix name match
- EXPECT_EQ(getCommand("an/other/b.cpp"), "clang -D an/other/foo.cpp");
+ EXPECT_EQ(getProxy("an/other/b.cpp"), "an/other/foo.cpp");
// if nothing matches at all, we still get the closest alpha match
- EXPECT_EQ(getCommand("below/some/obscure/path.cpp"),
- "clang -D an/other/foo.cpp");
+ EXPECT_EQ(getProxy("below/some/obscure/path.cpp"), "an/other/foo.cpp");
}
TEST_F(InterpolateTest, Language) {
@@ -727,7 +746,7 @@
add("FOO/BAR/BAZ/SHOUT.cc");
add("foo/bar/baz/quiet.cc");
// Case mismatches are completely ignored, so we choose the name match.
- EXPECT_EQ(getCommand("foo/bar/baz/shout.C"), "clang -D FOO/BAR/BAZ/SHOUT.cc");
+ EXPECT_EQ(getProxy("foo/bar/baz/shout.C"), "FOO/BAR/BAZ/SHOUT.cc");
}
TEST_F(InterpolateTest, Aliasing) {
Index: lib/Tooling/InterpolatingCompilationDatabase.cpp
===================================================================
--- lib/Tooling/InterpolatingCompilationDatabase.cpp
+++ lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -226,6 +226,7 @@
LangStandard::getLangStandardForKind(Std).getName()).str());
}
Result.CommandLine.push_back(Filename);
+ Result.Heuristic = "inferred from " + Cmd.Filename;
return Result;
}
Index: include/clang/Tooling/CompilationDatabase.h
===================================================================
--- include/clang/Tooling/CompilationDatabase.h
+++ include/clang/Tooling/CompilationDatabase.h
@@ -59,9 +59,15 @@
/// The output file associated with the command.
std::string Output;
+ /// If this compile command was guessed rather than read from an authoritative
+ /// source, a short human-readable explanation.
+ /// e.g. "inferred from foo/bar.h".
+ std::string Heuristic;
+
friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS) {
return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename &&
- LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output;
+ LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output &&
+ LHS.Heuristic == RHS.Heuristic;
}
friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS) {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits