[cfe-commits] r165392 - in /cfe/trunk: include/clang/Tooling/CompilationDatabase.h include/clang/Tooling/FileMatchTrie.h include/clang/Tooling/JSONCompilationDatabase.h lib/Tooling/CMakeLists.txt lib/Tooling/FileMatchTrie.cpp lib/Tooling/JSONCompilationDatabase.cpp unittests/Tooling/CompilationDatabaseTest.cpp
Benjamin Kramer
benny.kra at gmail.com
Mon Oct 8 09:40:33 PDT 2012
On 08.10.2012, at 18:08, Daniel Jasper <djasper at google.com> wrote:
> Author: djasper
> Date: Mon Oct 8 11:08:15 2012
> New Revision: 165392
>
> URL: http://llvm.org/viewvc/llvm-project?rev=165392&view=rev
> Log:
> Support symlinks and relative paths in complilation databases.
>
> Review: http://llvm-reviews.chandlerc.com/D30
>
> Added:
> cfe/trunk/include/clang/Tooling/FileMatchTrie.h
> cfe/trunk/lib/Tooling/FileMatchTrie.cpp
> Modified:
> cfe/trunk/include/clang/Tooling/CompilationDatabase.h
> cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h
> cfe/trunk/lib/Tooling/CMakeLists.txt
> cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp
> cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp
>
> Modified: cfe/trunk/include/clang/Tooling/CompilationDatabase.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/CompilationDatabase.h?rev=165392&r1=165391&r2=165392&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Tooling/CompilationDatabase.h (original)
> +++ cfe/trunk/include/clang/Tooling/CompilationDatabase.h Mon Oct 8 11:08:15 2012
> @@ -33,6 +33,7 @@
> #include "llvm/ADT/OwningPtr.h"
> #include "llvm/ADT/StringRef.h"
> #include "llvm/ADT/Twine.h"
> +
> #include <string>
> #include <vector>
>
>
> Added: cfe/trunk/include/clang/Tooling/FileMatchTrie.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/FileMatchTrie.h?rev=165392&view=auto
> ==============================================================================
> --- cfe/trunk/include/clang/Tooling/FileMatchTrie.h (added)
> +++ cfe/trunk/include/clang/Tooling/FileMatchTrie.h Mon Oct 8 11:08:15 2012
> @@ -0,0 +1,91 @@
> +//===--- FileMatchTrie.h - --------------------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements a match trie to find the matching file in a compilation
> +// database based on a given path in the presence of symlinks.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H
> +#define LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H
> +
> +#include "clang/Basic/LLVM.h"
> +#include "llvm/ADT/OwningPtr.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/ADT/Twine.h"
> +
> +#include <string>
> +#include <vector>
> +
> +namespace clang {
> +namespace tooling {
> +
> +struct PathComparator {
> + virtual ~PathComparator() {}
> + virtual bool equivalent(const Twine &FileA, const Twine &FileB) const = 0;
> +};
> +class FileMatchTrieNode;
> +
> +/// \brief A trie to efficiently match against the entries of the compilation
> +/// database in order of matching suffix length.
> +///
> +/// When a clang tool is supposed to operate on a specific file, we have to
> +/// find the corresponding file in the compilation database. Although entries
> +/// in the compilation database are keyed by filename, a simple string match
> +/// is insufficient because of symlinks. Commonly, a project hierarchy looks
> +/// like this:
> +/// /<project-root>/src/<path>/<somefile>.cc (used as input for the tool)
> +/// /<project-root>/build/<symlink-to-src>/<path>/<somefile>.cc (stored in DB)
> +///
> +/// Furthermore, there might be symlinks inside the source folder or inside the
> +/// database, so that the same source file is translated with different build
> +/// options.
> +///
> +/// For a given input file, the \c FileMatchTrie finds its entries in order
> +/// of matching suffix length. For each suffix length, there might be one or
> +/// more entries in the database. For each of those entries, it calls
> +/// \c llvm::sys::fs::equivalent() (injected as \c PathComparator). There might
> +/// be zero or more entries with the same matching suffix length that are
> +/// equivalent to the input file. Three cases are distinguished:
> +/// 0 equivalent files: Continue with the next suffix length.
> +/// 1 equivalent file: Best match found, return it.
> +/// >1 equivalent files: Match is ambiguous, return error.
> +class FileMatchTrie {
> +public:
> + FileMatchTrie();
> +
> + /// \brief Construct a new \c FileMatchTrie with the given \c PathComparator.
> + ///
> + /// The \c FileMatchTrie takes ownership of 'Comparator'. Used for testing.
> + FileMatchTrie(PathComparator* Comparator);
> +
> + ~FileMatchTrie();
> +
> + /// \brief Insert a new absolute path. Relative paths are ignored.
> + void insert(StringRef NewPath);
> +
> + /// \brief Finds the corresponding file in this trie.
> + ///
> + /// Returns file name stored in this trie that is equivalent to 'FileName'
> + /// according to 'Comparator', if it can be uniquely identified. If there
> + /// are no matches an empty \c StringRef is returned. If there are ambigious
> + /// matches, an empty \c StringRef is returned and a corresponding message
> + /// written to 'Error'.
> + StringRef findEquivalent(StringRef FileName,
> + llvm::raw_ostream &Error) const;
> +private:
> + FileMatchTrieNode *Root;
> + OwningPtr<PathComparator> Comparator;
> +};
> +
> +
> +} // end namespace tooling
> +} // end namespace clang
> +
> +#endif // LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H
>
> Modified: cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h?rev=165392&r1=165391&r2=165392&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h (original)
> +++ cfe/trunk/include/clang/Tooling/JSONCompilationDatabase.h Mon Oct 8 11:08:15 2012
> @@ -17,6 +17,7 @@
>
> #include "clang/Basic/LLVM.h"
> #include "clang/Tooling/CompilationDatabase.h"
> +#include "clang/Tooling/FileMatchTrie.h"
> #include "llvm/ADT/OwningPtr.h"
> #include "llvm/ADT/StringMap.h"
> #include "llvm/ADT/StringRef.h"
> @@ -93,6 +94,8 @@
> // Maps file paths to the compile command lines for that file.
> llvm::StringMap< std::vector<CompileCommandRef> > IndexByFile;
>
> + FileMatchTrie MatchTrie;
> +
> llvm::OwningPtr<llvm::MemoryBuffer> Database;
> llvm::SourceMgr SM;
> llvm::yaml::Stream YAMLStream;
>
> Modified: cfe/trunk/lib/Tooling/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CMakeLists.txt?rev=165392&r1=165391&r2=165392&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Tooling/CMakeLists.txt (original)
> +++ cfe/trunk/lib/Tooling/CMakeLists.txt Mon Oct 8 11:08:15 2012
> @@ -4,6 +4,7 @@
> ArgumentsAdjusters.cpp
> CommonOptionsParser.cpp
> CompilationDatabase.cpp
> + FileMatchTrie.cpp
> JSONCompilationDatabase.cpp
> Refactoring.cpp
> RefactoringCallbacks.cpp
>
> Added: cfe/trunk/lib/Tooling/FileMatchTrie.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/FileMatchTrie.cpp?rev=165392&view=auto
> ==============================================================================
> --- cfe/trunk/lib/Tooling/FileMatchTrie.cpp (added)
> +++ cfe/trunk/lib/Tooling/FileMatchTrie.cpp Mon Oct 8 11:08:15 2012
> @@ -0,0 +1,188 @@
> +//===--- FileMatchTrie.cpp - ----------------------------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains the implementation of a FileMatchTrie.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include <sstream>
> +#include "clang/Tooling/FileMatchTrie.h"
> +#include "llvm/ADT/StringMap.h"
> +#include "llvm/Support/FileSystem.h"
> +#include "llvm/Support/PathV2.h"
> +
> +namespace clang {
> +namespace tooling {
> +
> +/// \brief Default \c PathComparator using \c llvm::sys::fs::equivalent().
> +struct DefaultPathComparator : public PathComparator {
> + virtual ~DefaultPathComparator() {}
> + virtual bool equivalent(const Twine &FileA, const Twine &FileB) const {
> + return FileA.str() == FileB.str() ||
Comparing Twines is expensive, wouldn't StringRef be sufficient here? equivalent is only ever called with StringRef arguments. Also DefaultPathComparator could go into an anonymous namespace as it's not exposed anywhere.
- Ben
> + llvm::sys::fs::equivalent(FileA, FileB);
> + }
> +};
> +
> +/// \brief A node of the \c FileMatchTrie.
> +///
> +/// Each node has storage for up to one path and a map mapping a path segment to
> +/// child nodes. The trie starts with an empty root node.
> +class FileMatchTrieNode {
> +public:
> + /// \brief Inserts 'NewPath' into this trie. \c ConsumedLength denotes
> + /// the number of \c NewPath's trailing characters already consumed during
> + /// recursion.
> + ///
> + /// An insert of a path
> + /// 'p'starts at the root node and does the following:
> + /// - If the node is empty, insert 'p' into its storage and abort.
> + /// - If the node has a path 'p2' but no children, take the last path segment
> + /// 's' of 'p2', put a new child into the map at 's' an insert the rest of
> + /// 'p2' there.
> + /// - Insert a new child for the last segment of 'p' and insert the rest of
> + /// 'p' there.
> + ///
> + /// An insert operation is linear in the number of a path's segments.
> + void insert(StringRef NewPath, unsigned ConsumedLength = 0) {
> + // We cannot put relative paths into the FileMatchTrie as then a path can be
> + // a postfix of another path, violating a core assumption of the trie.
> + if (llvm::sys::path::is_relative(NewPath))
> + return;
> + if (Path.empty()) {
> + // This is an empty leaf. Store NewPath and return.
> + Path = NewPath;
> + return;
> + }
> + if (Children.empty()) {
> + // This is a leaf, ignore duplicate entry if 'Path' equals 'NewPath'.
> + if (NewPath == Path)
> + return;
> + // Make this a node and create a child-leaf with 'Path'.
> + StringRef Element(llvm::sys::path::filename(
> + StringRef(Path).drop_back(ConsumedLength)));
> + Children[Element].Path = Path;
> + }
> + StringRef Element(llvm::sys::path::filename(
> + StringRef(NewPath).drop_back(ConsumedLength)));
> + Children[Element].insert(NewPath, ConsumedLength + Element.size() + 1);
> + }
> +
> + /// \brief Tries to find the node under this \c FileMatchTrieNode that best
> + /// matches 'FileName'.
> + ///
> + /// If multiple paths fit 'FileName' equally well, \c IsAmbiguous is set to
> + /// \c true and an empty string is returned. If no path fits 'FileName', an
> + /// empty string is returned. \c ConsumedLength denotes the number of
> + /// \c Filename's trailing characters already consumed during recursion.
> + ///
> + /// To find the best matching node for a given path 'p', the
> + /// \c findEquivalent() function is called recursively for each path segment
> + /// (back to fron) of 'p' until a node 'n' is reached that does not ..
> + /// - .. have children. In this case it is checked
> + /// whether the stored path is equivalent to 'p'. If yes, the best match is
> + /// found. Otherwise continue with the parent node as if this node did not
> + /// exist.
> + /// - .. a child matching the next path segment. In this case, all children of
> + /// 'n' are an equally good match for 'p'. All children are of 'n' are found
> + /// recursively and their equivalence to 'p' is determined. If none are
> + /// equivalent, continue with the parent node as if 'n' didn't exist. If one
> + /// is equivalent, the best match is found. Otherwise, report and ambigiuity
> + /// error.
> + StringRef findEquivalent(const PathComparator& Comparator,
> + StringRef FileName,
> + bool &IsAmbiguous,
> + unsigned ConsumedLength = 0) const {
> + if (Children.empty()) {
> + if (Comparator.equivalent(StringRef(Path), FileName))
> + return StringRef(Path);
> + return StringRef();
> + }
> + StringRef Element(llvm::sys::path::filename(FileName.drop_back(
> + ConsumedLength)));
> + llvm::StringMap<FileMatchTrieNode>::const_iterator MatchingChild =
> + Children.find(Element);
> + if (MatchingChild != Children.end()) {
> + StringRef Result = MatchingChild->getValue().findEquivalent(
> + Comparator, FileName, IsAmbiguous,
> + ConsumedLength + Element.size() + 1);
> + if (!Result.empty() || IsAmbiguous)
> + return Result;
> + }
> + std::vector<StringRef> AllChildren;
> + getAll(AllChildren, MatchingChild);
> + StringRef Result;
> + for (unsigned i = 0; i < AllChildren.size(); i++) {
> + if (Comparator.equivalent(AllChildren[i], FileName)) {
> + if (Result.empty()) {
> + Result = AllChildren[i];
> + } else {
> + IsAmbiguous = true;
> + return StringRef();
> + }
> + }
> + }
> + return Result;
> + }
> +
> +private:
> + /// \brief Gets all paths under this FileMatchTrieNode.
> + void getAll(std::vector<StringRef> &Results,
> + llvm::StringMap<FileMatchTrieNode>::const_iterator Except) const {
> + if (Path.empty())
> + return;
> + if (Children.empty()) {
> + Results.push_back(StringRef(Path));
> + return;
> + }
> + for (llvm::StringMap<FileMatchTrieNode>::const_iterator
> + It = Children.begin(), E = Children.end();
> + It != E; ++It) {
> + if (It == Except)
> + continue;
> + It->getValue().getAll(Results, Children.end());
> + }
> + }
> +
> + // The stored absolute path in this node. Only valid for leaf nodes, i.e.
> + // nodes where Children.empty().
> + std::string Path;
> +
> + // The children of this node stored in a map based on the next path segment.
> + llvm::StringMap<FileMatchTrieNode> Children;
> +};
> +
> +FileMatchTrie::FileMatchTrie()
> + : Root(new FileMatchTrieNode), Comparator(new DefaultPathComparator()) {}
> +
> +FileMatchTrie::FileMatchTrie(PathComparator *Comparator)
> + : Root(new FileMatchTrieNode), Comparator(Comparator) {}
> +
> +FileMatchTrie::~FileMatchTrie() {
> + delete Root;
> +}
> +
> +void FileMatchTrie::insert(StringRef NewPath) {
> + Root->insert(NewPath);
> +}
> +
> +StringRef FileMatchTrie::findEquivalent(StringRef FileName,
> + llvm::raw_ostream &Error) const {
> + if (llvm::sys::path::is_relative(FileName)) {
> + Error << "Cannot resolve relative paths";
> + return StringRef();
> + }
> + bool IsAmbiguous = false;
> + StringRef Result = Root->findEquivalent(*Comparator, FileName, IsAmbiguous);
> + if (IsAmbiguous)
> + Error << "Path is ambiguous";
> + return Result;
> +}
> +
> +} // end namespace tooling
> +} // end namespace clang
>
> Modified: cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp?rev=165392&r1=165391&r2=165392&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp (original)
> +++ cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp Mon Oct 8 11:08:15 2012
> @@ -164,8 +164,18 @@
> JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
> llvm::SmallString<128> NativeFilePath;
> llvm::sys::path::native(FilePath, NativeFilePath);
> + std::vector<StringRef> PossibleMatches;
> + std::string Error;
> + llvm::raw_string_ostream ES(Error);
> + StringRef Match = MatchTrie.findEquivalent(NativeFilePath.str(), ES);
> + if (Match.empty()) {
> + if (Error.empty())
> + Error = "No match found.";
> + llvm::outs() << Error << "\n";
> + return std::vector<CompileCommand>();
> + }
> llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
> - CommandsRefI = IndexByFile.find(NativeFilePath);
> + CommandsRefI = IndexByFile.find(Match);
> if (CommandsRefI == IndexByFile.end())
> return std::vector<CompileCommand>();
> const std::vector<CompileCommandRef> &CommandsRef = CommandsRefI->getValue();
> @@ -271,10 +281,20 @@
> return false;
> }
> llvm::SmallString<8> FileStorage;
> + StringRef FileName = File->getValue(FileStorage);
> llvm::SmallString<128> NativeFilePath;
> - llvm::sys::path::native(File->getValue(FileStorage), NativeFilePath);
> + if (llvm::sys::path::is_relative(FileName)) {
> + llvm::SmallString<8> DirectoryStorage;
> + llvm::SmallString<128> AbsolutePath(
> + Directory->getValue(DirectoryStorage));
> + llvm::sys::path::append(AbsolutePath, FileName);
> + llvm::sys::path::native(AbsolutePath.str(), NativeFilePath);
> + } else {
> + llvm::sys::path::native(FileName, NativeFilePath);
> + }
> IndexByFile[NativeFilePath].push_back(
> - CompileCommandRef(Directory, Command));
> + CompileCommandRef(Directory, Command));
> + MatchTrie.insert(NativeFilePath.str());
> }
> return true;
> }
>
> Modified: cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp?rev=165392&r1=165391&r2=165392&view=diff
> ==============================================================================
> --- cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp (original)
> +++ cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp Mon Oct 8 11:08:15 2012
> @@ -11,6 +11,7 @@
> #include "clang/AST/DeclCXX.h"
> #include "clang/AST/DeclGroup.h"
> #include "clang/Frontend/FrontendAction.h"
> +#include "clang/Tooling/FileMatchTrie.h"
> #include "clang/Tooling/JSONCompilationDatabase.h"
> #include "clang/Tooling/Tooling.h"
> #include "gtest/gtest.h"
> @@ -55,13 +56,13 @@
> getAllFiles("[]", ErrorMessage)) << ErrorMessage;
>
> std::vector<std::string> expected_files;
> - expected_files.push_back("file1");
> - expected_files.push_back("file2");
> + expected_files.push_back("/dir/file1");
> + expected_files.push_back("/dir/file2");
> EXPECT_EQ(expected_files, getAllFiles(
> - "[{\"directory\":\"dir\","
> + "[{\"directory\":\"/dir\","
> "\"command\":\"command\","
> "\"file\":\"file1\"},"
> - " {\"directory\":\"dir\","
> + " {\"directory\":\"/dir\","
> "\"command\":\"command\","
> "\"file\":\"file2\"}]",
> ErrorMessage)) << ErrorMessage;
> @@ -81,6 +82,82 @@
> return Commands[0];
> }
>
> +struct FakeComparator : public PathComparator {
> + virtual ~FakeComparator() {}
> + virtual bool equivalent(const Twine &FileA, const Twine &FileB) const {
> + return StringRef(FileA.str()).equals_lower(FileB.str());
> + }
> +};
> +
> +class FileMatchTrieTest : public ::testing::Test {
> +protected:
> + FileMatchTrieTest() : Trie(new FakeComparator()) {}
> +
> + StringRef find(StringRef Path) {
> + llvm::raw_string_ostream ES(Error);
> + return Trie.findEquivalent(Path, ES);
> + }
> +
> + FileMatchTrie Trie;
> + std::string Error;
> +};
> +
> +TEST_F(FileMatchTrieTest, InsertingRelativePath) {
> + Trie.insert("/path/file.cc");
> + Trie.insert("file.cc");
> + EXPECT_EQ("/path/file.cc", find("/path/file.cc"));
> +}
> +
> +TEST_F(FileMatchTrieTest, MatchingRelativePath) {
> + EXPECT_EQ("", find("file.cc"));
> +}
> +
> +TEST_F(FileMatchTrieTest, ReturnsBestResults) {
> + Trie.insert("/d/c/b.cc");
> + Trie.insert("/d/b/b.cc");
> + EXPECT_EQ("/d/b/b.cc", find("/d/b/b.cc"));
> +}
> +
> +TEST_F(FileMatchTrieTest, HandlesSymlinks) {
> + Trie.insert("/AA/file.cc");
> + EXPECT_EQ("/AA/file.cc", find("/aa/file.cc"));
> +}
> +
> +TEST_F(FileMatchTrieTest, ReportsSymlinkAmbiguity) {
> + Trie.insert("/Aa/file.cc");
> + Trie.insert("/aA/file.cc");
> + EXPECT_TRUE(find("/aa/file.cc").empty());
> + EXPECT_EQ("Path is ambiguous", Error);
> +}
> +
> +TEST_F(FileMatchTrieTest, LongerMatchingSuffixPreferred) {
> + Trie.insert("/src/Aa/file.cc");
> + Trie.insert("/src/aA/file.cc");
> + Trie.insert("/SRC/aa/file.cc");
> + EXPECT_EQ("/SRC/aa/file.cc", find("/src/aa/file.cc"));
> +}
> +
> +TEST_F(FileMatchTrieTest, EmptyTrie) {
> + EXPECT_TRUE(find("/some/path").empty());
> +}
> +
> +TEST_F(FileMatchTrieTest, NoResult) {
> + Trie.insert("/somepath/otherfile.cc");
> + Trie.insert("/otherpath/somefile.cc");
> + EXPECT_EQ("", find("/somepath/somefile.cc"));
> +}
> +
> +TEST_F(FileMatchTrieTest, RootElementDifferent) {
> + Trie.insert("/path/file.cc");
> + Trie.insert("/otherpath/file.cc");
> + EXPECT_EQ("/path/file.cc", find("/path/file.cc"));
> +}
> +
> +TEST_F(FileMatchTrieTest, CannotResolveRelativePath) {
> + EXPECT_EQ("", find("relative-path.cc"));
> + EXPECT_EQ("Cannot resolve relative paths", Error);
> +}
> +
> TEST(findCompileArgsInJsonDatabase, FindsNothingIfEmpty) {
> std::string ErrorMessage;
> CompileCommand NotFound = findCompileArgsInJsonDatabase(
> @@ -148,7 +225,7 @@
> }
>
> TEST(findCompileArgsInJsonDatabase, FindsEntry) {
> - StringRef Directory("directory");
> + StringRef Directory("/directory");
> StringRef FileName("file");
> StringRef Command("command");
> std::string JsonDatabase = "[";
> @@ -162,19 +239,19 @@
> JsonDatabase += "]";
> std::string ErrorMessage;
> CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
> - "file4", JsonDatabase, ErrorMessage);
> - EXPECT_EQ("directory4", FoundCommand.Directory) << ErrorMessage;
> + "/directory4/file4", JsonDatabase, ErrorMessage);
> + EXPECT_EQ("/directory4", FoundCommand.Directory) << ErrorMessage;
> ASSERT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage;
> EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage;
> }
>
> static std::vector<std::string> unescapeJsonCommandLine(StringRef Command) {
> std::string JsonDatabase =
> - ("[{\"directory\":\"\", \"file\":\"test\", \"command\": \"" +
> + ("[{\"directory\":\"/root\", \"file\":\"test\", \"command\": \"" +
> Command + "\"}]").str();
> std::string ErrorMessage;
> CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
> - "test", JsonDatabase, ErrorMessage);
> + "/root/test", JsonDatabase, ErrorMessage);
> EXPECT_TRUE(ErrorMessage.empty()) << ErrorMessage;
> return FoundCommand.CommandLine;
> }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list