mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-04 02:31:36 +00:00
fix(group): assign thrift synthetic symbol uids
This commit is contained in:
parent
904457afa3
commit
476af9b152
3 changed files with 181 additions and 1 deletions
|
|
@ -178,6 +178,17 @@ function extractMethods(sanitizedServiceBody: string): string[] {
|
|||
return methods;
|
||||
}
|
||||
|
||||
function thriftSourceScanSymbolUid(
|
||||
contractId: string,
|
||||
role: 'provider' | 'consumer',
|
||||
filePath: string,
|
||||
symbolName: string,
|
||||
): string {
|
||||
return ['source-scan::thrift', role, contractId, normalizeThriftPath(filePath), symbolName].join(
|
||||
'::',
|
||||
);
|
||||
}
|
||||
|
||||
function makeContract(
|
||||
cid: string,
|
||||
role: 'provider' | 'consumer',
|
||||
|
|
@ -190,7 +201,7 @@ function makeContract(
|
|||
contractId: cid,
|
||||
type: 'thrift',
|
||||
role,
|
||||
symbolUid: '',
|
||||
symbolUid: thriftSourceScanSymbolUid(cid, role, filePath, symbolName),
|
||||
symbolRef: { filePath: normalizeThriftPath(filePath), name: symbolName },
|
||||
symbolName,
|
||||
confidence,
|
||||
|
|
|
|||
|
|
@ -303,6 +303,65 @@ describe('syncGroup', () => {
|
|||
expect(result.unmatched).toEqual([provider]);
|
||||
});
|
||||
|
||||
it('keeps wildcard thrift links to multiple extracted IDL provider methods', async () => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gitnexus-sync-thrift-wildcard-'));
|
||||
fs.mkdirSync(path.join(tmpDir, 'idl'), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, 'idl', 'order.thrift'),
|
||||
`namespace java billing.v1
|
||||
|
||||
service OrderService {
|
||||
PlaceOrderResponse PlaceOrder(1: PlaceOrderRequest request)
|
||||
OrderResponse GetOrder(1: string orderId)
|
||||
}`,
|
||||
);
|
||||
|
||||
try {
|
||||
const { ThriftExtractor } = await import(
|
||||
'../../../src/core/group/extractors/thrift-extractor.js'
|
||||
);
|
||||
const extractedProviders = (await new ThriftExtractor().extract(null, tmpDir, {
|
||||
id: 'provider-repo',
|
||||
path: 'app/provider',
|
||||
repoPath: tmpDir,
|
||||
storagePath: path.join(tmpDir, '.gitnexus'),
|
||||
}))
|
||||
.filter((c) => c.role === 'provider')
|
||||
.map(
|
||||
(c): StoredContract => ({
|
||||
...c,
|
||||
repo: 'app/provider',
|
||||
}),
|
||||
);
|
||||
|
||||
const consumer: StoredContract = {
|
||||
contractId: 'thrift::OrderService/*',
|
||||
type: 'thrift',
|
||||
role: 'consumer',
|
||||
symbolUid: 'manifest::app/consumer::thrift::OrderService/*',
|
||||
symbolRef: { filePath: 'group.yaml', name: 'OrderService' },
|
||||
symbolName: 'OrderService',
|
||||
confidence: 1,
|
||||
meta: {},
|
||||
repo: 'app/consumer',
|
||||
};
|
||||
|
||||
const result = await syncGroup(makeConfig({}), {
|
||||
extractorOverride: async () => [...extractedProviders, consumer],
|
||||
skipWrite: true,
|
||||
});
|
||||
|
||||
expect(result.crossLinks).toHaveLength(2);
|
||||
expect(result.crossLinks.map((cl) => cl.to.symbolRef.name).sort()).toEqual([
|
||||
'OrderService.GetOrder',
|
||||
'OrderService.PlaceOrder',
|
||||
]);
|
||||
expect(new Set(result.crossLinks.map((cl) => cl.to.symbolUid)).size).toBe(2);
|
||||
} finally {
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('matches weak thrift method consumers to namespace-qualified providers during sync', async () => {
|
||||
const config = makeConfig({ 'app/provider': 'provider-repo', 'app/consumer': 'consumer-repo' });
|
||||
const provider: StoredContract = {
|
||||
|
|
@ -341,6 +400,81 @@ describe('syncGroup', () => {
|
|||
expect(result.unmatched).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('keeps exact thrift links to extracted IDL and Java providers for same method', async () => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gitnexus-sync-thrift-exact-'));
|
||||
fs.mkdirSync(path.join(tmpDir, 'idl'), { recursive: true });
|
||||
fs.mkdirSync(path.join(tmpDir, 'src', 'main', 'java', 'example'), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, 'idl', 'order.thrift'),
|
||||
`namespace java billing.v1
|
||||
|
||||
service OrderService {
|
||||
PlaceOrderResponse PlaceOrder(1: PlaceOrderRequest request)
|
||||
}`,
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, 'src', 'main', 'java', 'example', 'IfaceOrderHandler.java'),
|
||||
`package example;
|
||||
|
||||
class IfaceOrderHandler implements OrderService.Iface {
|
||||
public PlaceOrderResponse PlaceOrder(PlaceOrderRequest request) {
|
||||
return new PlaceOrderResponse();
|
||||
}
|
||||
}`,
|
||||
);
|
||||
|
||||
try {
|
||||
const { ThriftExtractor } = await import(
|
||||
'../../../src/core/group/extractors/thrift-extractor.js'
|
||||
);
|
||||
const extractedProviders = (await new ThriftExtractor().extract(null, tmpDir, {
|
||||
id: 'provider-repo',
|
||||
path: 'app/provider',
|
||||
repoPath: tmpDir,
|
||||
storagePath: path.join(tmpDir, '.gitnexus'),
|
||||
}))
|
||||
.filter((c) => c.role === 'provider')
|
||||
.map(
|
||||
(c): StoredContract => ({
|
||||
...c,
|
||||
repo: 'app/provider',
|
||||
}),
|
||||
);
|
||||
|
||||
const consumer: StoredContract = {
|
||||
contractId: 'thrift::OrderService/PlaceOrder',
|
||||
type: 'thrift',
|
||||
role: 'consumer',
|
||||
symbolUid: [
|
||||
'source-scan::thrift',
|
||||
'consumer',
|
||||
'thrift::OrderService/PlaceOrder',
|
||||
'src/BillingWorkflow.java',
|
||||
'orderService.PlaceOrder',
|
||||
].join('::'),
|
||||
symbolRef: { filePath: 'src/BillingWorkflow.java', name: 'orderService.PlaceOrder' },
|
||||
symbolName: 'orderService.PlaceOrder',
|
||||
confidence: 0.45,
|
||||
meta: {},
|
||||
repo: 'app/consumer',
|
||||
};
|
||||
|
||||
const result = await syncGroup(makeConfig({}), {
|
||||
extractorOverride: async () => [...extractedProviders, consumer],
|
||||
skipWrite: true,
|
||||
});
|
||||
|
||||
expect(result.crossLinks).toHaveLength(2);
|
||||
expect(result.crossLinks.map((cl) => cl.to.symbolRef.filePath).sort()).toEqual([
|
||||
'idl/order.thrift',
|
||||
'src/main/java/example/IfaceOrderHandler.java',
|
||||
]);
|
||||
expect(new Set(result.crossLinks.map((cl) => cl.to.symbolUid)).size).toBe(2);
|
||||
} finally {
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('extracts thrift contracts during real sync when thrift detection is enabled', async () => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gitnexus-sync-thrift-'));
|
||||
const storageDir = path.join(tmpDir, '.gitnexus');
|
||||
|
|
|
|||
|
|
@ -455,6 +455,41 @@ class GeneratedOrderHandler implements OrderService {
|
|||
}
|
||||
});
|
||||
|
||||
it('test_extract_thrift_source_scan_contracts_have_stable_distinct_symbol_uids', async () => {
|
||||
writeFile(
|
||||
'idl/order.thrift',
|
||||
`namespace java billing.v1
|
||||
|
||||
service OrderService {
|
||||
PlaceOrderResponse PlaceOrder(1: PlaceOrderRequest request)
|
||||
}`,
|
||||
);
|
||||
writeFile(
|
||||
'src/main/java/example/IfaceOrderHandler.java',
|
||||
`package example;
|
||||
|
||||
class IfaceOrderHandler implements OrderService.Iface {
|
||||
public PlaceOrderResponse PlaceOrder(PlaceOrderRequest request) {
|
||||
return new PlaceOrderResponse();
|
||||
}
|
||||
}`,
|
||||
);
|
||||
|
||||
const first = await extractor.extract(null, tmpDir, makeRepo(tmpDir));
|
||||
const second = await extractor.extract(null, tmpDir, makeRepo(tmpDir));
|
||||
const providers = first
|
||||
.filter((c) => c.role === 'provider')
|
||||
.sort((a, b) => a.symbolRef.filePath.localeCompare(b.symbolRef.filePath));
|
||||
const repeatedProviders = second
|
||||
.filter((c) => c.role === 'provider')
|
||||
.sort((a, b) => a.symbolRef.filePath.localeCompare(b.symbolRef.filePath));
|
||||
|
||||
expect(providers).toHaveLength(2);
|
||||
expect(providers.map((c) => c.symbolUid)).toEqual(repeatedProviders.map((c) => c.symbolUid));
|
||||
expect(providers.every((c) => c.symbolUid.length > 0)).toBe(true);
|
||||
expect(new Set(providers.map((c) => c.symbolUid)).size).toBe(2);
|
||||
});
|
||||
|
||||
it('test_extract_java_thrift_providers_from_fully_qualified_generated_iface', async () => {
|
||||
writeFile(
|
||||
'idl/order.thrift',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue