@@ -25,20 +25,26 @@ private func getTestableImports(path: String) -> Set<String> {
25
25
} )
26
26
}
27
27
28
- private func getReferenceUSRs( unitReader: UnitReader , unitToRecord: [ String : RecordReader ] ) -> Set < String > {
28
+ private func getReferenceUSRs( unitReader: UnitReader , unitToRecord: [ String : RecordReader ] )
29
+ -> ( Set < String > , Set < String > )
30
+ {
29
31
// Empty source files have units but no records
30
32
guard let recordReader = unitToRecord [ unitReader. mainFile] else {
31
- return [ ]
33
+ return ( [ ] , [ ] )
32
34
}
33
35
34
36
var usrs = Set < String > ( )
37
+ var overrideUSRs = Set < String > ( )
35
38
recordReader. forEach { ( occurrence: SymbolOccurrence ) in
36
39
if occurrence. roles. contains ( . reference) {
37
40
usrs. insert ( occurrence. symbol. usr)
41
+ if occurrence. roles. contains ( . overrideOf) || occurrence. roles. contains ( . baseOf) {
42
+ overrideUSRs. insert ( occurrence. symbol. usr)
43
+ }
38
44
}
39
45
}
40
46
41
- return usrs
47
+ return ( usrs, overrideUSRs )
42
48
}
43
49
44
50
// TODO: Improve this. Issues:
@@ -56,7 +62,7 @@ private func getReferenceUSRs(unitReader: UnitReader, unitToRecord: [String: Rec
56
62
// the protocol itself is
57
63
// - This doesn't differentiate between `public` and `public final`, so if you subclass the class you need
58
64
// the testable import in the `public` case
59
- private func isPublic( file: String , occurrence: SymbolOccurrence ) -> Bool {
65
+ private func isPublic( file: String , occurrence: SymbolOccurrence , isOverride : Bool ) -> Bool {
60
66
// Assume implicit declarations (generated memberwise initializers) require testable
61
67
if occurrence. roles. contains ( . implicit) && !occurrence. roles. contains ( . accessorOf) {
62
68
return false
@@ -73,7 +79,7 @@ private func isPublic(file: String, occurrence: SymbolOccurrence) -> Bool {
73
79
return true
74
80
}
75
81
76
- let isPublic = text. contains ( " public " ) || text. contains ( " open " )
82
+ let isPublic = ( text. contains ( " public " ) && !isOverride ) || text. contains ( " open " )
77
83
// Handle public members that explicitly set 'internal(set)' for allowing setting from tests
78
84
return isPublic && !text. contains ( " internal( " )
79
85
}
@@ -180,7 +186,7 @@ func main(indexStorePath: String) {
180
186
continue
181
187
}
182
188
183
- let referencedUSRs = getReferenceUSRs ( unitReader: unitReader, unitToRecord: unitToRecord)
189
+ let ( referencedUSRs, overrideUSRs ) = getReferenceUSRs ( unitReader: unitReader, unitToRecord: unitToRecord)
184
190
var seenModules = Set < String > ( )
185
191
var requiredTestableImports = Set < String > ( )
186
192
for dependentUnit in units {
@@ -205,7 +211,8 @@ func main(indexStorePath: String) {
205
211
referencedUSRs. contains ( occurrence. symbol. usr) &&
206
212
!isChildOfProtocol( occurrence: occurrence) &&
207
213
!isGetterOrSetterFunction( occurrence: occurrence) &&
208
- !isPublic( file: dependentUnit. mainFile, occurrence: occurrence)
214
+ !isPublic( file: dependentUnit. mainFile, occurrence: occurrence,
215
+ isOverride: overrideUSRs. contains ( occurrence. symbol. usr) )
209
216
{
210
217
requiredTestableImports. insert ( moduleName)
211
218
}
0 commit comments