[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/JSONComp

David Blaikie dblaikie at gmail.com
Mon Oct 8 09:53:44 PDT 2012


On Mon, Oct 8, 2012 at 9:40 AM, Benjamin Kramer <benny.kra at gmail.com> wrote:
>
> 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.

Only expensive when done this way. Ideally the way to manifest a Twine is:

SmallString<32> X;
StringRef S = T.toStringRef(X);

In which case it only costs you the stack space for X and if T is
already just a StringRef it doesn't use X anyway, so you only pay the
cost when you need it.

If I could get this syntax to be any shorter/more convenient I would
love to - this would make it easier for callees to not worry so much
about whether their callers are just passing StringRefs or possibly
passing concatenations.

> 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
>
>
> _______________________________________________
> 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