Index: clang-tools-extra/trunk/include-fixer/YamlXrefsDB.h =================================================================== --- clang-tools-extra/trunk/include-fixer/YamlXrefsDB.h +++ clang-tools-extra/trunk/include-fixer/YamlXrefsDB.h @@ -12,6 +12,7 @@ #include "XrefsDB.h" #include "find-all-symbols/SymbolInfo.h" +#include "llvm/Support/ErrorOr.h" #include #include @@ -21,12 +22,20 @@ /// Yaml format database. class YamlXrefsDB : public XrefsDB { public: - YamlXrefsDB(llvm::StringRef FilePath); + /// Create a new Yaml db from a file. + static llvm::ErrorOr> + createFromFile(llvm::StringRef FilePath); + /// Look for a file called \c Name in \c Directory and all parent directories. + static llvm::ErrorOr> + createFromDirectory(llvm::StringRef Directory, llvm::StringRef Name); std::vector search(llvm::StringRef Identifier) override; private: + explicit YamlXrefsDB(std::vector Symbols) + : Symbols(std::move(Symbols)) {} + std::vector Symbols; }; Index: clang-tools-extra/trunk/include-fixer/YamlXrefsDB.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/YamlXrefsDB.cpp +++ clang-tools-extra/trunk/include-fixer/YamlXrefsDB.cpp @@ -8,10 +8,11 @@ //===----------------------------------------------------------------------===// #include "YamlXrefsDB.h" - #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" #include #include @@ -20,15 +21,30 @@ namespace clang { namespace include_fixer { -YamlXrefsDB::YamlXrefsDB(llvm::StringRef FilePath) { - int ReadFD = 0; - if (llvm::sys::fs::openFileForRead(FilePath, ReadFD)) - return; - auto Buffer = llvm::MemoryBuffer::getOpenFile(ReadFD, FilePath, -1); +llvm::ErrorOr> +YamlXrefsDB::createFromFile(llvm::StringRef FilePath) { + auto Buffer = llvm::MemoryBuffer::getFile(FilePath); if (!Buffer) - return; - Symbols = clang::find_all_symbols::ReadSymbolInfosFromYAML( - Buffer.get()->getBuffer()); + return Buffer.getError(); + + return std::unique_ptr( + new YamlXrefsDB(clang::find_all_symbols::ReadSymbolInfosFromYAML( + Buffer.get()->getBuffer()))); +} + +llvm::ErrorOr> +YamlXrefsDB::createFromDirectory(llvm::StringRef Directory, + llvm::StringRef Name) { + // Walk upwards from Directory, looking for files. + for (llvm::SmallString<128> PathStorage = Directory; !Directory.empty(); + Directory = llvm::sys::path::parent_path(Directory)) { + assert(Directory.size() <= PathStorage.size()); + PathStorage.resize(Directory.size()); // Shrink to parent. + llvm::sys::path::append(PathStorage, Name); + if (auto DB = createFromFile(PathStorage)) + return DB; + } + return llvm::make_error_code(llvm::errc::no_such_file_or_directory); } std::vector YamlXrefsDB::search(llvm::StringRef Identifier) { Index: clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp +++ clang-tools-extra/trunk/include-fixer/tool/ClangIncludeFixer.cpp @@ -73,8 +73,26 @@ break; } case yaml: { - XrefsDBMgr->addXrefsDB( - llvm::make_unique(Input)); + llvm::ErrorOr> DB(nullptr); + if (!Input.empty()) { + DB = include_fixer::YamlXrefsDB::createFromFile(Input); + } else { + // If we don't have any input file, look in the directory of the first + // file and its parents. + SmallString<128> AbsolutePath( + tooling::getAbsolutePath(options.getSourcePathList().front())); + StringRef Directory = llvm::sys::path::parent_path(AbsolutePath); + DB = include_fixer::YamlXrefsDB::createFromDirectory( + Directory, "find_all_symbols_db.yaml"); + } + + if (!DB) { + llvm::errs() << "Couldn't find YAML db: " << DB.getError().message() + << '\n'; + return 1; + } + + XrefsDBMgr->addXrefsDB(std::move(*DB)); break; } } Index: clang-tools-extra/trunk/test/include-fixer/yamldb_autodetect.cpp =================================================================== --- clang-tools-extra/trunk/test/include-fixer/yamldb_autodetect.cpp +++ clang-tools-extra/trunk/test/include-fixer/yamldb_autodetect.cpp @@ -0,0 +1,12 @@ +// REQUIRES: shell +// RUN: mkdir -p %T/foo/bar +// RUN: cp %p/Inputs/fake_yaml_db.yaml %T/find_all_symbols_db.yaml +// RUN: cd %T/foo +// RUN: sed -e 's#//.*$##' %s > bar/test.cpp +// RUN: clang-include-fixer -db=yaml bar/test.cpp -- +// RUN: FileCheck %s -input-file=bar/test.cpp + +// CHECK: #include "foo.h" +// CHECK: b::a::foo f; + +b::a::foo f;