(selector: string)
| 194 | * `_` first label). The resolver tries each. |
| 195 | */ |
| 196 | export function swiftBaseNamesForObjcSelector(selector: string): string[] { |
| 197 | if (!selector) return []; |
| 198 | |
| 199 | // Strip trailing colons and split into keywords. |
| 200 | const keywords = selector.replace(/:+$/g, '').split(':'); |
| 201 | const firstKeyword = keywords[0]; |
| 202 | if (!firstKeyword) return []; |
| 203 | |
| 204 | const candidates: Set<string> = new Set(); |
| 205 | |
| 206 | // Always a candidate: the raw first keyword. Covers |
| 207 | // `play:` → `play` |
| 208 | // `play:by:` → `play` |
| 209 | // `playWithSong:` → `playWithSong` (a literal Swift name) |
| 210 | // `tableView:...:` → `tableView` |
| 211 | candidates.add(firstKeyword); |
| 212 | |
| 213 | // `initWith<X>:` and `initWith<X>:<more>:` always reduce to `init`. |
| 214 | if (firstKeyword.startsWith('initWith')) { |
| 215 | candidates.add('init'); |
| 216 | } |
| 217 | |
| 218 | // Preposition-prefix patterns: `<base>(With|For|By|In|On|At|From|To|Of|As)<Cap>:` |
| 219 | // covers both Swift's @objc EXPORT rule (always "With") and Cocoa's |
| 220 | // IMPORTED selectors which use other prepositions natively (e.g. |
| 221 | // `objectForKey:`, `stringWithFormat:`, `compareTo:`, |
| 222 | // `imageNamed:inBundle:`). Strip to recover the Swift base name a caller |
| 223 | // would use (e.g. `object`, `string`, `compare`, `image`). |
| 224 | const prepositionMatch = firstKeyword.match( |
| 225 | /^([a-z][a-zA-Z0-9]*?)(?:With|For|By|In|On|At|From|To|Of|As)[A-Z]/ |
| 226 | ); |
| 227 | if (prepositionMatch && prepositionMatch[1]) { |
| 228 | candidates.add(prepositionMatch[1]); |
| 229 | } |
| 230 | |
| 231 | // `setX:` could be a property setter — the Swift property is `x` (lowercase). |
| 232 | // Only fires for the obvious shape: `set` + capital letter + ':' (one param). |
| 233 | if ( |
| 234 | keywords.length === 1 && |
| 235 | /^set[A-Z]/.test(firstKeyword) && |
| 236 | selector.endsWith(':') |
| 237 | ) { |
| 238 | const propName = lowerFirst(firstKeyword.slice(3)); |
| 239 | if (propName) candidates.add(propName); |
| 240 | } |
| 241 | |
| 242 | return Array.from(candidates); |
| 243 | } |
| 244 | |
| 245 | /** |
| 246 | * Detect whether a Swift method `@objc` declaration uses the `@objc(custom:)` |
no test coverage detected