Skip to content

Commit da098e0

Browse files
committed
Add an API to get the language in which a symbol is defined
1 parent 5eac09c commit da098e0

File tree

4 files changed

+96
-29
lines changed

4 files changed

+96
-29
lines changed

Sources/IndexStoreDB/Symbol.swift

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,33 @@ public enum IndexSymbolKind: Hashable {
4545
case commentTag
4646
}
4747

48+
public enum Language: Hashable {
49+
case c
50+
case cxx
51+
case objc
52+
case swift
53+
}
54+
4855
public struct Symbol: Equatable {
4956

5057
public var usr: String
5158
public var name: String
5259
public var kind: IndexSymbolKind
5360
public var properties: SymbolProperty
61+
public var language: Language
5462

55-
public init(usr: String, name: String, kind: IndexSymbolKind, properties: SymbolProperty = SymbolProperty()) {
63+
public init(
64+
usr: String,
65+
name: String,
66+
kind: IndexSymbolKind,
67+
properties: SymbolProperty = SymbolProperty(),
68+
language: Language
69+
) {
5670
self.usr = usr
5771
self.name = name
5872
self.kind = kind
5973
self.properties = properties
74+
self.language = language
6075
}
6176
}
6277

@@ -82,9 +97,16 @@ extension Symbol {
8297
name: String? = nil,
8398
usr: String? = nil,
8499
kind: IndexSymbolKind? = nil,
85-
properties: SymbolProperty? = nil) -> Symbol
86-
{
87-
return Symbol(usr: usr ?? self.usr, name: name ?? self.name, kind: kind ?? self.kind, properties: properties ?? self.properties)
100+
properties: SymbolProperty? = nil,
101+
language: Language? = nil
102+
) -> Symbol {
103+
return Symbol(
104+
usr: usr ?? self.usr,
105+
name: name ?? self.name,
106+
kind: kind ?? self.kind,
107+
properties: properties ?? self.properties,
108+
language: language ?? self.language
109+
)
88110
}
89111

90112
/// Returns a SymbolOccurrence with the given location and roles.
@@ -95,6 +117,23 @@ extension Symbol {
95117

96118
// MARK: CIndexStoreDB conversions
97119

120+
fileprivate extension Language {
121+
init(_ value: indexstoredb_language_t) {
122+
switch value {
123+
case INDEXSTOREDB_LANGUAGE_C:
124+
self = .c
125+
case INDEXSTOREDB_LANGUAGE_CXX:
126+
self = .cxx
127+
case INDEXSTOREDB_LANGUAGE_OBJC:
128+
self = .objc
129+
case INDEXSTOREDB_LANGUAGE_SWIFT:
130+
self = .swift
131+
default:
132+
preconditionFailure("Unhandled case from C enum indexstoredb_language_t")
133+
}
134+
}
135+
}
136+
98137
extension Symbol {
99138

100139
/// Note: `value` is expected to be passed +1.
@@ -103,7 +142,9 @@ extension Symbol {
103142
usr: String(cString: indexstoredb_symbol_usr(value)),
104143
name: String(cString: indexstoredb_symbol_name(value)),
105144
kind: IndexSymbolKind(indexstoredb_symbol_kind(value)),
106-
properties: SymbolProperty(rawValue: indexstoredb_symbol_properties(value)))
145+
properties: SymbolProperty(rawValue: indexstoredb_symbol_properties(value)),
146+
language: Language(indexstoredb_symbol_language(value))
147+
)
107148
}
108149
}
109150

Tests/IndexStoreDBTests/IndexTests.swift

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ final class IndexTests: XCTestCase {
4141

4242
try ws.buildAndIndex()
4343

44-
let csym = Symbol(usr: usr, name: "c()", kind: .function)
45-
let asym = Symbol(usr: "s:4main1ayyF", name: "a()", kind: .function)
44+
let csym = Symbol(usr: usr, name: "c()", kind: .function, language: .swift)
45+
let asym = Symbol(usr: "s:4main1ayyF", name: "a()", kind: .function, language: .swift)
4646

4747
let ccanon = SymbolOccurrence(
4848
symbol: csym,
@@ -92,7 +92,7 @@ final class IndexTests: XCTestCase {
9292
[
9393
ccall,
9494
SymbolOccurrence(
95-
symbol: Symbol(usr: "s:4main1byyF", name: "b()", kind: .function),
95+
symbol: Symbol(usr: "s:4main1byyF", name: "b()", kind: .function, language: .swift),
9696
location: SymbolLocation(ws.testLoc("b:call")),
9797
roles: [.reference, .call, .calledBy, .containedBy],
9898
relations: [
@@ -108,7 +108,7 @@ final class IndexTests: XCTestCase {
108108

109109
#if os(macOS)
110110

111-
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class)
111+
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .objc)
112112
let cdeclOccs = index.occurrences(ofUSR: cdecl.usr, roles: .all)
113113
checkOccurrences(cdeclOccs, expected: [
114114
cdecl.at(ws.testLoc("C:decl"), roles: [.declaration, .canonical]),
@@ -117,7 +117,7 @@ final class IndexTests: XCTestCase {
117117
cdecl.at(ws.testLoc("C:ref:e.mm"), roles: .reference),
118118
])
119119

120-
let cmethod = Symbol(usr: "c:objc(cs)C(im)method", name: "method", kind: .instanceMethod)
120+
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: [
123123
cmethod.with(name: "method()").at(ws.testLoc("C.method:call:swift"), roles: [.call, .dynamic]),
@@ -127,15 +127,15 @@ final class IndexTests: XCTestCase {
127127
])
128128
#endif
129129

130-
let ddecl = Symbol(usr: "c:@S@D", name: "D", kind: .class)
130+
let ddecl = Symbol(usr: "c:@S@D", name: "D", kind: .class, language: .c)
131131
let dOccs = index.occurrences(ofUSR: ddecl.usr, roles: .all)
132132
checkOccurrences(dOccs, expected: [
133133
ddecl.at(ws.testLoc("D:def"), roles: .definition),
134134
ddecl.at(ws.testLoc("D:ref"), roles: .reference),
135135
ddecl.at(ws.testLoc("D:ref:e.mm"), roles: .reference),
136136
])
137137

138-
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function)
138+
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function, language: .c)
139139
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
140140
checkOccurrences(bridgingHeaderOccs, expected: [
141141
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
@@ -154,15 +154,15 @@ 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)
157+
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .c)
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),
162162
cdecl.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)
165+
let cmethod = Symbol(usr: "c:objc(cs)C(im)method", name: "method", kind: .instanceMethod, language: .c)
166166
let cmethodOccs = index.occurrences(ofUSR: cmethod.usr, roles: .all)
167167
checkOccurrences(cmethodOccs, expected: [
168168
cmethod.with(name: "method()").at(ws.testLoc("C.method:call:swift"), roles: [.call, .dynamic]),
@@ -171,7 +171,7 @@ final class IndexTests: XCTestCase {
171171
])
172172
#endif
173173

174-
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function)
174+
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function, language: .c)
175175
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
176176
checkOccurrences(bridgingHeaderOccs, expected: [
177177
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
@@ -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)
194+
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .c)
195195
let getOccs = { index.occurrences(ofUSR: cdecl.usr, roles: .all) }
196196

197197
// Output units are not set yet.
@@ -205,7 +205,7 @@ final class IndexTests: XCTestCase {
205205
index.addUnitOutFilePaths(indexOutputPaths, waitForProcessing: true)
206206

207207
// The bridging header is referenced as a PCH unit dependency, make sure we can see the data.
208-
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function)
208+
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function, language: .c)
209209
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
210210
checkOccurrences(bridgingHeaderOccs, expected: [
211211
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
@@ -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)
242+
let cdecl = Symbol(usr: "c:objc(cs)C", name: "C", kind: .class, language: .c)
243243
let getOccs = { index.occurrences(ofUSR: cdecl.usr, roles: .all) }
244244

245245
// Output units are not set yet.
@@ -253,7 +253,7 @@ final class IndexTests: XCTestCase {
253253
index.addUnitOutFilePaths(indexOutputPaths, waitForProcessing: true)
254254

255255
// The bridging header is referenced as a PCH unit dependency, make sure we can see the data.
256-
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function)
256+
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function, language: .c)
257257
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
258258
checkOccurrences(bridgingHeaderOccs, expected: [
259259
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
@@ -279,7 +279,7 @@ final class IndexTests: XCTestCase {
279279
guard let ws = try staticTibsTestWorkspace(name: "SwiftModules") else { return }
280280
try ws.buildAndIndex()
281281

282-
let aaa = Symbol(usr: "s:1A3aaayyF", name: "aaa()", kind: .function)
282+
let aaa = Symbol(usr: "s:1A3aaayyF", name: "aaa()", kind: .function, language: .swift)
283283
checkOccurrences(ws.index.occurrences(ofUSR: aaa.usr, roles: .all), expected: [
284284
aaa.at(ws.testLoc("aaa:def"), moduleName: "A", roles: .definition),
285285
aaa.at(ws.testLoc("aaa:call"), moduleName: "B", roles: .call),
@@ -291,7 +291,7 @@ final class IndexTests: XCTestCase {
291291
guard let ws = try mutableTibsTestWorkspace(name: "proj1") else { return }
292292
try ws.buildAndIndex()
293293

294-
let cdecl = Symbol(usr: "s:4main1cyyF", name: "c()", kind: .function)
294+
let cdecl = Symbol(usr: "s:4main1cyyF", name: "c()", kind: .function, language: .swift)
295295
let roles: SymbolRole = [.reference, .definition, .declaration]
296296

297297
checkOccurrences(ws.index.occurrences(ofUSR: cdecl.usr, roles: .all), expected: [
@@ -348,7 +348,7 @@ final class IndexTests: XCTestCase {
348348
waitUntilDoneInitializing: true,
349349
listenToUnitEvents: true)
350350

351-
let csym = Symbol(usr: "s:4main1cyyF", name: "c()", kind: .function)
351+
let csym = Symbol(usr: "s:4main1cyyF", name: "c()", kind: .function, language: .swift)
352352
let waitOccs = indexWait.occurrences(ofUSR: csym.usr, roles: [.reference, .definition])
353353

354354
checkOccurrences(waitOccs, expected: [
@@ -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)
550+
let ddecl = Symbol(usr: "c:@S@D", name: "D", kind: .class, language: .c)
551551
let getOccs = { index.occurrences(ofUSR: ddecl.usr, roles: .all) }
552552

553553
// Output units are not set yet.
@@ -569,7 +569,7 @@ final class IndexTests: XCTestCase {
569569
])
570570

571571
// The bridging header is referenced as a PCH unit dependency, make sure we can see the data.
572-
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function)
572+
let bhdecl = Symbol(usr: "c:@F@bridgingHeader", name: "bridgingHeader", kind: .function, language: .c)
573573
let bridgingHeaderOccs = index.occurrences(ofUSR: bhdecl.usr, roles: .all)
574574
checkOccurrences(bridgingHeaderOccs, expected: [
575575
bhdecl.at(ws.testLoc("bridgingHeader:decl"), roles: .declaration),
@@ -634,25 +634,25 @@ final class IndexTests: XCTestCase {
634634

635635
try ws.buildAndIndex()
636636

637-
let asyncFuncSym = Symbol(usr: "s:4main9asyncFuncyyYaF", name: "asyncFunc()", kind: .function, properties: .swiftAsync)
637+
let asyncFuncSym = Symbol(usr: "s:4main9asyncFuncyyYaF", name: "asyncFunc()", kind: .function, properties: .swiftAsync, language: .swift)
638638
let asyncFuncOccs = index.occurrences(ofUSR: asyncFuncSym.usr, roles: .definition)
639639
checkOccurrences(asyncFuncOccs, expected: [
640640
asyncFuncSym.at(ws.testLoc("asyncFunc:def"), roles: .definition)
641641
])
642642

643-
let asyncMethSym = Symbol(usr: "s:4main8MyStructV11asyncMethodyyYaF", name: "asyncMethod()", kind: .instanceMethod, properties: .swiftAsync)
643+
let asyncMethSym = Symbol(usr: "s:4main8MyStructV11asyncMethodyyYaF", name: "asyncMethod()", kind: .instanceMethod, properties: .swiftAsync, language: .swift)
644644
let asyncMethOccs = index.occurrences(ofUSR: asyncMethSym.usr, roles: .definition)
645645
checkOccurrences(asyncMethOccs, expected: [
646646
asyncMethSym.at(ws.testLoc("asyncMethod:def"), roles: .definition)
647647
])
648648

649-
let testMeSym = Symbol(usr: "s:4main10MyTestCaseC6testMeyyF", name: "testMe()", kind: .instanceMethod, properties: .unitTest)
649+
let testMeSym = Symbol(usr: "s:4main10MyTestCaseC6testMeyyF", name: "testMe()", kind: .instanceMethod, properties: .unitTest, language: .swift)
650650
let testMeOccs = index.occurrences(ofUSR: testMeSym.usr, roles: .definition)
651651
checkOccurrences(testMeOccs, expected: [
652652
testMeSym.at(ws.testLoc("testMe:def"), roles: .definition)
653653
])
654654

655-
let testMeAsyncSym = Symbol(usr: "s:4main10MyTestCaseC11testMeAsyncyyYaF", name: "testMeAsync()", kind: .instanceMethod, properties: [.unitTest, .swiftAsync])
655+
let testMeAsyncSym = Symbol(usr: "s:4main10MyTestCaseC11testMeAsyncyyYaF", name: "testMeAsync()", kind: .instanceMethod, properties: [.unitTest, .swiftAsync], language: .swift)
656656
let testMeAsyncOccs = index.occurrences(ofUSR: testMeAsyncSym.usr, roles: .definition)
657657
checkOccurrences(testMeAsyncOccs, expected: [
658658
testMeAsyncSym.at(ws.testLoc("testMeAsync:def"), roles: .definition)
@@ -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)
668+
let largeType = Symbol(usr: "c:@CT@LargeType", name: "LargeType", kind: .concept, language: .cxx)
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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ typedef enum {
137137
INDEXSTOREDB_EVENT_UNIT_OUT_OF_DATE = 2,
138138
} indexstoredb_delegate_event_kind_t;
139139

140+
typedef enum {
141+
INDEXSTOREDB_LANGUAGE_C,
142+
INDEXSTOREDB_LANGUAGE_OBJC,
143+
INDEXSTOREDB_LANGUAGE_CXX,
144+
INDEXSTOREDB_LANGUAGE_SWIFT
145+
} indexstoredb_language_t;
146+
140147
typedef void *indexstoredb_delegate_event_t;
141148

142149
/// Returns true on success.
@@ -333,6 +340,10 @@ indexstoredb_symbol_name(_Nonnull indexstoredb_symbol_t);
333340
INDEXSTOREDB_PUBLIC uint64_t
334341
indexstoredb_symbol_properties(_Nonnull indexstoredb_symbol_t);
335342

343+
/// Return the language in which the given symbol is defined.
344+
indexstoredb_language_t
345+
indexstoredb_symbol_language(_Nonnull indexstoredb_symbol_t symbol);
346+
336347
/// Returns the symbol of the given symbol occurrence.
337348
///
338349
/// The symbol has the same lifetime as the \c indexstoredb_symbol_occurrence_t.

lib/CIndexStoreDB/CIndexStoreDB.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,21 @@ indexstoredb_symbol_usr(indexstoredb_symbol_t symbol) {
319319
return value->getUSR().c_str();
320320
}
321321

322+
indexstoredb_language_t
323+
indexstoredb_symbol_language(_Nonnull indexstoredb_symbol_t symbol) {
324+
auto value = (Symbol *)symbol;
325+
switch (value->getLanguage()) {
326+
case IndexStoreDB::SymbolLanguage::C:
327+
return INDEXSTOREDB_LANGUAGE_C;
328+
case IndexStoreDB::SymbolLanguage::ObjC:
329+
return INDEXSTOREDB_LANGUAGE_OBJC;
330+
case IndexStoreDB::SymbolLanguage::CXX:
331+
return INDEXSTOREDB_LANGUAGE_CXX;
332+
case IndexStoreDB::SymbolLanguage::Swift:
333+
return INDEXSTOREDB_LANGUAGE_SWIFT;
334+
}
335+
}
336+
322337
const char *
323338
indexstoredb_symbol_name(indexstoredb_symbol_t symbol) {
324339
auto value = (Symbol *)symbol;

0 commit comments

Comments
 (0)