Skip to content

Add an APIs to get the date at which the unit file that produced SymbolLocation was modified and the latest modification date of a unit that contains a given source file #185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/ISDBTestSupport/TestLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ extension SymbolLocation {
public init(_ loc: TestLocation, moduleName: String = TestLocation.unknownModuleName, isSystem: Bool = false) {
self.init(
path: loc.url.path,
timestamp: Date(),
moduleName: moduleName,
isSystem: isSystem,
line: loc.line,
Expand Down
14 changes: 14 additions & 0 deletions Sources/IndexStoreDB/IndexStoreDB.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

@_implementationOnly
import CIndexStoreDB
import Foundation

// For `strdup`
#if canImport(Glibc)
Expand Down Expand Up @@ -448,6 +449,19 @@ public final class IndexStoreDB {
}
return result
}

/// Returns the latest modification date of a unit that contains the given source file.
///
/// If no unit containing the given source file exists, returns `nil`.
public func dateOfLatestUnitFor(filePath: String) -> Date? {
let timestamp = filePath.withCString { filePathCString in
indexstoredb_timestamp_of_latest_unit_for_file(impl, filePathCString)
}
if timestamp == 0 {
return nil
}
return Date(timeIntervalSince1970: timestamp)
}
}

public protocol IndexStoreLibraryProvider {
Expand Down
7 changes: 6 additions & 1 deletion Sources/IndexStoreDB/SymbolLocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@

@_implementationOnly
import CIndexStoreDB
import Foundation

public struct SymbolLocation: Equatable {
public var path: String
/// The date at which the unit file that contains a symbol has last been modified.
public var timestamp: Date
public var moduleName: String
public var isSystem: Bool
public var line: Int
public var utf8Column: Int

public init(path: String, moduleName: String, isSystem: Bool = false, line: Int, utf8Column: Int) {
public init(path: String, timestamp: Date, moduleName: String, isSystem: Bool = false, line: Int, utf8Column: Int) {
self.path = path
self.timestamp = timestamp
self.moduleName = moduleName
self.isSystem = isSystem
self.line = line
Expand All @@ -47,6 +51,7 @@ extension SymbolLocation: CustomStringConvertible {
extension SymbolLocation {
internal init(_ loc: indexstoredb_symbol_location_t) {
path = String(cString: indexstoredb_symbol_location_path(loc))
timestamp = Date(timeIntervalSince1970: indexstoredb_symbol_location_timestamp(loc))
moduleName = String(cString: indexstoredb_symbol_location_module_name(loc))
isSystem = indexstoredb_symbol_location_is_system(loc)
line = Int(indexstoredb_symbol_location_line(loc))
Expand Down
14 changes: 14 additions & 0 deletions include/CIndexStoreDB/CIndexStoreDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,12 @@ INDEXSTOREDB_PUBLIC
const char * _Nonnull
indexstoredb_symbol_location_path(_Nonnull indexstoredb_symbol_location_t);

/// Returns a Unix timestamp (seconds since 1/1/1970) at which the unit file that contains a symbol has last been
/// modified.
INDEXSTOREDB_PUBLIC
double
indexstoredb_symbol_location_timestamp(_Nonnull indexstoredb_symbol_location_t loc);

/// Returns the module name of the given symbol location.
///
/// The string has the same lifetime as the \c indexstoredb_symbol_location_t.
Expand Down Expand Up @@ -571,6 +577,14 @@ indexstoredb_index_unit_tests(
_Nonnull indexstoredb_symbol_occurrence_receiver_t receiver
);

/// Returns a Unix timestamp (seconds since 1/1/1970) of the latest unit that contains the given source file.
///
/// If no unit containing the given source file exists, returns 0.
INDEXSTOREDB_PUBLIC double
indexstoredb_timestamp_of_latest_unit_for_file(
_Nonnull indexstoredb_index_t index,
const char *_Nonnull fileName
);

INDEXSTOREDB_END_DECLS

Expand Down
4 changes: 4 additions & 0 deletions include/IndexStoreDB/Index/IndexSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ class INDEXSTOREDB_EXPORT IndexSystem {
/// \returns `false` if the receiver returned `false` to stop receiving symbols, `true` otherwise.
bool foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver);

/// Returns the latest modification date of a unit that contains the given source file.
///
/// If no unit containing the given source file exists, returns `None`.
llvm::Optional<llvm::sys::TimePoint<>> timestampOfLatestUnitForFile(StringRef filePath);
private:
IndexSystem(void *Impl) : Impl(Impl) {}

Expand Down
6 changes: 6 additions & 0 deletions include/IndexStoreDB/Index/SymbolIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "IndexStoreDB/Support/LLVM.h"
#include "llvm/ADT/OptionSet.h"
#include "llvm/Support/Chrono.h"
#include <memory>

namespace indexstore {
Expand Down Expand Up @@ -101,6 +102,11 @@ class SymbolIndex {
///
/// \returns `false` if the receiver returned `false` to stop receiving symbols, `true` otherwise.
bool foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver);

/// Returns the latest modification date of a unit that contains the given source file.
///
/// If no unit containing the given source file exists, returns `None`.
llvm::Optional<llvm::sys::TimePoint<>> timestampOfLatestUnitForFile(CanonicalFilePathRef filePath);
private:
void *Impl; // A SymbolIndexImpl.
};
Expand Down
28 changes: 28 additions & 0 deletions lib/CIndexStoreDB/CIndexStoreDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,17 @@ indexstoredb_symbol_location_path(indexstoredb_symbol_location_t loc) {
return obj->getPath().getPathString().c_str();
}

double
indexstoredb_symbol_location_timestamp(indexstoredb_symbol_location_t loc) {
auto obj = (SymbolLocation *)loc;
// Up until C++20 the reference date of time_since_epoch is undefined but according to
// https://en.cppreference.com/w/cpp/chrono/system_clock most implementations use Unix Time.
// Since C++20, system_clock is defined to measure time since 1/1/1970.
// We rely on `time_since_epoch` always returning the nanoseconds since 1/1/1970.
auto nanosecondsSinceEpoch = obj->getPath().getModificationTime().time_since_epoch().count();
return static_cast<double>(nanosecondsSinceEpoch) / 1000 / 1000 / 1000;
}

const char *
indexstoredb_symbol_location_module_name(indexstoredb_symbol_location_t loc) {
auto obj = (SymbolLocation *)loc;
Expand Down Expand Up @@ -656,4 +667,21 @@ indexstoredb_index_unit_tests(
});
}

INDEXSTOREDB_PUBLIC double
indexstoredb_timestamp_of_latest_unit_for_file(
_Nonnull indexstoredb_index_t index,
const char *_Nonnull fileName
) {
auto obj = (Object<std::shared_ptr<IndexSystem>> *)index;
llvm::Optional<llvm::sys::TimePoint<>> timePoint = obj->value->timestampOfLatestUnitForFile(fileName);
if (timePoint) {
// Up until C++20 the reference date of time_since_epoch is undefined but according to
// https://en.cppreference.com/w/cpp/chrono/system_clock most implementations use Unix Time.
// Since C++20, system_clock is defined to measure time since 1/1/1970.
// We rely on `time_since_epoch` always returning the nanoseconds since 1/1/1970.
return timePoint->time_since_epoch().count();
}
return 0;
}

ObjectBase::~ObjectBase() {}
14 changes: 14 additions & 0 deletions lib/Index/IndexSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ class IndexSystemImpl {
///
/// \returns `false` if the receiver returned `false` to stop receiving symbols, `true` otherwise.
bool foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver);

/// Returns the latest modification date of a unit that contains the given source file.
///
/// If no unit containing the given source file exists, returns `None`.
llvm::Optional<llvm::sys::TimePoint<>> timestampOfLatestUnitForFile(StringRef filePath);
};

} // anonymous namespace
Expand Down Expand Up @@ -627,6 +632,11 @@ bool IndexSystemImpl::foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRe
return SymIndex->foreachUnitTestSymbol(std::move(receiver));
}

llvm::Optional<llvm::sys::TimePoint<>> IndexSystemImpl::timestampOfLatestUnitForFile(StringRef filePath) {
auto canonFilePath = PathIndex->getCanonicalPath(filePath);
return SymIndex->timestampOfLatestUnitForFile(canonFilePath);
}

//===----------------------------------------------------------------------===//
// IndexSystem
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -844,3 +854,7 @@ bool IndexSystem::foreachUnitTestSymbolReferencedByMainFiles(
bool IndexSystem::foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver) {
return IMPL->foreachUnitTestSymbol(std::move(receiver));
}

llvm::Optional<llvm::sys::TimePoint<>> IndexSystem::timestampOfLatestUnitForFile(StringRef filePath) {
return IMPL->timestampOfLatestUnitForFile(filePath);
}
29 changes: 29 additions & 0 deletions lib/Index/SymbolIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ class SymbolIndexImpl {
/// \returns `false` if the receiver returned `false` to stop receiving symbols, `true` otherwise.
bool foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver);

/// Returns the latest modification date of a unit that contains the given source file.
///
/// If no unit containing the given source file exists, returns `None`.
llvm::Optional<sys::TimePoint<>> timestampOfLatestUnitForFile(CanonicalFilePathRef filePath);

private:
/// Returns all the providers in the index that contain test cases and satisfy `unitFilter`.
std::vector<SymbolDataProviderRef> providersContainingTestCases(ReadTransaction &reader, function_ref<bool(const UnitInfo &)> unitFilter);
Expand Down Expand Up @@ -597,6 +602,26 @@ bool SymbolIndexImpl::foreachUnitTestSymbolOccurrence(const std::vector<SymbolDa
return true;
}

llvm::Optional<sys::TimePoint<>> SymbolIndexImpl::timestampOfLatestUnitForFile(CanonicalFilePathRef filePath) {
llvm::Optional<sys::TimePoint<>> result;

ReadTransaction reader(DBase);
IDCode filePathCode = reader.getFilePathCode(filePath);
reader.foreachUnitContainingFile(filePathCode, [&](ArrayRef<IDCode> idCodes) -> bool {
for (IDCode idCode : idCodes) {
UnitInfo unitInfo = reader.getUnitInfo(idCode);
if (!result) {
result = unitInfo.ModTime;
} else if (*result < unitInfo.ModTime) {
result = unitInfo.ModTime;
}
}
return true;
});
return result;
}


//===----------------------------------------------------------------------===//
// SymbolIndex
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -696,3 +721,7 @@ bool SymbolIndex::foreachUnitTestSymbolReferencedByMainFiles(
bool SymbolIndex::foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver) {
return IMPL->foreachUnitTestSymbol(std::move(receiver));
}

llvm::Optional<llvm::sys::TimePoint<>> SymbolIndex::timestampOfLatestUnitForFile(CanonicalFilePathRef filePath) {
return IMPL->timestampOfLatestUnitForFile(filePath);
}