blob: addaa86f130c6278d1048617e3cd5e1dfa148f0d [file] [log] [blame]
//===--- IndexStoreCXX.h - C++ wrapper for the Index Store C API. ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Header-only C++ wrapper for the Index Store C API.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEXSTORE_INDEXSTORECXX_H
#define LLVM_CLANG_INDEXSTORE_INDEXSTORECXX_H
#include "indexstore/indexstore.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include <ctime>
namespace indexstore {
using llvm::ArrayRef;
using llvm::Optional;
using llvm::StringRef;
static inline StringRef stringFromIndexStoreStringRef(indexstore_string_ref_t str) {
return StringRef(str.data, str.length);
}
class IndexRecordSymbol {
indexstore_symbol_t obj;
friend class IndexRecordReader;
public:
IndexRecordSymbol(indexstore_symbol_t obj) : obj(obj) {}
indexstore_symbol_language_t getLanguage() {
return indexstore_symbol_get_language(obj);
}
indexstore_symbol_kind_t getKind() { return indexstore_symbol_get_kind(obj); }
indexstore_symbol_subkind_t getSubKind() { return indexstore_symbol_get_subkind(obj); }
uint64_t getProperties() {
return indexstore_symbol_get_properties(obj);
}
uint64_t getRoles() { return indexstore_symbol_get_roles(obj); }
uint64_t getRelatedRoles() { return indexstore_symbol_get_related_roles(obj); }
StringRef getName() { return stringFromIndexStoreStringRef(indexstore_symbol_get_name(obj)); }
StringRef getUSR() { return stringFromIndexStoreStringRef(indexstore_symbol_get_usr(obj)); }
StringRef getCodegenName() { return stringFromIndexStoreStringRef(indexstore_symbol_get_codegen_name(obj)); }
};
class IndexSymbolRelation {
indexstore_symbol_relation_t obj;
public:
IndexSymbolRelation(indexstore_symbol_relation_t obj) : obj(obj) {}
uint64_t getRoles() { return indexstore_symbol_relation_get_roles(obj); }
IndexRecordSymbol getSymbol() { return indexstore_symbol_relation_get_symbol(obj); }
};
class IndexRecordOccurrence {
indexstore_occurrence_t obj;
public:
IndexRecordOccurrence(indexstore_occurrence_t obj) : obj(obj) {}
IndexRecordSymbol getSymbol() { return indexstore_occurrence_get_symbol(obj); }
uint64_t getRoles() { return indexstore_occurrence_get_roles(obj); }
bool foreachRelation(llvm::function_ref<bool(IndexSymbolRelation)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
return indexstore_occurrence_relations_apply(obj, ^bool(indexstore_symbol_relation_t sym_rel) {
return receiver(sym_rel);
});
#else
return false;
#endif
}
std::pair<unsigned, unsigned> getLineCol() {
unsigned line, col;
indexstore_occurrence_get_line_col(obj, &line, &col);
return std::make_pair(line, col);
}
};
class IndexStore;
typedef std::shared_ptr<IndexStore> IndexStoreRef;
class IndexStore {
indexstore_t obj;
friend class IndexRecordReader;
friend class IndexUnitReader;
public:
IndexStore(StringRef path, std::string &error) {
llvm::SmallString<64> buf = path;
indexstore_error_t c_err = nullptr;
obj = indexstore_store_create(buf.c_str(), &c_err);
if (c_err) {
error = indexstore_error_get_description(c_err);
indexstore_error_dispose(c_err);
}
}
IndexStore(IndexStore &&other) : obj(other.obj) {
other.obj = nullptr;
}
~IndexStore() {
indexstore_store_dispose(obj);
}
static IndexStoreRef create(StringRef path, std::string &error) {
auto storeRef = std::make_shared<IndexStore>(path, error);
if (storeRef->isInvalid())
return nullptr;
return storeRef;
}
static unsigned formatVersion() {
return indexstore_format_version();
}
bool isValid() const { return obj; }
bool isInvalid() const { return !isValid(); }
explicit operator bool() const { return isValid(); }
bool foreachUnit(bool sorted, llvm::function_ref<bool(StringRef unitName)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
return indexstore_store_units_apply(obj, sorted, ^bool(indexstore_string_ref_t unit_name) {
return receiver(stringFromIndexStoreStringRef(unit_name));
});
#else
return false;
#endif
}
class UnitEvent {
indexstore_unit_event_t obj;
public:
UnitEvent(indexstore_unit_event_t obj) : obj(obj) {}
enum class Kind {
Added,
Removed,
Modified,
DirectoryDeleted,
};
Kind getKind() const {
indexstore_unit_event_kind_t c_k = indexstore_unit_event_get_kind(obj);
Kind K;
switch (c_k) {
case INDEXSTORE_UNIT_EVENT_ADDED: K = Kind::Added; break;
case INDEXSTORE_UNIT_EVENT_REMOVED: K = Kind::Removed; break;
case INDEXSTORE_UNIT_EVENT_MODIFIED: K = Kind::Modified; break;
case INDEXSTORE_UNIT_EVENT_DIRECTORY_DELETED: K = Kind::DirectoryDeleted; break;
}
return K;
}
StringRef getUnitName() const {
return stringFromIndexStoreStringRef(indexstore_unit_event_get_unit_name(obj));
}
timespec getModificationTime() const { return indexstore_unit_event_get_modification_time(obj); }
};
class UnitEventNotification {
indexstore_unit_event_notification_t obj;
public:
UnitEventNotification(indexstore_unit_event_notification_t obj) : obj(obj) {}
bool isInitial() const { return indexstore_unit_event_notification_is_initial(obj); }
size_t getEventsCount() const { return indexstore_unit_event_notification_get_events_count(obj); }
UnitEvent getEvent(size_t index) const { return indexstore_unit_event_notification_get_event(obj, index); }
};
typedef std::function<void(UnitEventNotification)> UnitEventHandler;
void setUnitEventHandler(UnitEventHandler handler) {
#if INDEXSTORE_HAS_BLOCKS
if (!handler) {
indexstore_store_set_unit_event_handler(obj, nullptr);
return;
}
indexstore_store_set_unit_event_handler(obj, ^(indexstore_unit_event_notification_t evt_note) {
handler(UnitEventNotification(evt_note));
});
#endif
}
bool startEventListening(bool waitInitialSync, std::string &error) {
indexstore_unit_event_listen_options_t opts;
opts.wait_initial_sync = waitInitialSync;
indexstore_error_t c_err = nullptr;
bool ret = indexstore_store_start_unit_event_listening(obj, &opts, sizeof(opts), &c_err);
if (c_err) {
error = indexstore_error_get_description(c_err);
indexstore_error_dispose(c_err);
}
return ret;
}
void stopEventListening() {
return indexstore_store_stop_unit_event_listening(obj);
}
void discardUnit(StringRef UnitName) {
llvm::SmallString<64> buf = UnitName;
indexstore_store_discard_unit(obj, buf.c_str());
}
void discardRecord(StringRef RecordName) {
llvm::SmallString<64> buf = RecordName;
indexstore_store_discard_record(obj, buf.c_str());
}
void getUnitNameFromOutputPath(StringRef outputPath, llvm::SmallVectorImpl<char> &nameBuf) {
llvm::SmallString<256> buf = outputPath;
size_t nameLen = indexstore_store_get_unit_name_from_output_path(obj, buf.c_str(), nameBuf.data(), nameBuf.size());
if (nameLen+1 > nameBuf.size()) {
nameBuf.resize(nameLen+1);
indexstore_store_get_unit_name_from_output_path(obj, buf.c_str(), nameBuf.data(), nameBuf.size());
}
}
llvm::Optional<timespec>
getUnitModificationTime(StringRef unitName, std::string &error) {
llvm::SmallString<64> buf = unitName;
int64_t seconds, nanoseconds;
indexstore_error_t c_err = nullptr;
bool err = indexstore_store_get_unit_modification_time(obj, buf.c_str(),
&seconds, &nanoseconds, &c_err);
if (err && c_err) {
error = indexstore_error_get_description(c_err);
indexstore_error_dispose(c_err);
return llvm::None;
}
timespec ts;
ts.tv_sec = seconds;
ts.tv_nsec = nanoseconds;
return ts;
}
void purgeStaleData() {
indexstore_store_purge_stale_data(obj);
}
};
class IndexRecordReader {
indexstore_record_reader_t obj;
public:
IndexRecordReader(IndexStore &store, StringRef recordName, std::string &error) {
llvm::SmallString<64> buf = recordName;
indexstore_error_t c_err = nullptr;
obj = indexstore_record_reader_create(store.obj, buf.c_str(), &c_err);
if (c_err) {
error = indexstore_error_get_description(c_err);
indexstore_error_dispose(c_err);
}
}
IndexRecordReader(IndexRecordReader &&other) : obj(other.obj) {
other.obj = nullptr;
}
~IndexRecordReader() {
indexstore_record_reader_dispose(obj);
}
bool isValid() const { return obj; }
bool isInvalid() const { return !isValid(); }
explicit operator bool() const { return isValid(); }
/// Goes through and passes record decls, after filtering using a \c Checker
/// function.
///
/// Resulting decls can be used as filter for \c foreachOccurrence. This
/// allows allocating memory only for the record decls that the caller is
/// interested in.
bool searchSymbols(llvm::function_ref<bool(IndexRecordSymbol, bool &stop)> filter,
llvm::function_ref<void(IndexRecordSymbol)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
return indexstore_record_reader_search_symbols(obj, ^bool(indexstore_symbol_t symbol, bool *stop) {
return filter(symbol, *stop);
}, ^(indexstore_symbol_t symbol) {
receiver(symbol);
});
#else
return false;
#endif
}
bool foreachSymbol(bool noCache, llvm::function_ref<bool(IndexRecordSymbol)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
return indexstore_record_reader_symbols_apply(obj, noCache, ^bool(indexstore_symbol_t sym) {
return receiver(sym);
});
#else
return false;
#endif
}
/// \param DeclsFilter if non-empty indicates the list of decls that we want
/// to get occurrences for. An empty array indicates that we want occurrences
/// for all decls.
/// \param RelatedDeclsFilter Same as \c DeclsFilter but for related decls.
bool foreachOccurrence(ArrayRef<IndexRecordSymbol> symbolsFilter,
ArrayRef<IndexRecordSymbol> relatedSymbolsFilter,
llvm::function_ref<bool(IndexRecordOccurrence)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
llvm::SmallVector<indexstore_symbol_t, 16> c_symbolsFilter;
c_symbolsFilter.reserve(symbolsFilter.size());
for (IndexRecordSymbol sym : symbolsFilter) {
c_symbolsFilter.push_back(sym.obj);
}
llvm::SmallVector<indexstore_symbol_t, 16> c_relatedSymbolsFilter;
c_relatedSymbolsFilter.reserve(relatedSymbolsFilter.size());
for (IndexRecordSymbol sym : relatedSymbolsFilter) {
c_relatedSymbolsFilter.push_back(sym.obj);
}
return indexstore_record_reader_occurrences_of_symbols_apply(obj,
c_symbolsFilter.data(), c_symbolsFilter.size(),
c_relatedSymbolsFilter.data(),
c_relatedSymbolsFilter.size(),
^bool(indexstore_occurrence_t occur) {
return receiver(occur);
});
#else
return false;
#endif
}
bool foreachOccurrence(
llvm::function_ref<bool(IndexRecordOccurrence)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
return indexstore_record_reader_occurrences_apply(obj, ^bool(indexstore_occurrence_t occur) {
return receiver(occur);
});
#else
return false;
#endif
}
bool foreachOccurrenceInLineRange(unsigned lineStart, unsigned lineEnd,
llvm::function_ref<bool(IndexRecordOccurrence)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
return indexstore_record_reader_occurrences_in_line_range_apply(obj,
lineStart,
lineEnd,
^bool(indexstore_occurrence_t occur) {
return receiver(occur);
});
#else
return false;
#endif
}
};
class IndexUnitDependency {
indexstore_unit_dependency_t obj;
friend class IndexUnitReader;
public:
IndexUnitDependency(indexstore_unit_dependency_t obj) : obj(obj) {}
enum class DependencyKind {
Unit,
Record,
File,
};
DependencyKind getKind() {
switch (indexstore_unit_dependency_get_kind(obj)) {
case INDEXSTORE_UNIT_DEPENDENCY_UNIT: return DependencyKind::Unit;
case INDEXSTORE_UNIT_DEPENDENCY_RECORD: return DependencyKind::Record;
case INDEXSTORE_UNIT_DEPENDENCY_FILE: return DependencyKind::File;
}
}
bool isSystem() { return indexstore_unit_dependency_is_system(obj); }
StringRef getName() { return stringFromIndexStoreStringRef(indexstore_unit_dependency_get_name(obj)); }
StringRef getFilePath() { return stringFromIndexStoreStringRef(indexstore_unit_dependency_get_filepath(obj)); }
StringRef getModuleName() { return stringFromIndexStoreStringRef(indexstore_unit_dependency_get_modulename(obj)); }
time_t getModificationTime() { return indexstore_unit_dependency_get_modification_time(obj); }
size_t getFileSize() { return indexstore_unit_dependency_get_file_size(obj); }
};
class IndexUnitInclude {
indexstore_unit_include_t obj;
friend class IndexUnitReader;
public:
IndexUnitInclude(indexstore_unit_include_t obj) : obj(obj) {}
StringRef getSourcePath() {
return stringFromIndexStoreStringRef(indexstore_unit_include_get_source_path(obj));
}
StringRef getTargetPath() {
return stringFromIndexStoreStringRef(indexstore_unit_include_get_target_path(obj));
}
unsigned getSourceLine() {
return indexstore_unit_include_get_source_line(obj);
}
};
class IndexUnitReader {
indexstore_unit_reader_t obj;
public:
IndexUnitReader(IndexStore &store, StringRef unitName, std::string &error) {
llvm::SmallString<64> buf = unitName;
indexstore_error_t c_err = nullptr;
obj = indexstore_unit_reader_create(store.obj, buf.c_str(), &c_err);
if (c_err) {
error = indexstore_error_get_description(c_err);
indexstore_error_dispose(c_err);
}
}
IndexUnitReader(IndexUnitReader &&other) : obj(other.obj) {
other.obj = nullptr;
}
~IndexUnitReader() {
indexstore_unit_reader_dispose(obj);
}
bool isValid() const { return obj; }
bool isInvalid() const { return !isValid(); }
explicit operator bool() const { return isValid(); }
StringRef getProviderIdentifier() {
return stringFromIndexStoreStringRef(indexstore_unit_reader_get_provider_identifier(obj));
}
StringRef getProviderVersion() {
return stringFromIndexStoreStringRef(indexstore_unit_reader_get_provider_version(obj));
}
timespec getModificationTime() {
int64_t seconds, nanoseconds;
indexstore_unit_reader_get_modification_time(obj, &seconds, &nanoseconds);
timespec ts;
ts.tv_sec = seconds;
ts.tv_nsec = nanoseconds;
return ts;
}
bool isSystemUnit() { return indexstore_unit_reader_is_system_unit(obj); }
bool isModuleUnit() { return indexstore_unit_reader_is_module_unit(obj); }
bool isDebugCompilation() { return indexstore_unit_reader_is_debug_compilation(obj); }
bool hasMainFile() { return indexstore_unit_reader_has_main_file(obj); }
StringRef getMainFilePath() {
return stringFromIndexStoreStringRef(indexstore_unit_reader_get_main_file(obj));
}
StringRef getModuleName() {
return stringFromIndexStoreStringRef(indexstore_unit_reader_get_module_name(obj));
}
StringRef getWorkingDirectory() {
return stringFromIndexStoreStringRef(indexstore_unit_reader_get_working_dir(obj));
}
StringRef getOutputFile() {
return stringFromIndexStoreStringRef(indexstore_unit_reader_get_output_file(obj));
}
StringRef getSysrootPath() {
return stringFromIndexStoreStringRef(indexstore_unit_reader_get_sysroot_path(obj));
}
StringRef getTarget() {
return stringFromIndexStoreStringRef(indexstore_unit_reader_get_target(obj));
}
bool foreachDependency(llvm::function_ref<bool(IndexUnitDependency)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
return indexstore_unit_reader_dependencies_apply(obj, ^bool(indexstore_unit_dependency_t dep) {
return receiver(dep);
});
#else
return false;
#endif
}
bool foreachInclude(llvm::function_ref<bool(IndexUnitInclude)> receiver) {
#if INDEXSTORE_HAS_BLOCKS
return indexstore_unit_reader_includes_apply(obj, ^bool(indexstore_unit_include_t inc) {
return receiver(inc);
});
#else
return false;
#endif
}
};
} // namespace indexstore
#endif