rustcodegraph 1.2.6

Local-first code intelligence graph and CLI for AI agents
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
# 混合 iOS + React Native 桥接 - 覆盖设计

**观众:** 克劳德特工(或人类)在 #165 着陆后继续这项工作
纯 Objective-C 支持。
**任务:**制作 rustcodegraph 的 `trace` / `callers` / `callees` / `impact` /
流上下文调用跨**跨语言运行时进行端到端连接
调度边界**如今悄然打破了流程:**Swift ↔ Objective-C**
在混合 iOS 代码库中,以及 React Native / Expo 中的 **JavaScript ↔ native**
应用程序。

> 本文档是**计划**,而不是实施。没有代码登陆此
> 分支——只有设计、验证语料库和成功栏。
> 编码从每个阶段的后续分支开始。

这项工作是
[动态调度覆盖手册](./dynamic-dispatch-coverage-playbook.md) §6
矩阵:“Swift × Objective-C 桥接”行和一个新的“React Native 桥接”
排。两者都是 **resolver** 模式(双方都存在名为 refs 的
桥接规则是确定性的)——而不是合成器模式。参见第 3a 节
参考 Django ORM 解析器的 playbook。

---

## 1. 为什么这很重要(今天的差距)

#165 之后,rustcodegraph 索引了 Swift、Objective-C 和 JavaScript/TypeScript
每个都正确地**隔离**。但价值在于跨语言流动——
iOS 应用程序和 React Native 应用程序所在的位置:

- **混合 iOS 应用程序:** `MyViewController.swift` 调用 `imageDownloader.download(url:completion:)`,
也就是 `ImageDownloader.m` 中的 `-[ImageDownloader downloadURL:completion:]`。
今天:`trace("MyViewController.viewDidLoad", "downloadURL:completion:")`
调用不返回路径。 Swift 调用点解析为 `call_expression`,其
选择器无处可去; ObjC方法作为一个没有传入的节点存在
边缘。代理读取这两个文件以重建网桥。
- **React Native 应用程序:** `useEffect(() => NativeModules.Geolocation.getCurrentPosition(cb))`
在 `App.js` 达到 `RCT_EXPORT_METHOD(getCurrentPosition:(RCTResponseSenderBlock)cb)`
在`RNCGeolocation.m`。今天:JS 调用点没有传出优势
ObjC 实现; ObjC 处理程序没有来自 JS 的传入边缘。
`impact(getCurrentPosition)`(ObjC 端)显示没有 JS 调用者。
- **世博模块:** `await ExpoCamera.takePictureAsync(options)` (JS) 到达
`ExpoCamera.swift` 中的 `AsyncFunction("takePictureAsync") { ... }`(世博会
模块 API)。同样的休息。

在每种情况下,代理人或名称匹配者都存在**双方的名称
can correlate — Swift 的自动桥接 ObjC 选择器,`RCT_EXPORT_METHOD`
文字第一个参数,Expo `Function("name")` 文字。修复方法是
**解析器**知道每个通道的桥接规则并发出
`references` 与 `provenance:'heuristic'` 和 `metadata.synthesizedBy:'<channel>'` 边缘。

剧本的承重警告在这里比平常更适用:

> **部分覆盖比没有覆盖更糟糕。** 弥合一个边界,但不弥合整个边界
> 接下来显示一个跳跃,然后代理进行钻探+读取以完成。始终关闭
> 端到端的流程并重新测量——切勿发送半桥流程。

对于混合 iOS,这意味着**两个方向**(Swift→ObjC 和 ObjC→Swift)并且
**所有桥接类型**(方法、属性、初始化/初始化器、协议)
测量前必须关闭。对于 React Native,JS→native AND
native→JS (`RCTEventEmitter`, `sendEvent`) 必须都关闭,并且**都关闭
传统桥和 TurboModules**,或混合它们的应用程序将半桥。

---

## 2. 建模的桥接机制

在剧本的词汇表中,每一行都是一个单独的**调度通道** -
每个都有自己的解析器(如果不存在静态引用则为合成器),它自己的
验证,在 §6 矩阵中拥有自己的行。

| # | 方向 | 渠道 | 映射规则 | 它住在哪里 | 困难 |
|---|---|---|---|---|---|
| 1 | Swift→ObjC | 直接调用,通过`-Bridging-Header.h`导入ObjC类 | Swift 调用 `obj.x(y:z:)` ↔ ObjC 选择器 `-x:z:` (文字映射,参见 §3a) | `frameworks/swift-objc.ts` 中的旋转变压器 | 中等的 |
| 2 | ObjC → Swift | `@objc`曝光 | Swift `@objc func foo(bar:)` ↔ ObjC `-fooWithBar:` (自动名称); `@objc(custom:)` 覆盖 | `frameworks/swift-objc.ts` 中的旋转变压器 | 中等的 |
| 3 | 斯威夫特 ↔ ObjC | 属性/getter/setter 桥接 | 斯威夫特 `var name: String` ↔ 对象 C `-name` / `-setName:` | `frameworks/swift-objc.ts` 中的旋转变压器 | 低的 |
| 4 | 斯威夫特 ↔ ObjC | 初始化器桥接 | 斯威夫特 `init(name:age:)` ↔ ObjC `-initWithName:age:` | `frameworks/swift-objc.ts` 中的旋转变压器 | 低的 |
| 5 | 斯威夫特 ↔ ObjC | 协议桥接 (`@objc protocol`) | 跨语言的一致性边缘 | `frameworks/swift-objc.ts` 中的旋转变压器 | 中等的 |
| 6 | JS → ObjC(RN 遗留桥) | `NativeModules.<Mod>.<fn>` ↔ `RCT_EXPORT_METHOD(<fn>:...)` 或 `RCT_REMAP_METHOD(<jsName>, <selector>:...)` | ObjC 端由 `RCT_EXPORT_MODULE()` 文字键入的名称匹配 | `frameworks/react-native.ts` 中的旋转变压器 | 中等的 |
| 7 | JS → Java/Kotlin(RN 遗留桥,Android) | `NativeModules.<Mod>.<fn>` ↔ `ReactContextBaseJavaModule` 子类上的 `@ReactMethod` 带注释的方法,其中 `getName()` 返回 `<Mod>` | 解析器 — 形状与 #6 相同,JVM 端 | 中等的 |
| 8 | JS ↔ 原生(RN TurboModules / Codegen) | `TurboModuleRegistry.get('Mod')` ↔ 生成的规范接口(`NativeMod` TS 类型) ↔ 与规范匹配的 ObjC++/Kotlin impl | 将规范文件读取为基本事实的解析器 | 难的 |
| 9 | 原生 → JS(事件) | ObjC `[self sendEventWithName:@"x" body:b]`(扩展 `RCTEventEmitter`)↔ JS `new NativeEventEmitter(NativeModules.Mod).addListener('x', cb)` | EventEmitter 风格的合成器(与语言 EventEmitter 的现有 `callback-synthesizer.ts` 相匹配) | 中等的 |
| 10 | JS → 原生(Expo 模块) | JS `ExpoX.fn(args)` ↔ Swift `Function("fn") { ... }` 或 `AsyncFunction("fn") { ... }` 位于具有 `Name("ExpoX")` 的 `Module` 子类中 | `frameworks/expo-modules.ts` 中的旋转变压器 | 中等的 |
| 11 | JS → 原生(Fabric 视图组件) | JS `<MyView prop={v}/>` ↔ ObjC/Swift `RCT_EXPORT_VIEW_PROPERTY(prop, ...)` 或 Codegen 查看规范 | 解析器 + JSX hop(与现有的 JSX 合成器组合) | 硬(推迟) |

**难度**列驱动分阶段——参见§6。

### 2a.为什么这些是解析器,而不是合成器

在每一行中,**桥接规则都是由名称确定的**:
- Swift 的 `@objc` 曝光的是有记录的自动映射; `@objc(custom:)`
是显式覆盖;两者都是静态可提取的。
- `RCT_EXPORT_METHOD` 采用文字选择器; `RCT_EXPORT_MODULE()` 采取
可选的文字模块名称(默认值:类名称减去 `RCT` 前缀);
`NativeModules.Mod.fn` 是对已知全局的文字属性访问。
- 展览模块 `Function("name") { ... }` 和 `Module { Name("ExpoX"); ... }`
是 `Module` 定义内的文字字符串。
- TurboModules 规范接口是文字 `Native<Name>` 导出
`TurboModuleRegistry.get<...>('<Name>')`。

所以工作是:**提取桥接端名称→使解析器匹配
他们**。与 `djangoResolver` 形状相同,将 `_iterable_class` 解析为
`ModelIterable` — 不需要全图相关传递。

一个例外是 **#9 本机→JS 事件**,其中注册站点
看起来非常像现有的语言内 EventEmitter 模式
回调合成器已经处理。扩展该合成器
跨语言渠道是天作之合。

---

## 3. 具体桥接规则(参考表)

### 3a. Swift → ObjC 选择器映射(自动)

Swift 使用标准规则从 Swift 方法派生 ObjC 选择器:

| 迅速声明 | 对象选择器 |
|---|---|
| `func greet()` | `greet` |
| `func say(_ msg: String)` | `say:` |
| `func set(name: String)` | `setWithName:` |
| `func setName(_ name: String)` | `setName:` |
| `func move(to point: CGPoint)` | `moveTo:` |
| `func move(from a: CGPoint, to b: CGPoint)` | `moveFrom:to:` |
| `init(name: String)` | `initWithName:` |
| `init(name: String, age: Int)` | `initWithName:age:` |
| `var name: String`(吸气剂) | `name` |
| `var name: String`(二传手) | `setName:` |
| `@objc(customSel:) func f(...)` | `customSel:`(显式覆盖) |

完整的规则集位于
[Apple — 将 Swift 导入 Objective-C](https://developer.apple.com/documentation/swift/importing-swift-into-objective-c)
— 特别是“方法名称翻译”和“初始化程序名称翻译”
部分。解析器在提取处以**一个方向实现此映射
time** (Swift 声明生成桥接 ObjC 名称,附加为
Swift 方法节点上的别名),因此 ObjC 端的名称解析找到
通过正常名称匹配的 Swift 方法。

### 3b. React Native 遗留桥 — 名称解析

```objc
// Native side (ObjC)
@implementation RCTGeolocation
RCT_EXPORT_MODULE();                                    // module name: "Geolocation" (RCT prefix stripped)
RCT_EXPORT_METHOD(getCurrentPosition:(RCTResponseSenderBlock)cb) { ... }
@end
```
```js
// JS side
import { NativeModules } from 'react-native';
NativeModules.Geolocation.getCurrentPosition(cb);       // resolves to the ObjC method above
```

规则:
1. 在本机端,为每个类提取一个合成 `module` 节点,其中包含
`RCT_EXPORT_MODULE()`。名称 = 显式字符串参数(如果存在),否则
去掉 `RCT` 前缀的类名。
2. 每个 `RCT_EXPORT_METHOD(<sel>)` 和 `RCT_REMAP_METHOD(<jsName>, <sel>)`
成为附加到该模块节点的方法节点,具有 JS 可见
名称(`<sel>` 的第一个关键字为 `RCT_EXPORT_METHOD`,或 `<jsName>` 为
`RCT_REMAP_METHOD`)。
3. 在 JS 端,解析器匹配文字属性链
`NativeModules.<Mod>.<fn>` 与 `(module, jsName)` 对
本机方面。
4. 旋转变压器发出 `references`(`provenance:'heuristic'`、`synthesizedBy:'rn-bridge'`)
从 JS 调用点到本机方法。

### 3c. React Native TurboModule — 名称解析

```ts
// Spec (TS) — codegen ground truth
export interface Spec extends TurboModule {
  getCurrentPosition(cb: (loc: Location) => void): void;
}
export default TurboModuleRegistry.getEnforcing<Spec>('Geolocation');
```
```objc
// ObjC++ impl
@implementation RCTGeolocation
- (void)getCurrentPosition:(RCTResponseSenderBlock)cb { ... }
@end
```
```js
import Geolocation from './NativeGeolocation';
Geolocation.getCurrentPosition(cb);  // resolves to the ObjC method via the spec
```

规则:
1. 规范文件是事实来源:解析 `TurboModuleRegistry.get*<Spec>('<Name>')`
找到模块名称,然后读取`Spec`接口方法。
2. 将每个规范方法与本机 impl 的同名方法相匹配(通过选择器
第一个关键字,在通过名称约定或阅读识别的类中
任何 `JSI_EXPORT_MODULE` 宏(如果存在)。
3. 规范文件的 JS 导入通过规范获得名称解析。
4. 发出与 #3b 相同的 `references` 边缘,其中 `synthesizedBy:'rn-turbomodule'`。

### 3d.世博模块 — 名称解析

```swift
// Native (Swift, expo-modules-core API)
public class ExpoCameraModule: Module {
  public func definition() -> ModuleDefinition {
    Name("ExpoCamera")
    AsyncFunction("takePictureAsync") { (options: CameraOptions) in /* ... */ }
    View(ExpoCameraView.self) {
      Prop("type") { (view: ExpoCameraView, type: String) in /* ... */ }
    }
  }
}
```
```js
import { requireNativeModule } from 'expo-modules-core';
const ExpoCamera = requireNativeModule('ExpoCamera');
await ExpoCamera.takePictureAsync({ quality: 1 });
```

规则:
1. 在本机端:扩展 `Module` 的类,其 `definition()` (或
`init { /* DSL */ }` 对于较新的 API)包含 `Name("X")` 调用定义
该模块。每个 `Function("y")` / `AsyncFunction("y")` 文字定义一个
方法。尾随闭包是实现主体——extract as a
名为 `y` 的方法节点,附加到模块 `X`。
2. 在JS端:`requireNativeModule('X')`产生一个绑定;解决
属性访问它的命名方法。
3. 视图模块的 `Prop("name")` 的行为类似于 RN 的 `RCT_EXPORT_VIEW_PROPERTY` —
与视图组件边界的其余部分推迟。

---

## 4. 需要存在哪些边

对于每个通道,闭合流量为:

- **JS 调用点 → 桥接方法节点**(`references`、启发式、`synthesizedBy:'<channel>'`)
- **桥接方法节点→本机实现方法**(已提取;适用于#6/#7
桥接方法是本机实现;对于#10,封闭体是
暗示)
- **Native-impl-method → 它自己的被调用者**(已用语言提取)

特别是对于 Swift↔ObjC,最干净的模型是 **alias-name
声明节点**:扩展 Swift 方法提取来计算 ObjC
自动桥接名称并将其存储为解析器的备用名称
认为。 Swift 和 ObjC 方法节点之间不需要新的边
— 正常的名称解析就足够了,因为双方都同意桥接
提取后的选择器。

MCP 读取工具已内联表面启发式边缘
(参见 #312/#403 中的 `metadata.synthesizedBy` 管道);这些新的边缘
沿着这条路行驶,无需额外的管道。

---

## 5. 验证语料库(小/中/大栏)

遵循 CLAUDE.md 的验证方法 — **≥3 个流程提示
小型/中型/大型存储库,具有确定性探针+代理 A/B,
≥2 次运行/臂**。以下选择是要承诺的候选人
实施部门;实施 PR 确认之后的选择
验证每个存储库仍然可以干净地构建索引。

### 5a.混合 iOS (Swift+ObjC) — 选择 3

| 等级 | 回购协议 | 为什么 | 规范流 |
|---|---|---|---|
| **小的** | [图表](https://github.com/danielgindi/Charts)(约 150 个文件 Swift+ObjC) | 带有 ObjC 兼容层的 Swift-first 库;知名 | “在 `ChartView` 上设置 `data` 如何到达渲染器?” |
| **小(替代)** | [洛蒂奥斯](https://github.com/airbnb/lottie-ios)(约 300 个文件,混合在一起;当前可能是纯 Swift — 验证) | 动画引擎,知名组合 | “`AnimationView.play()` 如何到达图层合成器?” |
| **中等的** | [境界-可可](https://github.com/realm/realm-swift)(约 500 个文件) | Heavy Swift-on-top-of-ObjC:Swift API 包装了 ObjC 核心,而 ObjC 核心又包装了 C++ Realm Core | “`Realm.write { realm.add(obj) }`如何到达ObjC持久层?” |
| **大的** | [维基百科-iOS](https://github.com/wikimedia/wikipedia-ios)(约 2500 个 Swift+ObjC 文件) | 真正的应用程序,深度混合,积极开发 | “点击搜索结果如何到达文章获取网络调用?” |
| **大(替代)** | [WordPress-iOS](https://github.com/wordpress-mobile/WordPress-iOS) | 较重的 ObjC 遗留 + Swift 添加 | “新帖子草稿保存如何达到核心数据持久性?” |

每个仓库的酒吧:
1. 纯语言探测仍然通过(Swift-in-Swift 跟踪;ObjC-in-ObjC 跟踪)——与 #165 的纯 ObjC 基线相比没有回归。
2. **跨语言探测通过:** 上面的规范流程以 `trace` 端到端跟踪,在语言边界处没有中断。
3. **代理 A/B(使用 rustcodegraph 与不使用 rustcodegraph,≥2 次运行/臂):** 在探索调用预算内读取 = 0;比不使用 rustcodegraph 更快;纯 Swift 或纯 ObjC 控制存储库(例如纹理)上没有回归。
4. **没有节点数爆炸** 与桥接前基线(之前/之后的 `select count(*) from nodes`)相比。

### 5b. React Native — 选择 3

| 等级 | 回购协议 | 为什么 | 规范流 |
|---|---|---|---|
| **小的** | [反应本机 svg](https://github.com/software-mansion/react-native-svg)(~100 个文件 JS+ObjC+Java) | 小型、范围广泛的本机模块集 | “设置`<Path d=.../>`如何到达iOS Core Graphics调用?” |
| **中等的** | [反应本机屏幕](https://github.com/software-mansion/react-native-screens)(~300 个文件,JS+原生) | 真正的导航原语,包括传统的网桥和 Fabric | “导航到新屏幕如何到达 UINavigationController?” |
| **中(替代)** | [反应本机 Firebase](https://github.com/invertase/react-native-firebase)(跨包约 1000 个文件) | 许多本机模块,两个平台 - 强调模块发现 | “`firestore().collection('x').get()` 如何到达 iOS Firebase SDK 调用?” |
| **大的** | [facebook/react-native](https://github.com/facebook/react-native) RNTester 子集(约 3000 个文件) | 框架本身+示例应用程序;规范桥接用法 | “按下 RNTester 的 GeolocationExample 中的按钮如何到达 iOS 核心位置调用?” |

每个仓库的酒吧:
1. Pure-JS 探针不变(`useState` → 重新渲染流程仍然解析 - 现有的反应合成器没有回归)。
2. **JS → ObjC 桥接探测通过**,每个存储库上有 ≥1 个已知的 RCT_EXPORT_METHOD。
3. **JS → TurboModule 探针在使用 TurboModules 的存储库上传递**(react-native main 两者都有;各选一个)。
4. **本机 → JS 事件探测传递**对于 ≥1 个发射器(NativeEventEmitter 模式)。
5. **代理 A/B** 如上所述。关键:*过桥*的问题(例如“按下按钮 X 如何到达网络调用”)必须在使用 rustcodegraph 运行 ≥1 次时将 Read 降至 0。
6. **在纯 JS 控制存储库上没有回归**(现有的 React-realworld / excalidraw 测量不变)。

### 5c. Expo — 选择 2(范围更小,API 面更窄)

| 等级 | 回购协议 | 为什么 |
|---|---|---|
| **小/中** | [博览会](https://github.com/expo/expo) — 一个 SDK 模块,如 `expo-camera` 或 `expo-location` | 最干净的 Expo Modules API 示例;居住 |
| **大的** | 完整的 `expo/expo` monorepo(所有 SDK 模块 + JS API) | 跨多个包的压力测试模块名称解析 |

规范流程:“`await Camera.takePictureAsync()` (JS) 如何到达
本机相机 API 调用(Swift `AVCaptureSession` 或 Kotlin
`CameraDevice`)?”

---

## 6. 分阶段——先做什么

根据剧本的难度梯度和半桥规则,顺序
由在**最小的存储库首先**上端到端关闭流程的内容来修复。

### 第 1 阶段 — Swift ↔ ObjC 桥接(上面第 1-5 行)
最小范围,确定性名称映射,不涉及 JS。验证在
继续之前的图表/领域/维基百科语料库。 **不要继续进入第 2 阶段
直到第 1 阶段通过所有三个存储库的 §5a 条。**

### 第 2 阶段 — React Native 遗留桥(第 6-7 行,ObjC + Java/Kotlin)
iOS 和 Android 双方必须在同一个 PR 中关闭——半桥接 PR
平台显示另一个平台上的半覆盖跳跃,并且代理读取。
在 §5b 语料库上进行验证。

### 第 3 阶段 — 本机 → JS 事件(第 9 行)
使用跨语言通道扩展现有的回调合成器。
在相同的 §5b 语料库上进行验证(大多数 RN 库至少使用一个事件发射器)。

### 第 4 阶段 — 世博模块(第 10 行)
分层于第一阶段的快速提取。较小的语料库 (§5c)。

### 第 5 阶段 — RN TurboModules/Codegen(第 8 行)
需要将规范文件作为跨语言的基本事实进行读取。验证于
§5b 语料库的 TurboModule 用户(react-native main,0.73 后的库)。

### 第 6 阶段 - Fabric 视图组件(第 11 行)
Deferred — 与现有的 JSX 合成器和视图端组合
涡轮增压模块。当 ≥1 个 §5b 语料库存储库有桥时的地址
否则关闭,但结构流仍然中断。

---

## 7. 反目标(我们不会尝试做的事情)

- **Android Kotlin/Java 提取质量** — 超出范围。我们用什么
Kotlin/Java 提取器已经生成。如果他们错过了 `@ReactMethod`
注释的字面名称我们可以添加一个微小的提取器细化,但是我们
不要重新设计 JVM 提取。
- **动态/计算桥键** — `NativeModules[someVar]`,
`requireNativeModule(name)` 其中`name`是参数等。我们只
解析文字键访问(匹配
[代理评估 Lua 前沿](./dynamic-dispatch-coverage-playbook.md) — 仅匿名模式被推迟)。
- **桥接头文件内容解析** — 我们*做*索引 `.h` 文件
(已经通过#165的内容嗅探做到了)但我们**不**解析
桥接标头的 `#import` 列表作为特殊的“Swift 可见内容”
显现。将其视为普通的 ObjC 标头。
- **`performSelector:` 上的运行时调度** — 超出范围;匹配
同样的“仅限命名”的反目标。
- **JSI(原始、非 TurboModule)** — 超出范围。使用裸 JSI 的应用程序
通过没有记录的自定义 `Host*` 接口调用本机
声明性规范等待这些应用程序迁移到 TurboModules。
- **ObjC 协议上的仅 Swift 泛型/ObjC 上的 Swift 扩展
类** — 如果 `@objc`,扩展方法仍然可以在 ObjC 中调用,所以
他们经历相同的第一阶段路径。泛型不是——我们默默地
想念他们。可以接受;匹配 Java/Kotlin 泛型前沿。

---

## 8. 覆盖矩阵条目——测量

| 语言 | 框架 | 规范流 | 机制 | 地位 |
|---|---|---|---|---|
| Swift × Objective-C | 桥接 | Swift 调用 → ObjC 选择器; ObjC 调用 → @objc Swift 方法 | 右 | ✅ 第 1 阶段 (§8a) |
| JavaScript × Objective-C/Java/Kotlin | React Native 遗留桥 | `NativeModules.<M>.<f>` → `RCT_EXPORT_METHOD` / `@ReactMethod` | 右 | ✅ 第 2 阶段 (§8b) |
| JavaScript × 原生 | React Native TurboModules | 规范接口 ↔ impl | R(规范作为基本事实) | ✅ 部分 — 名称匹配路径着陆 (§8b) |
| Objective-C/Java/Kotlin → JavaScript | React Native 事件发射器 | `[self sendEventWithName:]` → `addListener` | S(跨语言通道) | ✅ 第 3 阶段 (§8e) |
| JavaScript × Swift/Kotlin | 世博模块 | `requireNativeModule('X').fn(...)` → `Function("fn") { }` | R(提取合成方法节点) | ✅ 第 4 阶段 (§8f) |
| JavaScript × 原生 | React Native Fabric 视图 | `<MyView p=v/>` → Codegen 规范组件 + NativeProps | R(提取)+ S(原生实现)+ JSX | ✅ 第 6 阶段(§8g) |

### 8a.第一阶段测量 — Swift ↔ ObjC

| 回购协议 | 源文件 | 桥接边缘(框架解析) | 样品边缘 |
|---|---|---|---|
| **图表**(小) | 269(205 斯威夫特 + 59 ObjC/.h) | 28 objc→swift, 1 swift→objc | `handleOption:forChartView:` → `animate` · `setupPieChartView:` → `setExtraOffsets` · `setDataCount:range:` → `setColor` |
| **领域-快速**(中) | 369(151 Swift + 218 ObjC 系列) | 36 objc→斯威夫特, 1185 斯威夫特→objc | `valueForUndefinedKey:` → `get` · `setValue:forUndefinedKey:` → `set` · `promote:on:` → `initialize` |
| **维基百科-ios**(大) | 1734(1234 斯威夫特 + 500 ObjC/.h) | 52 objc→斯威夫特, 983 斯威夫特→objc | 真实 iOS 应用程序跨多个功能模块的桥接 |

所有这三个:语言基线不变,没有节点数爆炸,
`trace` 连接跨边界的规范流(已在
图表:`trace(handleOption:forChartView:, animate)` 表面
直接桥接边缘)。

### 8b.第 2 + 5 阶段(部分)测量 — React Native 桥

| 回购协议 | 源文件 | 桥接边缘(框架解析) | 笔记 |
|---|---|---|---|
| **react-native-svg**(小/中) | 〜700(93 .mm + 115 .java + 6 .kt + 49 js + 92 ts + 154 tsx) | 9 tsx→java 通过 TurboModule 规范 | RNSvg 的 iOS 使用 TurboModule auto-gen (无 `RCT_EXPORT_METHOD`);决议涉及爪哇岛。所有 9 个精确:`isPointInStroke`、`isPointInFill`、`getTotalLength`、`getPointAtLength`、`getCTM`、`getScreenCTM`、`getBBox`、`toDataURL`。 |
| **AsyncStorage**(小型、纯遗留桥) | ~60(28 kt + 2 mm + 16 ts + 14 tsx + …) | **8/8 精确** | 规范的遗留桥接测试 — Kotlin `@ReactMethod` + ObjC `RCT_EXPORT_METHOD`。 JS `setItem` → Kotlin `legacy_multiSet`; `getItem` → `legacy_multiGet`; `clear` → `legacy_clear`; ETC。 |
| **react-native-firebase**(大) | 〜1100(111 .java + 63 .m + 13 .mm + 239 js + 427 ts + 9 tsx) | RCTEventEmitter 黑名单后为 18(之前为 78) | 最初的 78 个包括 60 个针对 `addListener:` / `remove:` 的误报(每个 RCTEventEmitter 都声明它们;每个对 `.addListener(...)` 的 JS 调用都解析为噪声)。黑名单削减至 18 个,全部精确:`httpsCallable:region:emulatorHost:...`、`signInWithProvider`、`configureProvider`、`removeFunctionsStreaming:`。 |
| **反应本机屏幕**(中) | 1211 | 0 — 空 TurboModule 规范,无 `RCT_EXPORT_METHOD`,所有 Fabric/Codegen 视图端 | RNScreens 完全处于第 6 阶段(Fabric,延迟)。桥牌在这里拒绝过度匹配是正确的行为。 |

### 8c.验证期间发现的架构修复

解析器的 `initialize()` 在 RustCodeGraph 构造中运行 - 在任何之前
文件被索引 - 因此 `detect()` 咨询的框架解析器
索引文件列表(UIKit / SwiftUI 扫描导入,
`swift-objc-bridge` 寻找 Swift 和 ObjC 文件,
`react-native-bridge` 寻找 RN 标记)全部返回 false
最初的通过并默默地放弃了自己。这影响了每一个
代码库中的框架解析器读取 `context.getAllFiles()` /
`context.readFile()` 而不是直接扫描文件系统 - a
预先存在的潜在错误,不是特定于桥的。已修复:现在 `indexAll()`
提取完成后调用 `resolver.initialize()`,因此 detector()
针对填充的索引运行。

### 8d.桥接精度阻止列表(经验教训)

| 桥 | 被屏蔽的名字 | 原因 |
|---|---|---|
| swift-objc | `init`、`description`、`hash`、`isEqual`、`copy`、`count`、`value`、`data`、`string`、`object`、`add`、`remove`、`update`、`load`、 `save`、`reload`、`cancel`、`start`、`stop`、`pause`、`resume`、`close`、`open`、`show`、`hide`、`dealloc`、`release`、 `retain`、`autorelease`、…… | 每个 NSObject 子类都实现了这些;将它们桥接到任意项目本地 ObjC 方法会产生噪音。常规名称匹配器会自行处理它们。 |
| 反应本机 | `addListener`、`removeListeners`、`remove`、`invalidate`、`startObserving`、`stopObserving` | 每个 `RCTEventEmitter` 子类都通过 `RCT_EXPORT_METHOD` 声明它们。 `.addListener(...)` / `.remove(...)` 的 JS 调用者通过 `NativeEventEmitter` (JS 抽象),而不是直接通过本机桥。 |

### 8e.第 3 阶段测量 — RN 原生 → JS 事件通道

合成器模式;将 `src/resolution/callback-synthesizer.ts` 扩展为
由文字事件名称键入的跨语言事件通道。验证于
**RNFirebase**(大):

| 合成事件通道 | 边缘 | 样本 |
|---|---|---|
| `messaging_message_received` | 2 | `application:didReceiveRemoteNotification:fetchCompletionHandler:` → TS `onMessage`(并且 `UNUserNotificationCenter` 将呈现变体 → 相同的 `onMessage`) |
| `messaging_notification_opened` | 1 | `userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:` → TS `onNotificationOpenedApp` |

每条边都是`provenance:'heuristic'`,
`metadata.synthesizedBy:'rn-event-channel'`。相同`EVENT_FANOUT_CAP = 6`
作为语言通道 - 具有太多处理程序的通用事件名称
或者调度员跳过而不是过度链接。

合成器还处理常见的 **订阅包装模式**
RN 库(`messaging().onMessage(listener)`,其中 `listener` 是
流向用户代码的参数):当 JS 处理程序 arg 不是
命名符号,它将侦听器归因于 ENCLOSING JS 函数
(可达性正确,抽象层的属性)。

### 8f.第四阶段测量——Expo 模块

框架 `extract()` 解析 Swift / Kotlin 源代码以获取文字
`Function("X") { … }` / `AsyncFunction("X") { … }` / `Property("X") { … }`
/ `Constants` 里面的声明 `class X: Module` (或者 `: Module()` 里面
Kotlin) 并为每个文字发出一个名为 `X` 的 `method` 节点。标准
name-matcher 将 `Foo.takePictureAsync(...)` 之类的 JS 调用解析为
这些合成节点通过现有的 `obj.method` → 方法名称路径。

在真实的 Expo SDK 包上进行验证:

| 包裹 | 文件已编入索引 | 提取的 Expo 方法节点 | 跨语言边缘 |
|---|---|---|---|
| **世博会触觉** | 14 | 6(3 Swift + 3 Kotlin:`notificationAsync`、`impactAsync`、`selectionAsync` / `performHapticsAsync`) | 模块节点注册;消费者应用程序调用者通过名称匹配进行解析 |
| **世博相机** | 72 | 41(Swift + Kotlin;涵盖 `takePictureAsync`、`record`、`resumePreview`、`getAvailableLenses`、`scanFromURLAsync`、`requestCameraPermissionsAsync`、视图端 `width` / `height` 属性,...) | 9 swift→expo,7 kotlin→expo 内部边缘。包中的 JS 端调用点使用 TS 包装器隐藏本机名称(在 `CameraView.tsx` 上定义的 `pausePreview()`); name-match 正确地更喜欢本地 TS 方法。 `Camera.takePictureAsync()` 的外部消费者应用程序直接解析为本机方法。 |

五项测试涵盖提取器 + 端到端固定装置:
文字 AsyncFunction("uniqueExpoHapticCall") 的 JS 调用点解析
到本机 impl 节点` — 确认无解析器的桥接路径
当名称没有阴影时有效。

### 8克。第 6 阶段测量——Fabric/Codegen 视图组件

两部分设计:

1. **框架提取器** (`src/resolution/frameworks/fabric.ts`) — 解析
`codegenNativeComponent<Props>('Name', ...)` 的 TS / TSX 规格文件
声明。发出:
   - 每个声明一个 `component` 节点(以 JS-visible 命名)
组件名称;匹配 JSX 合成器的 name+kind 过滤器)。
   - `NativeProps` 的每个声明字段有一个 `property` 节点
接口 — 呈现 JSX 可调用的 props,例如 `onTap`,
`nativeContainerBackgroundColor` 作为可发现的图节点。

2. **合成器**(`callback-synthesizer.ts` 中的 `fabricNativeImplEdges`)—
遍历每个 `fabric-component:*` 节点并寻找本地类
将其名称与 RN 的约定后缀之一匹配(空 / `View`
/ `ViewManager` / `ComponentView` / `Manager`)。发出 `calls` 边缘
组件中的 `metadata.synthesizedBy:'fabric-native-impl'`
每场比赛。约定足够精确,以至于没有名字
结构良好的 RN 库中的碰撞。

与现有的 `reactJsxChildEdges` JSX 合成器相结合,该
关闭完整的 JSX → 原生流程:消费者应用程序 JSX `<MyView prop=v/>`
→ Fabric `component` 节点 `MyView` → 原生类 `MyViewView`
(或 `MyViewManager` / `MyViewComponentView` / …)。

在**react-native-screens**(语料库存储库)上重新验证
完全 Fabric 并在第 2 阶段显示 0 个桥):

| 公制 | 数数 |
|---|---|
| `codegenNativeComponent` 规格声明 | 54 |
| 提取的 Fabric 组件节点 | 27(每个非网络规范一个;`*.web.ts` 变体按规范有效性过滤掉) |
| 提取的 Fabric 支撑节点 | 272(所有组件的完整 NativeProps 界面) |
| `fabric-native-impl` 桥边 | 68 |

桥边缘示例:

| JS组件 | 母语班 | 后缀 |
|---|---|---|
| `RNSFullWindowOverlay` | `RNSFullWindowOverlay`(对象) | (精确的) |
| `RNSFullWindowOverlay` | `RNSFullWindowOverlayManager`(对象) | `Manager` |
| `RNSModalScreen` | `RNSModalScreenManager`(对象) | `Manager` |
| `RNSScreenContainer` | `RNSScreenContainerView`(对象) | `View` |

四项测试涵盖提取器 + 完整的端到端夹具
(`App (TSX) → MyView (fabric-component) → MyViewView (ObjC class)`)
断言 JSX→组件边缘 AND
组件→本机类边在索引后都存在。

---

## 9. 第一阶段需要解决的开放性问题

这些并不会阻碍第一阶段的开始——它们是首先要做的事情
*在*编写 Swift↔ObjC 解析器时决定:

1. **声明上的别名与新桥接边缘?** 存储自动桥接
ObjC 选择器作为 Swift 方法节点上的替代名称更便宜
并与名称解析的工作方式保持一致。另一种选择
(在匹配节点之间合成跨语言`references`边)
在 `trace` 输出中更明确,但为每个 `@objc` 符号添加 N 个边。
**默认:alias。** 验证 `callers`/`callees`/`trace` 中的别名表面
结果。
2. **`trace` 如何显示跨语言跳转?** MCP `trace` 工具
内联每个跃点的主体。 Swift → ObjC 跳跃应该使这一点显而易见
渲染的输出(“Swift `func foo(bar:)` →桥接到 ObjC 选择器
`-fooWithBar:` → ObjC `-[ImageDownloader fooWithBar:]`”)。可能会
需要在 `trace.ts` 中对渲染器进行小的调整来标记桥。
3. **解析器桥接规则位于哪里?** 建议
`src/resolution/frameworks/swift-objc.ts` 用于自动名称映射(
纯函数)由 Swift 提取器导入(以计算
提取时的别名)和测试。将映射保留在一处。
4. **`@objcMembers` 怎么样?** 类级别导出 — 适用于所有成员
除非`@nonobjc`。通过检查 Swift 中类的修饰符来处理
提取器并从中默认每个成员的 `@objc`-ness。

---

## 10. 完成吧(这样我们就知道何时停止)

第 1 阶段 (Swift↔ObjC) 在以下情况下完成:
- 所有三个 §5a 语料库均通过:纯语言探测不变;跨语言
规范流探针找到端到端的路径;代理 A/B 显示 Read = 0
使用 rustcodegraph 运行 ≥1 次,比不使用更快。
- 手册第 6 节中的覆盖矩阵行用数字填充。
- 存在 CHANGELOG `[Unreleased]` 条目,是在用户端写入的。

每个后续阶段都有相同的形状 - 它自己的 §5 语料库,它自己的
矩阵行,它自己的 CHANGELOG 条目 — 并且 ** 直到
前一项通过**。在这里,半桥是必须避免的;他们
积极地使 rustcodegraph 在这些代码库上比没有任何代码更糟糕
根本无法桥接。