mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-30 06:42:43 +00:00
fix(r): order merged bindings by code unit, not by locale
rMergeBindings sorted same-tier bindings with localeCompare, whose order follows the machine's locale. Compare node ids by code unit, as the package discovery does.
This commit is contained in:
parent
33d411c50c
commit
72af8166b7
2 changed files with 40 additions and 1 deletions
|
|
@ -28,7 +28,10 @@ export function rMergeBindings(
|
|||
if ((TIER[b.origin] ?? 99) !== bestTier) continue;
|
||||
if (!byNode.has(b.def.nodeId)) byNode.set(b.def.nodeId, b);
|
||||
}
|
||||
return [...byNode.values()].sort((a, b) => a.def.nodeId.localeCompare(b.def.nodeId));
|
||||
// By code unit, not `localeCompare`: the order must not depend on the machine's locale.
|
||||
return [...byNode.values()].sort((a, b) =>
|
||||
a.def.nodeId < b.def.nodeId ? -1 : a.def.nodeId > b.def.nodeId ? 1 : 0,
|
||||
);
|
||||
}
|
||||
|
||||
/** R declarations carry no synthesized arity metadata (no `...`/default-arg
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* `rMergeBindings` orders the bindings of one tier by node id. The order must be the same on every
|
||||
* machine, so it compares code units, not `localeCompare`, which follows the locale: in an
|
||||
* English collation `a` sorts before `B` and `é` before `f`; by code unit `B` and `f` come first.
|
||||
*/
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { BindingRef, SymbolDefinition } from 'gitnexus-shared';
|
||||
import { rMergeBindings } from '../../../../src/core/ingestion/languages/r/simple-hooks.js';
|
||||
|
||||
const local = (nodeId: string): BindingRef => ({
|
||||
origin: 'local',
|
||||
def: { nodeId } as SymbolDefinition,
|
||||
});
|
||||
|
||||
const order = (...ids: string[]): string[] =>
|
||||
rMergeBindings(ids.map(local), [], 'scope:test').map((b) => b.def.nodeId);
|
||||
|
||||
describe('rMergeBindings', () => {
|
||||
it('orders same-tier bindings by code unit', () => {
|
||||
expect(order('Function:a.R:a', 'Function:a.R:B')).toEqual(['Function:a.R:B', 'Function:a.R:a']);
|
||||
expect(order('Function:a.R:é', 'Function:a.R:f')).toEqual(['Function:a.R:f', 'Function:a.R:é']);
|
||||
});
|
||||
|
||||
it('gives the same order whichever way round the bindings arrive', () => {
|
||||
expect(order('Function:a.R:B', 'Function:a.R:a')).toEqual(['Function:a.R:B', 'Function:a.R:a']);
|
||||
});
|
||||
|
||||
it('keeps one binding per node and prefers the tightest tier', () => {
|
||||
const merged = rMergeBindings(
|
||||
[local('Function:a.R:x'), { origin: 'import', def: { nodeId: 'Function:b.R:x' } as never }],
|
||||
[local('Function:a.R:x')],
|
||||
'scope:test',
|
||||
);
|
||||
expect(merged.map((b) => b.def.nodeId)).toEqual(['Function:a.R:x']);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue