Skip to content

Commit 591de07

Browse files
authored
Merge pull request #73 from akyrtzi/module-name-in-symbol-location
Make sure Swift symbol occurrences are associated with the module name they belong to
2 parents 14e6e25 + ded10dc commit 591de07

File tree

7 files changed

+67
-13
lines changed

7 files changed

+67
-13
lines changed

Sources/ISDBTestSupport/TestLocation.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import IndexStoreDB
1616
/// A source location (file:line:column) in a test project, for use with the TestLocationScanner.
1717
public struct TestLocation: Hashable {
1818

19+
/// Marker string to mark a `SymbolLocation` as containing an unknown module name from a test location.
20+
public static let unknownModuleName: String = "<UNKNOWN>"
21+
1922
/// The path/url of the source file.
2023
public var url: URL
2124

@@ -45,9 +48,10 @@ extension TestLocation: Comparable {
4548
extension SymbolLocation {
4649

4750
/// Constructs a SymbolLocation from a TestLocation, using a non-system path by default.
48-
public init(_ loc: TestLocation, isSystem: Bool = false) {
51+
public init(_ loc: TestLocation, moduleName: String = TestLocation.unknownModuleName, isSystem: Bool = false) {
4952
self.init(
5053
path: loc.url.path,
54+
moduleName: moduleName,
5155
isSystem: isSystem,
5256
line: loc.line,
5357
utf8Column: loc.utf8Column)
@@ -57,8 +61,8 @@ extension SymbolLocation {
5761
extension Symbol {
5862

5963
/// Returns a SymbolOccurrence with the given location and roles.
60-
public func at(_ location: TestLocation, roles: SymbolRole) -> SymbolOccurrence {
61-
return self.at(SymbolLocation(location), roles: roles)
64+
public func at(_ location: TestLocation, moduleName: String = TestLocation.unknownModuleName, roles: SymbolRole) -> SymbolOccurrence {
65+
return self.at(SymbolLocation(location, moduleName: moduleName), roles: roles)
6266
}
6367
}
6468

Sources/ISDBTestSupport/XCTestAssertions.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,32 @@
1313
import IndexStoreDB
1414
import XCTest
1515

16+
extension SymbolLocation {
17+
/// Special equality check for testing.
18+
func testEqual(with other: SymbolLocation) -> Bool {
19+
// We do not have a way to automatically infer the module name from test locations,
20+
// if we used `SymbolLocation`'s standard equality check we'd have to manually pass
21+
// the module name string in every symbol occurrence test.
22+
// Instead we ignore the module name if this `SymbolLocation` was initialized from
23+
// a test location without an explicit module name.
24+
return path == other.path &&
25+
(moduleName == TestLocation.unknownModuleName || other.moduleName == TestLocation.unknownModuleName || moduleName == other.moduleName) &&
26+
isSystem == other.isSystem &&
27+
line == other.line &&
28+
utf8Column == other.utf8Column
29+
}
30+
}
31+
32+
extension SymbolOccurrence {
33+
/// Special equality check for testing.
34+
func testEqual(with other: SymbolOccurrence) -> Bool {
35+
return symbol == other.symbol &&
36+
location.testEqual(with: other.location) &&
37+
roles == other.roles &&
38+
relations == other.relations
39+
}
40+
}
41+
1642
/// An XCTest assertion that the given symbol occurrences match the expected values, ignoring the
1743
/// order of results, and optionally ignoring relations. By default, the given occurrences also are
1844
/// allowed to have additional SymbolRoles.
@@ -59,7 +85,7 @@ public func checkOccurrences(
5985
actual.roles.formIntersection(expected.roles)
6086
}
6187

62-
if actual == expected { return .orderedSame }
88+
if actual.testEqual(with: expected) { return .orderedSame }
6389
if actual < expected { return .orderedAscending }
6490
return .orderedDescending
6591
}

Sources/IndexStoreDB/SymbolLocation.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ import CIndexStoreDB
1414

1515
public struct SymbolLocation: Equatable {
1616
public var path: String
17+
public var moduleName: String
1718
public var isSystem: Bool
1819
public var line: Int
1920
public var utf8Column: Int
2021

21-
public init(path: String, isSystem: Bool = false, line: Int, utf8Column: Int) {
22+
public init(path: String, moduleName: String, isSystem: Bool = false, line: Int, utf8Column: Int) {
2223
self.path = path
24+
self.moduleName = moduleName
2325
self.isSystem = isSystem
2426
self.line = line
2527
self.utf8Column = utf8Column
@@ -28,14 +30,14 @@ public struct SymbolLocation: Equatable {
2830

2931
extension SymbolLocation: Comparable {
3032
public static func <(a: SymbolLocation, b: SymbolLocation) -> Bool {
31-
return (a.path, a.line, a.utf8Column, a.isSystem ? 1 : 0)
32-
< (b.path, b.line, b.utf8Column, b.isSystem ? 1 : 0)
33+
return (a.path, a.moduleName, a.line, a.utf8Column, a.isSystem ? 1 : 0)
34+
< (b.path, a.moduleName, b.line, b.utf8Column, b.isSystem ? 1 : 0)
3335
}
3436
}
3537

3638
extension SymbolLocation: CustomStringConvertible {
3739
public var description: String {
38-
"\(path):\(line):\(utf8Column)\(isSystem ? " [system]" : "")"
40+
"\(!moduleName.isEmpty ? "\(moduleName)::" : "")\(path):\(line):\(utf8Column)\(isSystem ? " [system]" : "")"
3941
}
4042
}
4143

@@ -44,6 +46,7 @@ extension SymbolLocation: CustomStringConvertible {
4446
extension SymbolLocation {
4547
public init(_ loc: indexstoredb_symbol_location_t) {
4648
path = String(cString: indexstoredb_symbol_location_path(loc))
49+
moduleName = String(cString: indexstoredb_symbol_location_module_name(loc))
4750
isSystem = indexstoredb_symbol_location_is_system(loc)
4851
line = Int(indexstoredb_symbol_location_line(loc))
4952
utf8Column = Int(indexstoredb_symbol_location_column_utf8(loc))

Tests/IndexStoreDBTests/IndexTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ final class IndexTests: XCTestCase {
3232

3333
let ccanon = SymbolOccurrence(
3434
symbol: csym,
35-
location: SymbolLocation(ws.testLoc("c")),
35+
location: SymbolLocation(ws.testLoc("c"), moduleName: "main"),
3636
roles: [.definition, .canonical],
3737
relations: [])
3838

@@ -135,9 +135,9 @@ final class IndexTests: XCTestCase {
135135

136136
let aaa = Symbol(usr: "s:1A3aaayyF", name: "aaa()", kind: .function)
137137
checkOccurrences(ws.index.occurrences(ofUSR: aaa.usr, roles: .all), expected: [
138-
aaa.at(ws.testLoc("aaa:def"), roles: .definition),
139-
aaa.at(ws.testLoc("aaa:call"), roles: .call),
140-
aaa.at(ws.testLoc("aaa:call:c"), roles: .call),
138+
aaa.at(ws.testLoc("aaa:def"), moduleName: "A", roles: .definition),
139+
aaa.at(ws.testLoc("aaa:call"), moduleName: "B", roles: .call),
140+
aaa.at(ws.testLoc("aaa:call:c"), moduleName: "C", roles: .call),
141141
])
142142
}
143143

include/CIndexStoreDB/CIndexStoreDB.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,13 @@ INDEXSTOREDB_PUBLIC
231231
const char * _Nonnull
232232
indexstoredb_symbol_location_path(_Nonnull indexstoredb_symbol_location_t);
233233

234+
/// Returns the module name of the given symbol location.
235+
///
236+
/// The string has the same lifetime as the \c indexstoredb_symbol_location_t.
237+
INDEXSTOREDB_PUBLIC
238+
const char * _Nonnull
239+
indexstoredb_symbol_location_module_name(_Nonnull indexstoredb_symbol_location_t);
240+
234241
/// Returns whether the given symbol location is a system location.
235242
INDEXSTOREDB_PUBLIC bool
236243
indexstoredb_symbol_location_is_system(_Nonnull indexstoredb_symbol_location_t);

lib/CIndexStoreDB/CIndexStoreDB.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ indexstoredb_symbol_location_path(indexstoredb_symbol_location_t loc) {
286286
return obj->getPath().getPathString().c_str();
287287
}
288288

289+
const char *
290+
indexstoredb_symbol_location_module_name(indexstoredb_symbol_location_t loc) {
291+
auto obj = (SymbolLocation *)loc;
292+
return obj->getPath().getModuleName().c_str();
293+
}
294+
289295
bool
290296
indexstoredb_symbol_location_is_system(indexstoredb_symbol_location_t loc) {
291297
auto obj = (SymbolLocation *)loc;

lib/Index/IndexDatastore.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,16 @@ void StoreUnitRepo::registerUnit(StringRef unitName) {
367367
if (!Dep.isSystem())
368368
UserFileDepends.push_back(CanonPath);
369369
StringRef recordName = Dep.getName();
370+
StringRef moduleName = Dep.getModuleName();
371+
if (moduleName.empty()) {
372+
// Workaround for swift compiler not associating the module name with records of swift files.
373+
// FIXME: Fix this on swift compiler and remove this.
374+
if (CanonPath.getPath().endswith(".swift")) {
375+
moduleName = Reader.getModuleName();
376+
}
377+
}
370378
bool isNewProvider;
371-
IDCode providerCode = unitImport.addProviderDependency(recordName, CanonPath, Dep.getModuleName(), Dep.isSystem(), &isNewProvider);
379+
IDCode providerCode = unitImport.addProviderDependency(recordName, CanonPath, moduleName, Dep.isSystem(), &isNewProvider);
372380
if (!isNewProvider)
373381
break;
374382

0 commit comments

Comments
 (0)