[include-fixer] Autodetect yaml databases in parent directories.

This looks for find_all_symbols_db.yaml in all parent directories of the
source file (like we do for compile_commands.json) so we don't have to
pass the path manually.

Differential Revision: http://reviews.llvm.org/D20066

llvm-svn: 268920
This commit is contained in:
Benjamin Kramer 2016-05-09 14:14:55 +00:00
parent 1172668682
commit b6aed5f441
4 changed files with 67 additions and 12 deletions

View File

@ -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 <string>
#include <vector>
@ -20,15 +21,30 @@ using clang::find_all_symbols::SymbolInfo;
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<std::unique_ptr<YamlXrefsDB>>
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<YamlXrefsDB>(
new YamlXrefsDB(clang::find_all_symbols::ReadSymbolInfosFromYAML(
Buffer.get()->getBuffer())));
}
llvm::ErrorOr<std::unique_ptr<YamlXrefsDB>>
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<SymbolInfo> YamlXrefsDB::search(llvm::StringRef Identifier) {

View File

@ -12,6 +12,7 @@
#include "XrefsDB.h"
#include "find-all-symbols/SymbolInfo.h"
#include "llvm/Support/ErrorOr.h"
#include <map>
#include <vector>
@ -21,12 +22,20 @@ namespace include_fixer {
/// Yaml format database.
class YamlXrefsDB : public XrefsDB {
public:
YamlXrefsDB(llvm::StringRef FilePath);
/// Create a new Yaml db from a file.
static llvm::ErrorOr<std::unique_ptr<YamlXrefsDB>>
createFromFile(llvm::StringRef FilePath);
/// Look for a file called \c Name in \c Directory and all parent directories.
static llvm::ErrorOr<std::unique_ptr<YamlXrefsDB>>
createFromDirectory(llvm::StringRef Directory, llvm::StringRef Name);
std::vector<clang::find_all_symbols::SymbolInfo>
search(llvm::StringRef Identifier) override;
private:
explicit YamlXrefsDB(std::vector<clang::find_all_symbols::SymbolInfo> Symbols)
: Symbols(std::move(Symbols)) {}
std::vector<clang::find_all_symbols::SymbolInfo> Symbols;
};

View File

@ -73,8 +73,26 @@ int includeFixerMain(int argc, const char **argv) {
break;
}
case yaml: {
XrefsDBMgr->addXrefsDB(
llvm::make_unique<include_fixer::YamlXrefsDB>(Input));
llvm::ErrorOr<std::unique_ptr<include_fixer::YamlXrefsDB>> 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;
}
}

View File

@ -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;