(context: ResolutionContext)
| 261 | ]); |
| 262 | |
| 263 | function buildRNMaps(context: ResolutionContext): { byJsName: Map<string, NativeMethod[]> } { |
| 264 | const cached = nativeMethodMaps.get(context); |
| 265 | if (cached) return cached; |
| 266 | |
| 267 | const byJsName = new Map<string, NativeMethod[]>(); |
| 268 | const allFiles = context.getAllFiles(); |
| 269 | // Pre-index native methods by name for fast lookup when matching to |
| 270 | // their bridge exports. |
| 271 | const objcMethodsByFirstKw = new Map<string, Node[]>(); |
| 272 | const jvmMethodsByName = new Map<string, Node[]>(); |
| 273 | for (const node of context.getNodesByKind('method')) { |
| 274 | if (node.language === 'objc') { |
| 275 | const firstKw = node.name.includes(':') ? node.name.split(':')[0] : node.name; |
| 276 | if (firstKw) { |
| 277 | const arr = objcMethodsByFirstKw.get(firstKw); |
| 278 | if (arr) arr.push(node); |
| 279 | else objcMethodsByFirstKw.set(firstKw, [node]); |
| 280 | } |
| 281 | } else if (node.language === 'java' || node.language === 'kotlin') { |
| 282 | const arr = jvmMethodsByName.get(node.name); |
| 283 | if (arr) arr.push(node); |
| 284 | else jvmMethodsByName.set(node.name, [node]); |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | for (const file of allFiles) { |
| 289 | // Legacy bridge — ObjC side. |
| 290 | if (file.endsWith('.m') || file.endsWith('.mm')) { |
| 291 | const source = context.readFile(file); |
| 292 | if (!source) continue; |
| 293 | const className = findObjcClassName(source); |
| 294 | const exports = parseObjcRNExports(source, className); |
| 295 | for (const exp of exports) { |
| 296 | if (RN_EMITTER_BUILTINS.has(exp.jsName)) continue; |
| 297 | // Resolve to the native node by selector first-keyword. Multiple |
| 298 | // ObjC methods may share a first keyword across modules; filter by |
| 299 | // file path to attribute the export to this module's |
| 300 | // implementation file. |
| 301 | const candidates = objcMethodsByFirstKw.get(exp.nativeSelectorFirstKw) ?? []; |
| 302 | const node = candidates.find((c) => c.filePath === file) ?? candidates[0]; |
| 303 | if (!node) continue; |
| 304 | const entry: NativeMethod = { moduleName: exp.moduleName, jsName: exp.jsName, node }; |
| 305 | const arr = byJsName.get(exp.jsName); |
| 306 | if (arr) arr.push(entry); |
| 307 | else byJsName.set(exp.jsName, [entry]); |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | // Legacy bridge — Java/Kotlin side. |
| 312 | if (file.endsWith('.java') || file.endsWith('.kt')) { |
| 313 | const source = context.readFile(file); |
| 314 | if (!source) continue; |
| 315 | const exports = parseJvmRNExports(source); |
| 316 | for (const exp of exports) { |
| 317 | if (RN_EMITTER_BUILTINS.has(exp.jsName)) continue; |
| 318 | const candidates = jvmMethodsByName.get(exp.jsName) ?? []; |
| 319 | const node = candidates.find((c) => c.filePath === file) ?? candidates[0]; |
| 320 | if (!node) continue; |
no test coverage detected