Skip to content

Commit a335a47

Browse files
committed
Allow retrieval of the symbol provider kind for a source file
1 parent da098e0 commit a335a47

File tree

8 files changed

+117
-25
lines changed

8 files changed

+117
-25
lines changed

Sources/IndexStoreDB/IndexStoreDB.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ public struct PathMapping {
3535
}
3636
}
3737

38+
public enum SymbolProviderKind {
39+
case clang
40+
case swift
41+
}
42+
3843
/// IndexStoreDB index.
3944
public final class IndexStoreDB {
4045

@@ -275,6 +280,41 @@ public final class IndexStoreDB {
275280
return result
276281
}
277282

283+
public func symbolProvider(for sourceFilePath: String) -> SymbolProviderKind? {
284+
var result: SymbolProviderKind? = nil
285+
indexstoredb_index_units_containing_file(impl, sourceFilePath) { unit in
286+
let providerKind: SymbolProviderKind? = switch indexstoredb_unit_info_symbol_provider_kind(unit) {
287+
case INDEXSTOREDB_SYMBOL_PROVIDER_KIND_SWIFT:
288+
.swift
289+
case INDEXSTOREDB_SYMBOL_PROVIDER_KIND_CLANG:
290+
.clang
291+
case INDEXSTOREDB_SYMBOL_PROVIDER_KIND_UNKNOWN:
292+
nil
293+
default:
294+
preconditionFailure("Unknown enum case in indexstoredb_symbol_provider_kind_t")
295+
}
296+
297+
let mainFilePath = String(cString: indexstoredb_unit_info_main_file_path(unit))
298+
if providerKind == .swift && mainFilePath != sourceFilePath {
299+
// We have a unit that is "included" from Swift. This happens for header
300+
// files that Swift files depend on. But Swift doesn't have includes and
301+
// we shouldn't infer the header file's language to Swift based on this unit.
302+
// Ignore it.
303+
return true
304+
}
305+
306+
if result == nil {
307+
result = providerKind
308+
} else if result != providerKind {
309+
// Found two conflicting provider kinds. Return nil as we don't know the provider in this case.
310+
result = nil
311+
return false
312+
}
313+
return true
314+
}
315+
return result
316+
}
317+
278318
@discardableResult
279319
public func foreachFileIncludedByFile(path: String, body: @escaping (String) -> Bool) -> Bool {
280320
return indexstoredb_index_files_included_by_file(impl, path) { targetPath, line in

Sources/IndexStoreDB/Symbol.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ extension Symbol: Comparable {
8484
extension Symbol: CustomStringConvertible {
8585
public var description: String {
8686
if properties.isEmpty {
87-
return "\(name) | \(kind) | \(usr)"
87+
return "\(name) | \(kind) | \(usr) | \(language)"
8888
}
89-
return "\(name) | \(kind) (\(properties)) | \(usr)"
89+
return "\(name) | \(kind) (\(properties)) | \(usr) | \(language)"
9090
}
9191
}
9292

Tests/IndexStoreDBTests/IndexTests.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,21 @@ final class IndexTests: XCTestCase {
113113
checkOccurrences(cdeclOccs, expected: [
114114
cdecl.at(ws.testLoc("C:decl"), roles: [.declaration, .canonical]),
115115
cdecl.at(ws.testLoc("C:def"), roles: .definition),
116-
cdecl.at(ws.testLoc("C:ref:swift"), roles: .reference),
116+
cdecl.with(language: .swift).at(ws.testLoc("C:ref:swift"), roles: .reference),
117117
cdecl.at(ws.testLoc("C:ref:e.mm"), roles: .reference),
118118
])
119119

120120
let cmethod = Symbol(usr: "c:objc(cs)C(im)method", name: "method", kind: .instanceMethod, language: .objc)
121121
let cmethodOccs = index.occurrences(ofUSR: cmethod.usr, roles: .all)
122122
checkOccurrences(cmethodOccs, expected: [
123-
cmethod.with(name: "method()").at(ws.testLoc("C.method:call:swift"), roles: [.call, .dynamic]),
123+
cmethod.with(name: "method()", language: .swift).at(ws.testLoc("C.method:call:swift"), roles: [.call, .dynamic]),
124124
cmethod.at(ws.testLoc("C.method:decl"), roles: .declaration),
125125
cmethod.at(ws.testLoc("C.method:def"), roles: .definition),
126126
cmethod.at(ws.testLoc("C.method:call:e.mm"), roles: [.call, .dynamic]),
127127
])
128128
#endif
129129

130-
let ddecl = Symbol(usr: "c:@S@D", name: "D", kind: .class, language: .c)
130+
let ddecl = Symbol(usr: "c:@S@D", name: "D", kind: .class, language: .cxx)
131131
let dOccs = index.occurrences(ofUSR: ddecl.usr, roles: .all)
132132
checkOccurrences(dOccs, expected: [
133133
ddecl.at(ws.testLoc("D:def"), roles: .definition),
@@ -139,7 +139,7 @@ final class IndexTests: XCTestCase {
139139
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
140140
checkOccurrences(bridgingHeaderOccs, expected: [
141141
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
142-
bhdecl.with(name: "bridgingHeader()").at(ws.testLoc("bridgingHeader:call"), roles: .call),
142+
bhdecl.with(name: "bridgingHeader()", language: .swift).at(ws.testLoc("bridgingHeader:call"), roles: .call),
143143
])
144144
}
145145

@@ -154,18 +154,18 @@ final class IndexTests: XCTestCase {
154154
let index = ws.index
155155

156156
#if os(macOS)
157-
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .c)
157+
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .objc)
158158
let cdeclOccs = index.occurrences(ofUSR: cdecl.usr, roles: .all)
159159
checkOccurrences(cdeclOccs, expected: [
160160
cdecl.at(ws.testLoc("C:decl"), roles: [.declaration, .canonical]),
161161
cdecl.at(ws.testLoc("C:def"), roles: .definition),
162-
cdecl.at(ws.testLoc("C:ref:swift"), roles: .reference),
162+
cdecl.with(language: .swift).at(ws.testLoc("C:ref:swift"), roles: .reference),
163163
])
164164

165-
let cmethod = Symbol(usr: "c:objc(cs)C(im)method", name: "method", kind: .instanceMethod, language: .c)
165+
let cmethod = Symbol(usr: "c:objc(cs)C(im)method", name: "method", kind: .instanceMethod, language: .objc)
166166
let cmethodOccs = index.occurrences(ofUSR: cmethod.usr, roles: .all)
167167
checkOccurrences(cmethodOccs, expected: [
168-
cmethod.with(name: "method()").at(ws.testLoc("C.method:call:swift"), roles: [.call, .dynamic]),
168+
cmethod.with(name: "method()", language: .swift).at(ws.testLoc("C.method:call:swift"), roles: [.call, .dynamic]),
169169
cmethod.at(ws.testLoc("C.method:decl"), roles: .declaration),
170170
cmethod.at(ws.testLoc("C.method:def"), roles: .definition),
171171
])
@@ -175,7 +175,7 @@ final class IndexTests: XCTestCase {
175175
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
176176
checkOccurrences(bridgingHeaderOccs, expected: [
177177
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
178-
bhdecl.with(name: "bridgingHeader()").at(ws.testLoc("bridgingHeader:call"), roles: .call),
178+
bhdecl.with(name: "bridgingHeader()", language: .swift).at(ws.testLoc("bridgingHeader:call"), roles: .call),
179179
])
180180
}
181181

@@ -191,7 +191,7 @@ final class IndexTests: XCTestCase {
191191
let index = ws.index
192192

193193
#if os(macOS)
194-
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .c)
194+
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .objc)
195195
let getOccs = { index.occurrences(ofUSR: cdecl.usr, roles: .all) }
196196

197197
// Output units are not set yet.
@@ -209,13 +209,13 @@ final class IndexTests: XCTestCase {
209209
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
210210
checkOccurrences(bridgingHeaderOccs, expected: [
211211
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
212-
bhdecl.with(name: "bridgingHeader()").at(ws.testLoc("bridgingHeader:call"), roles: .call),
212+
bhdecl.with(name: "bridgingHeader()", language: .swift).at(ws.testLoc("bridgingHeader:call"), roles: .call),
213213
])
214214
#if os(macOS)
215215
checkOccurrences(getOccs(), expected: [
216216
cdecl.at(ws.testLoc("C:decl"), roles: [.declaration, .canonical]),
217217
cdecl.at(ws.testLoc("C:def"), roles: .definition),
218-
cdecl.at(ws.testLoc("C:ref:swift"), roles: .reference),
218+
cdecl.with(language: .swift).at(ws.testLoc("C:ref:swift"), roles: .reference),
219219
])
220220

221221
let outUnitASwift = try XCTUnwrap(indexOutputPaths.first{ $0.hasSuffix("-a.swift.o") })
@@ -239,7 +239,7 @@ final class IndexTests: XCTestCase {
239239
let index = ws.index
240240

241241
#if os(macOS)
242-
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .c)
242+
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .objc)
243243
let getOccs = { index.occurrences(ofUSR: cdecl.usr, roles: .all) }
244244

245245
// Output units are not set yet.
@@ -257,13 +257,13 @@ final class IndexTests: XCTestCase {
257257
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
258258
checkOccurrences(bridgingHeaderOccs, expected: [
259259
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
260-
bhdecl.with(name: "bridgingHeader()").at(ws.testLoc("bridgingHeader:call"), roles: .call),
260+
bhdecl.with(name: "bridgingHeader()", language: .swift).at(ws.testLoc("bridgingHeader:call"), roles: .call),
261261
])
262262
#if os(macOS)
263263
checkOccurrences(getOccs(), expected: [
264264
cdecl.at(ws.testLoc("C:decl"), roles: [.declaration, .canonical]),
265265
cdecl.at(ws.testLoc("C:def"), roles: .definition),
266-
cdecl.at(ws.testLoc("C:ref:swift"), roles: .reference),
266+
cdecl.with(language: .swift).at(ws.testLoc("C:ref:swift"), roles: .reference),
267267
])
268268

269269
let outUnitASwift = try XCTUnwrap(indexOutputPaths.first{ $0.hasSuffix("-a.swift.o") })
@@ -547,7 +547,7 @@ final class IndexTests: XCTestCase {
547547
try ws.buildAndIndex()
548548
let index = ws.index
549549

550-
let ddecl = Symbol(usr: "c:@S@D", name: "D", kind: .class, language: .c)
550+
let ddecl = Symbol(usr: "c:@S@D", name: "D", kind: .class, language: .cxx)
551551
let getOccs = { index.occurrences(ofUSR: ddecl.usr, roles: .all) }
552552

553553
// Output units are not set yet.
@@ -573,7 +573,7 @@ final class IndexTests: XCTestCase {
573573
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
574574
checkOccurrences(bridgingHeaderOccs, expected: [
575575
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
576-
bhdecl.with(name: "bridgingHeader()").at(ws.testLoc("bridgingHeader:call"), roles: .call),
576+
bhdecl.with(name: "bridgingHeader()", language: .swift).at(ws.testLoc("bridgingHeader:call"), roles: .call),
577577
])
578578
}
579579

@@ -665,7 +665,7 @@ final class IndexTests: XCTestCase {
665665

666666
try ws.buildAndIndex()
667667

668-
let largeType = Symbol(usr: "c:@CT@LargeType", name: "LargeType", kind: .concept, language: .cxx)
668+
let largeType = Symbol(usr: "c:@CT@LargeType", name: "LargeType", kind: .concept, language: .c)
669669
let largeTypeOccs = ws.index.occurrences(ofUSR: largeType.usr, roles: .all)
670670
checkOccurrences(largeTypeOccs, expected: [
671671
largeType.at(ws.testLoc("LargeType:def"), roles: .definition),

include/CIndexStoreDB/CIndexStoreDB.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ typedef enum {
144144
INDEXSTOREDB_LANGUAGE_SWIFT
145145
} indexstoredb_language_t;
146146

147+
typedef enum {
148+
INDEXSTOREDB_SYMBOL_PROVIDER_KIND_CLANG,
149+
INDEXSTOREDB_SYMBOL_PROVIDER_KIND_SWIFT,
150+
INDEXSTOREDB_SYMBOL_PROVIDER_KIND_UNKNOWN,
151+
} indexstoredb_symbol_provider_kind_t;
152+
147153
typedef void *indexstoredb_delegate_event_t;
148154

149155
/// Returns true on success.
@@ -483,6 +489,9 @@ indexstoredb_unit_info_main_file_path(_Nonnull indexstoredb_unit_info_t);
483489
INDEXSTOREDB_PUBLIC const char *_Nonnull
484490
indexstoredb_unit_info_unit_name(_Nonnull indexstoredb_unit_info_t);
485491

492+
INDEXSTOREDB_PUBLIC indexstoredb_symbol_provider_kind_t
493+
indexstoredb_unit_info_symbol_provider_kind(_Nonnull indexstoredb_unit_info_t info);
494+
486495
/// Iterates over the compilation units that contain \p path and return their units.
487496
///
488497
/// This can be used to find information for units that include a given header.

include/IndexStoreDB/Index/StoreUnitInfo.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef INDEXSTOREDB_INDEX_STOREUNITINFO_H
1414
#define INDEXSTOREDB_INDEX_STOREUNITINFO_H
1515

16+
#include "IndexStoreDB/Core/Symbol.h"
1617
#include "IndexStoreDB/Support/Path.h"
1718
#include "llvm/Support/Chrono.h"
1819
#include <string>
@@ -26,16 +27,18 @@ struct StoreUnitInfo {
2627
std::string OutFileIdentifier;
2728
bool HasTestSymbols = false;
2829
llvm::sys::TimePoint<> ModTime;
30+
Optional<SymbolProviderKind> SymProviderKind;
2931

3032
StoreUnitInfo() = default;
3133
StoreUnitInfo(std::string unitName, CanonicalFilePath mainFilePath,
3234
StringRef outFileIdentifier, bool hasTestSymbols,
33-
llvm::sys::TimePoint<> modTime)
35+
llvm::sys::TimePoint<> modTime, Optional
36+
<SymbolProviderKind> SymProviderKind)
3437
: UnitName(unitName),
3538
MainFilePath(mainFilePath),
3639
OutFileIdentifier(outFileIdentifier),
3740
HasTestSymbols(hasTestSymbols),
38-
ModTime(modTime) {}
41+
ModTime(modTime), SymProviderKind(SymProviderKind) {}
3942
};
4043

4144
} // namespace index

lib/CIndexStoreDB/CIndexStoreDB.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,20 @@ indexstoredb_unit_info_unit_name(indexstoredb_unit_info_t info) {
566566
return obj->UnitName.c_str();
567567
}
568568

569+
indexstoredb_symbol_provider_kind_t
570+
indexstoredb_unit_info_symbol_provider_kind(_Nonnull indexstoredb_unit_info_t info) {
571+
auto obj = (const StoreUnitInfo *)info;
572+
if (!obj->SymProviderKind) {
573+
return INDEXSTOREDB_SYMBOL_PROVIDER_KIND_UNKNOWN;
574+
}
575+
switch (*obj->SymProviderKind) {
576+
case IndexStoreDB::SymbolProviderKind::Clang:
577+
return INDEXSTOREDB_SYMBOL_PROVIDER_KIND_CLANG;
578+
case IndexStoreDB::SymbolProviderKind::Swift:
579+
return INDEXSTOREDB_SYMBOL_PROVIDER_KIND_SWIFT;
580+
}
581+
}
582+
569583
bool
570584
indexstoredb_index_units_containing_file(
571585
indexstoredb_index_t index,

lib/Index/FilePathIndex.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ bool FileIndexImpl::foreachMainUnitContainingFile(CanonicalFilePathRef filePath,
166166
currUnit.ModTime = unitInfo.ModTime;
167167
currUnit.MainFilePath = reader.getFullFilePathFromCode(unitInfo.MainFileCode);
168168
currUnit.OutFileIdentifier = reader.getUnitFileIdentifierFromCode(unitInfo.OutFileCode);
169+
currUnit.SymProviderKind = unitInfo.SymProviderKind;
169170
return true;
170171
});
171172
}

lib/Index/IndexDatastore.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ void StoreUnitRepo::registerUnit(StringRef unitName, bool isInitialScan, std::sh
479479
bool needDatabaseUpdate;
480480
Optional<bool> optIsSystem;
481481
Optional<bool> PrevHasTestSymbols;
482+
Optional<SymbolProviderKind> PrevSymProviderKind;
482483
IDCode PrevMainFileCode;
483484
IDCode PrevOutFileCode;
484485
Optional<StoreUnitInfo> StoreUnitInfoOpt;
@@ -498,6 +499,7 @@ void StoreUnitRepo::registerUnit(StringRef unitName, bool isInitialScan, std::sh
498499
PrevMainFileCode = unitImport.getPrevMainFileCode();
499500
PrevOutFileCode = unitImport.getPrevOutFileCode();
500501
PrevHasTestSymbols = unitImport.getHasTestSymbols();
502+
PrevSymProviderKind = unitImport.getSymbolProviderKind();
501503
return false;
502504
}
503505

@@ -595,7 +597,14 @@ void StoreUnitRepo::registerUnit(StringRef unitName, bool isInitialScan, std::sh
595597
}
596598

597599
unitImport.commit();
598-
StoreUnitInfoOpt = StoreUnitInfo{unitName, CanonMainFile, OutFileIdentifier, unitImport.getHasTestSymbols().getValue(), unitModTime};
600+
StoreUnitInfoOpt = StoreUnitInfo{
601+
unitName,
602+
CanonMainFile,
603+
OutFileIdentifier,
604+
unitImport.getHasTestSymbols().getValue(),
605+
unitModTime,
606+
unitImport.getSymbolProviderKind()
607+
};
599608
import.commit();
600609
return false;
601610
};
@@ -608,7 +617,14 @@ void StoreUnitRepo::registerUnit(StringRef unitName, bool isInitialScan, std::sh
608617
ReadTransaction reader(SymIndex->getDBase());
609618
CanonicalFilePath mainFile = reader.getFullFilePathFromCode(PrevMainFileCode);
610619
std::string outFileIdentifier = reader.getUnitFileIdentifierFromCode(PrevOutFileCode);
611-
StoreUnitInfoOpt = StoreUnitInfo{unitName, mainFile, outFileIdentifier, PrevHasTestSymbols.getValue(), unitModTime};
620+
StoreUnitInfoOpt = StoreUnitInfo{
621+
unitName,
622+
mainFile,
623+
outFileIdentifier,
624+
PrevHasTestSymbols.getValue(),
625+
unitModTime,
626+
PrevSymProviderKind.getValue()
627+
};
612628
}
613629
Delegate->processedStoreUnit(StoreUnitInfoOpt.getValue());
614630
}
@@ -816,6 +832,7 @@ void StoreUnitRepo::onUnitOutOfDate(IDCode unitCode, StringRef unitName,
816832
CanonicalFilePath MainFilePath;
817833
std::string OutFileIdentifier;
818834
bool hasTestSymbols = false;
835+
Optional<SymbolProviderKind> SymProviderKind;
819836
llvm::sys::TimePoint<> CurrModTime;
820837
SmallVector<IDCode, 8> dependentUnits;
821838
{
@@ -827,13 +844,21 @@ void StoreUnitRepo::onUnitOutOfDate(IDCode unitCode, StringRef unitName,
827844
}
828845
OutFileIdentifier = reader.getUnitFileIdentifierFromCode(unitInfo.OutFileCode);
829846
hasTestSymbols = unitInfo.HasTestSymbols;
847+
SymProviderKind = unitInfo.SymProviderKind;
830848
CurrModTime = unitInfo.ModTime;
831849
}
832850
reader.getDirectDependentUnits(unitCode, dependentUnits);
833851
}
834852

835853
if (!MainFilePath.empty() && Delegate) {
836-
StoreUnitInfo unitInfo{unitName, MainFilePath, OutFileIdentifier, hasTestSymbols, CurrModTime};
854+
StoreUnitInfo unitInfo{
855+
unitName,
856+
MainFilePath,
857+
OutFileIdentifier,
858+
hasTestSymbols,
859+
CurrModTime,
860+
SymProviderKind
861+
};
837862
Delegate->unitIsOutOfDate(unitInfo, outOfDateModTime, hint, synchronous);
838863
}
839864

0 commit comments

Comments
 (0)