Files
codegraph/__tests__/framework-edge-name.test.ts
Colby Mchenry 5ba3674629 fix(resolution): a framework-resolved edge names its resolver (#2159)
The README said every bridge hop carries `metadata.synthesizedBy`, but only
the synthesized channels (rn-event-channel, fabric-native-impl) did; a
resolver-made hop (Swift↔ObjC, RN legacy / TurboModules, Expo Modules JS)
carried only `resolvedBy: 'framework'`, and `expo-module-extract` named
nothing that exists. The framework loop now adds `metadata.framework` (the
resolver's name: swift-objc-bridge, react-native-bridge, expo-modules-js,
fabric-view, rails, laravel, …) and the README says what each kind carries.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:36:02 +00:00

58 lines
1.8 KiB
TypeScript

/**
* A link a framework or bridge resolver made names that resolver on the edge
* (`metadata.framework`), as a synthesized channel names itself with
* `synthesizedBy`: a Swift → Objective-C hop says `swift-objc-bridge`.
*/
import { describe, it, expect, afterAll, beforeAll } from 'vitest';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { CodeGraph } from '../src';
let root = '';
let cg: CodeGraph;
beforeAll(async () => {
root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-framework-edge-'));
const files: Record<string, string> = {
'Sources/Cache.h': `#import <Foundation/Foundation.h>
@interface Cache : NSObject
- (id)fetchEntryForKey:(NSString *)key;
@end
`,
'Sources/Cache.m': `#import "Cache.h"
@implementation Cache
- (id)fetchEntryForKey:(NSString *)key {
return nil;
}
@end
`,
'Sources/Caller.swift': `import Foundation
func load(cache: Cache) {
_ = cache.fetchEntry(forKey: "x")
}
`,
};
for (const [rel, content] of Object.entries(files)) {
fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true });
fs.writeFileSync(path.join(root, rel), content);
}
cg = await CodeGraph.init(root, { index: true });
});
afterAll(() => {
cg?.close();
if (root) fs.rmSync(root, { recursive: true, force: true });
});
describe('framework-resolved edges', () => {
it('name the resolver that made them', () => {
const caller = cg.getNodesInFile('Sources/Caller.swift').find((n) => n.name === 'load')!;
const bridged = cg.getOutgoingEdges(caller.id).find((e) => cg.getNode(e.target)?.name === 'fetchEntryForKey:');
expect(bridged).toBeDefined();
expect(bridged!.metadata?.resolvedBy).toBe('framework');
expect(bridged!.metadata?.framework).toBe('swift-objc-bridge');
});
});