Skip to content

Commit ba32ab7

Browse files
committed
Add an API to return the latest modification date of a unit that contains a given source file.
1 parent 5f15ad9 commit ba32ab7

File tree

7 files changed

+92
-0
lines changed

7 files changed

+92
-0
lines changed

Sources/IndexStoreDB/IndexStoreDB.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
@_implementationOnly
1414
import CIndexStoreDB
15+
import Foundation
1516

1617
// For `strdup`
1718
#if canImport(Glibc)
@@ -448,6 +449,19 @@ public final class IndexStoreDB {
448449
}
449450
return result
450451
}
452+
453+
/// Returns the latest modification date of a unit that contains the given source file.
454+
///
455+
/// If no unit containing the given source file exists, returns `nil`.
456+
public func dateOfLatestUnitFor(filePath: String) -> Date? {
457+
let timestamp = filePath.withCString { filePathCString in
458+
indexstoredb_timestamp_of_latest_unit_for_file(impl, filePathCString)
459+
}
460+
if timestamp == 0 {
461+
return nil
462+
}
463+
return Date(timeIntervalSince1970: timestamp)
464+
}
451465
}
452466

453467
public protocol IndexStoreLibraryProvider {

include/CIndexStoreDB/CIndexStoreDB.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,14 @@ indexstoredb_index_unit_tests(
577577
_Nonnull indexstoredb_symbol_occurrence_receiver_t receiver
578578
);
579579

580+
/// Returns a Unix timestamp (seconds since 1/1/1970) of the latest unit that contains the given source file.
581+
///
582+
/// If no unit containing the given source file exists, returns 0.
583+
INDEXSTOREDB_PUBLIC double
584+
indexstoredb_timestamp_of_latest_unit_for_file(
585+
_Nonnull indexstoredb_index_t index,
586+
const char *_Nonnull fileName
587+
);
580588

581589
INDEXSTOREDB_END_DECLS
582590

include/IndexStoreDB/Index/IndexSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ class INDEXSTOREDB_EXPORT IndexSystem {
177177
/// \returns `false` if the receiver returned `false` to stop receiving symbols, `true` otherwise.
178178
bool foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver);
179179

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

include/IndexStoreDB/Index/SymbolIndex.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "IndexStoreDB/Support/LLVM.h"
1717
#include "llvm/ADT/OptionSet.h"
18+
#include "llvm/Support/Chrono.h"
1819
#include <memory>
1920

2021
namespace indexstore {
@@ -101,6 +102,11 @@ class SymbolIndex {
101102
///
102103
/// \returns `false` if the receiver returned `false` to stop receiving symbols, `true` otherwise.
103104
bool foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver);
105+
106+
/// Returns the latest modification date of a unit that contains the given source file.
107+
///
108+
/// If no unit containing the given source file exists, returns `None`.
109+
llvm::Optional<llvm::sys::TimePoint<>> timestampOfLatestUnitForFile(CanonicalFilePathRef filePath);
104110
private:
105111
void *Impl; // A SymbolIndexImpl.
106112
};

lib/CIndexStoreDB/CIndexStoreDB.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,4 +667,21 @@ indexstoredb_index_unit_tests(
667667
});
668668
}
669669

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

lib/Index/IndexSystem.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ class IndexSystemImpl {
233233
///
234234
/// \returns `false` if the receiver returned `false` to stop receiving symbols, `true` otherwise.
235235
bool foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver);
236+
237+
/// Returns the latest modification date of a unit that contains the given source file.
238+
///
239+
/// If no unit containing the given source file exists, returns `None`.
240+
llvm::Optional<llvm::sys::TimePoint<>> timestampOfLatestUnitForFile(StringRef filePath);
236241
};
237242

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

635+
llvm::Optional<llvm::sys::TimePoint<>> IndexSystemImpl::timestampOfLatestUnitForFile(StringRef filePath) {
636+
auto canonFilePath = PathIndex->getCanonicalPath(filePath);
637+
return SymIndex->timestampOfLatestUnitForFile(canonFilePath);
638+
}
639+
630640
//===----------------------------------------------------------------------===//
631641
// IndexSystem
632642
//===----------------------------------------------------------------------===//
@@ -844,3 +854,7 @@ bool IndexSystem::foreachUnitTestSymbolReferencedByMainFiles(
844854
bool IndexSystem::foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver) {
845855
return IMPL->foreachUnitTestSymbol(std::move(receiver));
846856
}
857+
858+
llvm::Optional<llvm::sys::TimePoint<>> IndexSystem::timestampOfLatestUnitForFile(StringRef filePath) {
859+
return IMPL->timestampOfLatestUnitForFile(filePath);
860+
}

lib/Index/SymbolIndex.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ class SymbolIndexImpl {
9999
/// \returns `false` if the receiver returned `false` to stop receiving symbols, `true` otherwise.
100100
bool foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver);
101101

102+
/// Returns the latest modification date of a unit that contains the given source file.
103+
///
104+
/// If no unit containing the given source file exists, returns `None`.
105+
llvm::Optional<sys::TimePoint<>> timestampOfLatestUnitForFile(CanonicalFilePathRef filePath);
106+
102107
private:
103108
/// Returns all the providers in the index that contain test cases and satisfy `unitFilter`.
104109
std::vector<SymbolDataProviderRef> providersContainingTestCases(ReadTransaction &reader, function_ref<bool(const UnitInfo &)> unitFilter);
@@ -597,6 +602,26 @@ bool SymbolIndexImpl::foreachUnitTestSymbolOccurrence(const std::vector<SymbolDa
597602
return true;
598603
}
599604

605+
llvm::Optional<sys::TimePoint<>> SymbolIndexImpl::timestampOfLatestUnitForFile(CanonicalFilePathRef filePath) {
606+
llvm::Optional<sys::TimePoint<>> result;
607+
608+
ReadTransaction reader(DBase);
609+
IDCode filePathCode = reader.getFilePathCode(filePath);
610+
reader.foreachUnitContainingFile(filePathCode, [&](ArrayRef<IDCode> idCodes) -> bool {
611+
for (IDCode idCode : idCodes) {
612+
UnitInfo unitInfo = reader.getUnitInfo(idCode);
613+
if (!result) {
614+
result = unitInfo.ModTime;
615+
} else if (*result < unitInfo.ModTime) {
616+
result = unitInfo.ModTime;
617+
}
618+
}
619+
return true;
620+
});
621+
return result;
622+
}
623+
624+
600625
//===----------------------------------------------------------------------===//
601626
// SymbolIndex
602627
//===----------------------------------------------------------------------===//
@@ -696,3 +721,7 @@ bool SymbolIndex::foreachUnitTestSymbolReferencedByMainFiles(
696721
bool SymbolIndex::foreachUnitTestSymbol(function_ref<bool(SymbolOccurrenceRef Occur)> receiver) {
697722
return IMPL->foreachUnitTestSymbol(std::move(receiver));
698723
}
724+
725+
llvm::Optional<llvm::sys::TimePoint<>> SymbolIndex::timestampOfLatestUnitForFile(CanonicalFilePathRef filePath) {
726+
return IMPL->timestampOfLatestUnitForFile(filePath);
727+
}

0 commit comments

Comments
 (0)