From 98a162124b52343e6fbd467a0c21af71c87b9c54 Mon Sep 17 00:00:00 2001 From: taylorswift Date: Mon, 3 Jun 2024 23:00:25 +0000 Subject: [PATCH 1/6] add API for querying all symbol occurrences within a file --- Sources/IndexStoreDB/IndexStoreDB.swift | 26 +++++++++++-- include/CIndexStoreDB/CIndexStoreDB.h | 9 +++++ include/IndexStoreDB/Index/IndexSystem.h | 5 ++- .../IndexStoreDB/Index/SymbolDataProvider.h | 2 + include/IndexStoreDB/Index/SymbolIndex.h | 5 ++- lib/CIndexStoreDB/CIndexStoreDB.cpp | 10 +++++ lib/Index/IndexSystem.cpp | 26 ++++++++++--- lib/Index/StoreSymbolRecord.cpp | 14 +++++++ lib/Index/StoreSymbolRecord.h | 2 + lib/Index/SymbolIndex.cpp | 39 ++++++++++++++++++- 10 files changed, 124 insertions(+), 14 deletions(-) diff --git a/Sources/IndexStoreDB/IndexStoreDB.swift b/Sources/IndexStoreDB/IndexStoreDB.swift index ff34570d..9d9da072 100644 --- a/Sources/IndexStoreDB/IndexStoreDB.swift +++ b/Sources/IndexStoreDB/IndexStoreDB.swift @@ -300,7 +300,7 @@ public final class IndexStoreDB { } return result } - + public func symbolProvider(for sourceFilePath: String) -> SymbolProviderKind? { var result: SymbolProviderKind? = nil indexstoredb_index_units_containing_file(impl, sourceFilePath) { unit in @@ -345,7 +345,7 @@ public final class IndexStoreDB { } } } - + public func filesIncludedByFile(path: String) -> [String] { var result: [String] = [] foreachFileIncludedByFile(path: path) { targetPath in @@ -354,7 +354,7 @@ public final class IndexStoreDB { } return result } - + @discardableResult public func foreachFileIncludingFile(path: String, body: (String) -> Bool) -> Bool { return withoutActuallyEscaping(body) { body in @@ -364,7 +364,7 @@ public final class IndexStoreDB { } } } - + public func filesIncludingFile(path: String) -> [String] { var result: [String] = [] foreachFileIncludingFile(path: path) { targetPath in @@ -445,6 +445,15 @@ public final class IndexStoreDB { return result } + public func symbolOccurrences(inFilePath path: String) -> [SymbolOccurrence] { + var result: [SymbolOccurrence] = [] + forEachSymbolOccurrence(inFilePath: path) { occur in + result.append(occur) + return true + } + return result + } + @discardableResult func forEachSymbol(inFilePath filePath: String, body: (Symbol) -> Bool) -> Bool { return withoutActuallyEscaping(body) { body in @@ -454,6 +463,15 @@ public final class IndexStoreDB { } } + @discardableResult + func forEachSymbolOccurrence(inFilePath filePath: String, body: (SymbolOccurrence) -> Bool) -> Bool { + return withoutActuallyEscaping(body) { body in + return indexstoredb_index_symbol_occurrences_in_file_path(impl, filePath) { occur in + return body(SymbolOccurrence(occur)) + } + } + } + /// Returns all unit test symbol in unit files that reference one of the main files in `mainFilePaths`. public func unitTests(referencedByMainFiles mainFilePaths: [String]) -> [SymbolOccurrence] { var result: [SymbolOccurrence] = [] diff --git a/include/CIndexStoreDB/CIndexStoreDB.h b/include/CIndexStoreDB/CIndexStoreDB.h index 97110279..1833083f 100644 --- a/include/CIndexStoreDB/CIndexStoreDB.h +++ b/include/CIndexStoreDB/CIndexStoreDB.h @@ -328,6 +328,15 @@ indexstoredb_index_symbols_contained_in_file_path(_Nonnull indexstoredb_index_t const char *_Nonnull path, _Nonnull indexstoredb_symbol_receiver_t); +/// Iterates over all the symbol occurrences contained in \p path +/// +/// The occurrence passed to the receiver is only valid for the duration of the +/// receiver call. +INDEXSTOREDB_PUBLIC bool +indexstoredb_index_symbol_occurrences_in_file_path(_Nonnull indexstoredb_index_t index, + const char *_Nonnull path, + _Nonnull indexstoredb_symbol_occurrence_receiver_t); + /// Returns the USR of the given symbol. /// /// The string has the same lifetime as the \c indexstoredb_symbol_t. diff --git a/include/IndexStoreDB/Index/IndexSystem.h b/include/IndexStoreDB/Index/IndexSystem.h index f7f16e11..18945270 100644 --- a/include/IndexStoreDB/Index/IndexSystem.h +++ b/include/IndexStoreDB/Index/IndexSystem.h @@ -104,6 +104,9 @@ class INDEXSTOREDB_EXPORT IndexSystem { bool foreachSymbolInFilePath(StringRef FilePath, function_ref Receiver); + bool foreachSymbolOccurrenceInFilePath(StringRef FilePath, + function_ref Receiver); + bool foreachSymbolOccurrenceByUSR(StringRef USR, SymbolRoleSet RoleSet, function_ref Receiver); @@ -178,7 +181,7 @@ class INDEXSTOREDB_EXPORT IndexSystem { bool foreachUnitTestSymbol(function_ref 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> timestampOfLatestUnitForFile(StringRef filePath); private: diff --git a/include/IndexStoreDB/Index/SymbolDataProvider.h b/include/IndexStoreDB/Index/SymbolDataProvider.h index a4d8fe04..bec4d421 100644 --- a/include/IndexStoreDB/Index/SymbolDataProvider.h +++ b/include/IndexStoreDB/Index/SymbolDataProvider.h @@ -48,6 +48,8 @@ class SymbolDataProvider { SymbolRoleSet Roles, SymbolRoleSet RelatedRoles)> Receiver) = 0; + virtual bool foreachSymbolOccurrence(function_ref Receiver) = 0; + virtual bool foreachSymbolOccurrenceByUSR(ArrayRef USRs, SymbolRoleSet RoleSet, function_ref Receiver) = 0; diff --git a/include/IndexStoreDB/Index/SymbolIndex.h b/include/IndexStoreDB/Index/SymbolIndex.h index 08c7b346..28655f43 100644 --- a/include/IndexStoreDB/Index/SymbolIndex.h +++ b/include/IndexStoreDB/Index/SymbolIndex.h @@ -68,6 +68,9 @@ class SymbolIndex { bool foreachSymbolInFilePath(CanonicalFilePathRef filePath, function_ref Receiver); + bool foreachSymbolOccurrenceInFilePath(CanonicalFilePathRef filePath, + function_ref Receiver); + bool foreachCanonicalSymbolOccurrenceContainingPattern(StringRef Pattern, bool AnchorStart, bool AnchorEnd, @@ -104,7 +107,7 @@ class SymbolIndex { bool foreachUnitTestSymbol(function_ref 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> timestampOfLatestUnitForFile(CanonicalFilePathRef filePath); private: diff --git a/lib/CIndexStoreDB/CIndexStoreDB.cpp b/lib/CIndexStoreDB/CIndexStoreDB.cpp index f344e24c..0d0ab565 100644 --- a/lib/CIndexStoreDB/CIndexStoreDB.cpp +++ b/lib/CIndexStoreDB/CIndexStoreDB.cpp @@ -314,6 +314,16 @@ indexstoredb_index_symbols_contained_in_file_path(_Nonnull indexstoredb_index_t }); } +bool +indexstoredb_index_symbol_occurrences_in_file_path(_Nonnull indexstoredb_index_t index, + const char *_Nonnull path, + _Nonnull indexstoredb_symbol_occurrence_receiver_t receiver) { + auto obj = (Object> *)index; + return obj->value->foreachSymbolOccurrenceInFilePath(path, [&](SymbolOccurrenceRef Occur) -> bool { + return receiver((indexstoredb_symbol_occurrence_t)Occur.get()); + }); +} + const char * indexstoredb_symbol_usr(indexstoredb_symbol_t symbol) { auto value = (Symbol *)symbol; diff --git a/lib/Index/IndexSystem.cpp b/lib/Index/IndexSystem.cpp index 7ea9eb31..3f3fcf8b 100644 --- a/lib/Index/IndexSystem.cpp +++ b/lib/Index/IndexSystem.cpp @@ -160,11 +160,14 @@ class IndexSystemImpl { void addDelegate(std::shared_ptr Delegate); - bool foreachSymbolInFilePath(StringRef filePath, - function_ref receiver); - - bool foreachSymbolOccurrenceByUSR(StringRef USR, SymbolRoleSet RoleSet, - function_ref Receiver); + bool foreachSymbolInFilePath(StringRef filePath, + function_ref receiver); + + bool foreachSymbolOccurrenceInFilePath(StringRef filePath, + function_ref Receiver); + + bool foreachSymbolOccurrenceByUSR(StringRef USR, SymbolRoleSet RoleSet, + function_ref Receiver); bool foreachCanonicalSymbolOccurrenceContainingPattern(StringRef Pattern, bool AnchorStart, @@ -236,7 +239,7 @@ class IndexSystemImpl { bool foreachUnitTestSymbol(function_ref 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> timestampOfLatestUnitForFile(StringRef filePath); }; @@ -579,6 +582,12 @@ bool IndexSystemImpl::foreachSymbolInFilePath(StringRef filePath, return SymIndex->foreachSymbolInFilePath(canonPath, std::move(receiver)); } +bool IndexSystemImpl::foreachSymbolOccurrenceInFilePath(StringRef filePath, + function_ref Receiver) { + auto canonPath = PathIndex->getCanonicalPath(filePath); + return SymIndex->foreachSymbolOccurrenceInFilePath(canonPath, std::move(Receiver)); +} + bool IndexSystemImpl::foreachFileOfUnit(StringRef unitName, bool followDependencies, function_ref receiver) { @@ -778,6 +787,11 @@ bool IndexSystem::foreachSymbolInFilePath(StringRef FilePath, return IMPL->foreachSymbolInFilePath(FilePath, std::move(Receiver)); } +bool IndexSystem::foreachSymbolOccurrenceInFilePath(StringRef FilePath, + function_ref Receiver) { + return IMPL->foreachSymbolOccurrenceInFilePath(FilePath, std::move(Receiver)); +} + bool IndexSystem::isKnownFile(StringRef filePath) { return IMPL->isKnownFile(filePath); } diff --git a/lib/Index/StoreSymbolRecord.cpp b/lib/Index/StoreSymbolRecord.cpp index a1f5190e..e8cd0974 100644 --- a/lib/Index/StoreSymbolRecord.cpp +++ b/lib/Index/StoreSymbolRecord.cpp @@ -289,6 +289,20 @@ bool StoreSymbolRecord::foreachCoreSymbolData(function_ref Receiver) { + bool Finished; + bool Err = doForData([&](IndexRecordReader &Reader) { + // Return all occurrences. + auto Pred = [](IndexRecordOccurrence) -> bool { return true; }; + PredOccurrenceConverter Converter(*this, Pred, Receiver); + Finished = Reader.foreachOccurrence(/*symbolsFilter=*/None, + /*relatedSymbolsFilter=*/None, + Converter); + }); + + return !Err && Finished; +} + static void searchDeclsByUSR(IndexRecordReader &Reader, ArrayRef USRs, SmallVectorImpl &FoundDecls) { diff --git a/lib/Index/StoreSymbolRecord.h b/lib/Index/StoreSymbolRecord.h index 07488220..c3566ca3 100644 --- a/lib/Index/StoreSymbolRecord.h +++ b/lib/Index/StoreSymbolRecord.h @@ -75,6 +75,8 @@ class StoreSymbolRecord : public SymbolDataProvider { SymbolRoleSet Roles, SymbolRoleSet RelatedRoles)> Receiver) override; + virtual bool foreachSymbolOccurrence(function_ref Receiver) override; + virtual bool foreachSymbolOccurrenceByUSR(ArrayRef USRs, SymbolRoleSet RoleSet, function_ref Receiver) override; diff --git a/lib/Index/SymbolIndex.cpp b/lib/Index/SymbolIndex.cpp index 8b242096..312d76fd 100644 --- a/lib/Index/SymbolIndex.cpp +++ b/lib/Index/SymbolIndex.cpp @@ -76,6 +76,9 @@ class SymbolIndexImpl { bool foreachSymbolInFilePath(CanonicalFilePathRef filePath, function_ref Receiver); + bool foreachSymbolOccurrenceInFilePath(CanonicalFilePathRef filePath, + function_ref Receiver); + bool foreachSymbolName(function_ref receiver); bool foreachCanonicalSymbolOccurrenceByUSR(StringRef USR, @@ -100,7 +103,7 @@ class SymbolIndexImpl { bool foreachUnitTestSymbol(function_ref 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> timestampOfLatestUnitForFile(CanonicalFilePathRef filePath); @@ -481,7 +484,7 @@ bool SymbolIndexImpl::foreachSymbolInFilePath(CanonicalFilePathRef filePath, SymbolInfo info, SymbolRoleSet roles, SymbolRoleSet relatedRoles) -> bool { - + if (roles.containsAny(SymbolRoleSet(SymbolRole::Definition) | SymbolRole::Declaration)) { return Receiver(std::make_shared(info, name, usr)); } else { @@ -500,6 +503,33 @@ bool SymbolIndexImpl::foreachSymbolInFilePath(CanonicalFilePathRef filePath, return didFinish; } +bool SymbolIndexImpl::foreachSymbolOccurrenceInFilePath(CanonicalFilePathRef filePath, + function_ref Receiver) { + bool didFinish = true; + ReadTransaction reader(DBase); + + IDCode filePathCode = reader.getFilePathCode(filePath); + reader.foreachUnitContainingFile(filePathCode, [&](ArrayRef idCodes) -> bool { + for (IDCode idCode : idCodes) { + UnitInfo unitInfo = reader.getUnitInfo(idCode); + + for (UnitInfo::Provider provider : unitInfo.ProviderDepends) { + IDCode providerCode = provider.ProviderCode; + if (provider.FileCode == filePathCode) { + auto record = createVisibleProviderForCode(providerCode, reader); + didFinish = record->foreachSymbolOccurrence(Receiver); + + return false; + } + } + } + + return true; + }); + + return didFinish; +} + bool SymbolIndexImpl::foreachCanonicalSymbolOccurrenceByKind(SymbolKind symKind, bool workspaceOnly, function_ref Receiver) { return foreachCanonicalSymbolOccurrenceImpl(workspaceOnly, @@ -706,6 +736,11 @@ bool SymbolIndex::foreachSymbolInFilePath(CanonicalFilePathRef filePath, return IMPL->foreachSymbolInFilePath(filePath, std::move(Receiver)); } +bool SymbolIndex::foreachSymbolOccurrenceInFilePath(CanonicalFilePathRef filePath, + function_ref Receiver) { + return IMPL->foreachSymbolOccurrenceInFilePath(filePath, std::move(Receiver)); +} + bool SymbolIndex::foreachUnitTestSymbolReferencedByOutputPaths(ArrayRef FilePaths, function_ref Receiver) { return IMPL->foreachUnitTestSymbolReferencedByOutputPaths(FilePaths, std::move(Receiver)); From 2ef13f914518765f1626eeb5ef2c12271502e331 Mon Sep 17 00:00:00 2001 From: taylorswift Date: Mon, 3 Jun 2024 23:01:07 +0000 Subject: [PATCH 2/6] gitignore .vscode for the next person who contributes from VSCode --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0f6ea2cd..11195f21 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +.vscode default.profraw Package.resolved /.build From 97d610ebadcd193b5a78d503f76ee4a6df137fc6 Mon Sep 17 00:00:00 2001 From: taylorswift Date: Tue, 4 Jun 2024 17:50:12 -0500 Subject: [PATCH 3/6] cleanup diff --- Sources/IndexStoreDB/IndexStoreDB.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/IndexStoreDB/IndexStoreDB.swift b/Sources/IndexStoreDB/IndexStoreDB.swift index 7eebf74b..bd6a4a2a 100644 --- a/Sources/IndexStoreDB/IndexStoreDB.swift +++ b/Sources/IndexStoreDB/IndexStoreDB.swift @@ -311,7 +311,7 @@ public final class IndexStoreDB { } return result } - + public func symbolProvider(for sourceFilePath: String) -> SymbolProviderKind? { var result: SymbolProviderKind? = nil indexstoredb_index_units_containing_file(impl, sourceFilePath) { unit in From 6125052cfa58db0dd0826ad7352265207b5d6bd7 Mon Sep 17 00:00:00 2001 From: taylorswift Date: Sat, 8 Jun 2024 04:00:16 +0000 Subject: [PATCH 4/6] correct merge resolution error --- Sources/IndexStoreDB/IndexStoreDB.swift | 35 ------------------------- 1 file changed, 35 deletions(-) diff --git a/Sources/IndexStoreDB/IndexStoreDB.swift b/Sources/IndexStoreDB/IndexStoreDB.swift index bd6a4a2a..0a632ab6 100644 --- a/Sources/IndexStoreDB/IndexStoreDB.swift +++ b/Sources/IndexStoreDB/IndexStoreDB.swift @@ -312,41 +312,6 @@ public final class IndexStoreDB { return result } - public func symbolProvider(for sourceFilePath: String) -> SymbolProviderKind? { - var result: SymbolProviderKind? = nil - indexstoredb_index_units_containing_file(impl, sourceFilePath) { unit in - let providerKind: SymbolProviderKind? = switch indexstoredb_unit_info_symbol_provider_kind(unit) { - case INDEXSTOREDB_SYMBOL_PROVIDER_KIND_SWIFT: - .swift - case INDEXSTOREDB_SYMBOL_PROVIDER_KIND_CLANG: - .clang - case INDEXSTOREDB_SYMBOL_PROVIDER_KIND_UNKNOWN: - nil - default: - preconditionFailure("Unknown enum case in indexstoredb_symbol_provider_kind_t") - } - - let mainFilePath = String(cString: indexstoredb_unit_info_main_file_path(unit)) - if providerKind == .swift && mainFilePath != sourceFilePath { - // We have a unit that is "included" from Swift. This happens for header - // files that Swift files depend on. But Swift doesn't have includes and - // we shouldn't infer the header file's language to Swift based on this unit. - // Ignore it. - return true - } - - if result == nil { - result = providerKind - } else if result != providerKind { - // Found two conflicting provider kinds. Return nil as we don't know the provider in this case. - result = nil - return false - } - return true - } - return result - } - @discardableResult public func foreachFileIncludedByFile(path: String, body: (String) -> Bool) -> Bool { return withoutActuallyEscaping(body) { body in From 103c995b41a83a321067d38bb88dc4b25ee03a16 Mon Sep 17 00:00:00 2001 From: taylorswift Date: Sat, 8 Jun 2024 04:02:16 +0000 Subject: [PATCH 5/6] indentation --- lib/Index/StoreSymbolRecord.cpp | 2 +- lib/Index/SymbolIndex.cpp | 34 ++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/Index/StoreSymbolRecord.cpp b/lib/Index/StoreSymbolRecord.cpp index e8cd0974..634ff844 100644 --- a/lib/Index/StoreSymbolRecord.cpp +++ b/lib/Index/StoreSymbolRecord.cpp @@ -292,7 +292,7 @@ bool StoreSymbolRecord::foreachCoreSymbolData(function_ref Receiver) { bool Finished; bool Err = doForData([&](IndexRecordReader &Reader) { - // Return all occurrences. + // Return all occurrences. auto Pred = [](IndexRecordOccurrence) -> bool { return true; }; PredOccurrenceConverter Converter(*this, Pred, Receiver); Finished = Reader.foreachOccurrence(/*symbolsFilter=*/None, diff --git a/lib/Index/SymbolIndex.cpp b/lib/Index/SymbolIndex.cpp index 312d76fd..3ee039d5 100644 --- a/lib/Index/SymbolIndex.cpp +++ b/lib/Index/SymbolIndex.cpp @@ -505,29 +505,29 @@ bool SymbolIndexImpl::foreachSymbolInFilePath(CanonicalFilePathRef filePath, bool SymbolIndexImpl::foreachSymbolOccurrenceInFilePath(CanonicalFilePathRef filePath, function_ref Receiver) { - bool didFinish = true; - ReadTransaction reader(DBase); + bool didFinish = true; + ReadTransaction reader(DBase); - IDCode filePathCode = reader.getFilePathCode(filePath); - reader.foreachUnitContainingFile(filePathCode, [&](ArrayRef idCodes) -> bool { - for (IDCode idCode : idCodes) { - UnitInfo unitInfo = reader.getUnitInfo(idCode); + IDCode filePathCode = reader.getFilePathCode(filePath); + reader.foreachUnitContainingFile(filePathCode, [&](ArrayRef idCodes) -> bool { + for (IDCode idCode : idCodes) { + UnitInfo unitInfo = reader.getUnitInfo(idCode); - for (UnitInfo::Provider provider : unitInfo.ProviderDepends) { - IDCode providerCode = provider.ProviderCode; - if (provider.FileCode == filePathCode) { - auto record = createVisibleProviderForCode(providerCode, reader); - didFinish = record->foreachSymbolOccurrence(Receiver); + for (UnitInfo::Provider provider : unitInfo.ProviderDepends) { + IDCode providerCode = provider.ProviderCode; + if (provider.FileCode == filePathCode) { + auto record = createVisibleProviderForCode(providerCode, reader); + didFinish = record->foreachSymbolOccurrence(Receiver); - return false; - } - } + return false; } + } + } - return true; - }); + return true; + }); - return didFinish; + return didFinish; } bool SymbolIndexImpl::foreachCanonicalSymbolOccurrenceByKind(SymbolKind symKind, bool workspaceOnly, From da980455bf2bbbffeffe1946dfc3665eb03c3bcd Mon Sep 17 00:00:00 2001 From: taylorswift Date: Fri, 7 Jun 2024 23:05:26 -0500 Subject: [PATCH 6/6] Update comment in include/CIndexStoreDB/CIndexStoreDB.h Co-authored-by: Alex Hoppen --- include/CIndexStoreDB/CIndexStoreDB.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/CIndexStoreDB/CIndexStoreDB.h b/include/CIndexStoreDB/CIndexStoreDB.h index 752c4878..734e823c 100644 --- a/include/CIndexStoreDB/CIndexStoreDB.h +++ b/include/CIndexStoreDB/CIndexStoreDB.h @@ -328,7 +328,7 @@ indexstoredb_index_symbols_contained_in_file_path(_Nonnull indexstoredb_index_t const char *_Nonnull path, _Nonnull indexstoredb_symbol_receiver_t); -/// Iterates over all the symbol occurrences contained in \p path +/// Iterates over all the symbol occurrences contained in the source file at \p path /// /// The occurrence passed to the receiver is only valid for the duration of the /// receiver call.