Skip to content

Commit ca29517

Browse files
authored
Merge pull request #177 from ahoppen/ahoppen/get-source-language
Add API to get the language in which a symbol is defined and the symbol provider for a source file
2 parents 5eac09c + b859160 commit ca29517

File tree

8 files changed

+211
-47
lines changed

8 files changed

+211
-47
lines changed

Sources/IndexStoreDB/IndexStoreDB.swift

Lines changed: 45 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

@@ -148,13 +153,18 @@ public final class IndexStoreDB {
148153
return indexstoredb_index_remove_unit_out_file_paths(impl, cPaths, cPaths.count, waitForProcessing)
149154
}
150155

156+
/// Invoke `body` with every occurrance of `usr` in one of the specified roles.
157+
///
158+
/// Stop iteration if `body` returns `false`.
159+
/// - Returns: `false` if iteration was terminated by `body` returning `true` or `true` if iteration finished.
151160
@discardableResult
152161
public func forEachSymbolOccurrence(byUSR usr: String, roles: SymbolRole, _ body: @escaping (SymbolOccurrence) -> Bool) -> Bool {
153162
return indexstoredb_index_symbol_occurrences_by_usr(impl, usr, roles.rawValue) { occur in
154163
return body(SymbolOccurrence(occur))
155164
}
156165
}
157166

167+
/// Returns all occurrences of `usr` in one of the specified roles.
158168
public func occurrences(ofUSR usr: String, roles: SymbolRole) -> [SymbolOccurrence] {
159169
var result: [SymbolOccurrence] = []
160170
forEachSymbolOccurrence(byUSR: usr, roles: roles) { occur in
@@ -275,6 +285,41 @@ public final class IndexStoreDB {
275285
return result
276286
}
277287

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

Sources/IndexStoreDB/Symbol.swift

Lines changed: 48 additions & 7 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

@@ -69,9 +84,9 @@ extension Symbol: Comparable {
6984
extension Symbol: CustomStringConvertible {
7085
public var description: String {
7186
if properties.isEmpty {
72-
return "\(name) | \(kind) | \(usr)"
87+
return "\(name) | \(kind) | \(usr) | \(language)"
7388
}
74-
return "\(name) | \(kind) (\(properties)) | \(usr)"
89+
return "\(name) | \(kind) (\(properties)) | \(usr) | \(language)"
7590
}
7691
}
7792

@@ -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

0 commit comments

Comments
 (0)