@@ -125,8 +125,21 @@ public struct FengNiao {
125125 let allResources = allResourceFiles ( )
126126 let usedNames = allUsedStringNames ( )
127127 let memberAccessUsedNames = allUsedMemberAccessNames ( )
128+
129+ // Generated asset symbols are an additional conservative usage signal.
130+ // Swift uses `.icFlag`, while Objective-C image symbols use `ACImageNameIcFlag`.
128131 let resourcesUsedByGeneratedSymbols = Set (
129- allResources. keys. filter { memberAccessUsedNames. contains ( $0. generatedAssetSymbolKey) }
132+ allResources. keys. filter { resourceKey in
133+ let swiftSymbolKey = resourceKey. generatedAssetSymbolKey
134+ if memberAccessUsedNames. contains ( swiftSymbolKey) {
135+ return true
136+ }
137+ let objcImageSymbolKey = resourceKey. objcGeneratedAssetSymbolKey
138+ if memberAccessUsedNames. contains ( objcImageSymbolKey) {
139+ return true
140+ }
141+ return false
142+ }
130143 )
131144 let combinedUsedNames = usedNames. union ( resourcesUsedByGeneratedSymbols)
132145
@@ -216,7 +229,8 @@ public struct FengNiao {
216229 }
217230
218231 func allUsedMemberAccessNames( ) -> Set < String > {
219- guard searchInFileExtensions. contains ( " swift " ) else {
232+ let memberAccessExtensions : Set < String > = [ " swift " , " m " , " mm " , " h " ]
233+ guard searchInFileExtensions. contains ( where: { memberAccessExtensions. contains ( $0) } ) else {
220234 return [ ]
221235 }
222236 return usedMemberAccessNames ( at: projectPath)
@@ -271,7 +285,9 @@ public struct FengNiao {
271285 return [ ]
272286 }
273287
274- let searchRule = SwiftMemberAccessSearchRule ( )
288+ let memberAccessExtensions : Set < String > = [ " swift " , " m " , " mm " , " h " ]
289+ let swiftSearchRule = SwiftMemberAccessSearchRule ( )
290+ let objcSearchRule = ObjCMemberAccessSearchRule ( )
275291 var result = Set < String > ( )
276292 for subPath in subPaths {
277293 if subPath. lastComponent. hasPrefix ( " . " ) {
@@ -285,12 +301,23 @@ public struct FengNiao {
285301 if subPath. isDirectory {
286302 result. formUnion ( usedMemberAccessNames ( at: subPath) )
287303 } else {
288- guard ( subPath. extension ?? " " ) == " swift " else {
304+ let fileExt = subPath. extension ?? " "
305+ guard searchInFileExtensions. contains ( fileExt) , memberAccessExtensions. contains ( fileExt) else {
289306 continue
290307 }
291308
292309 let content = ( try ? subPath. read ( ) ) ?? " "
293- result. formUnion ( searchRule. search ( in: content) )
310+
311+ switch fileExt {
312+ case " swift " :
313+ result. formUnion ( swiftSearchRule. search ( in: content) )
314+ case " m " , " mm " , " h " :
315+ // Scan headers conservatively as well, since projects may wrap generated
316+ // asset symbols in macros or inline helpers that are later imported into Swift.
317+ result. formUnion ( objcSearchRule. search ( in: content) )
318+ default :
319+ break
320+ }
294321 }
295322 }
296323
0 commit comments