A batch whose functions were all already on main (only confirmed now) was titled "Decompile N functions", while its diff showed only the batch's other changes. When a split keeps pending code, annotations that are on main stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RNwtXPYqFu3oKaaXwYwNWW
62 lines
2.8 KiB
JavaScript
62 lines
2.8 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { functionRegions, withoutFunctions } from '../src/server/split.js';
|
|
|
|
const file = `#include "a.h"
|
|
|
|
// FUNCTION: fn_00001
|
|
int a() {
|
|
const char* s = "}";
|
|
return 1; // }
|
|
}
|
|
|
|
// FUNCTION: fn_00002
|
|
// FUNCTION: fn_00003
|
|
int folded() { /* { */ return 2; }
|
|
|
|
// FUNCTION: fn_00004
|
|
int b() {
|
|
return 4;
|
|
}
|
|
`;
|
|
|
|
test('function regions run from the annotations to the closing brace', () => {
|
|
const r = functionRegions(file);
|
|
assert.deepEqual([r.get('fn_00001').start, r.get('fn_00001').end], [2, 7]);
|
|
assert.equal(r.get('fn_00002'), r.get('fn_00003'));
|
|
assert.deepEqual([r.get('fn_00004').start, r.get('fn_00004').end], [12, 16]);
|
|
});
|
|
|
|
test('withoutFunctions restores pending functions from the base, or drops new ones', () => {
|
|
const base = file.replace('return 4;', 'return 0; // old');
|
|
const out = withoutFunctions({ 'a.cpp': file }, ['fn_00004'], () => base);
|
|
assert.equal(out['a.cpp'], base);
|
|
const dropped = withoutFunctions({ 'a.cpp': file }, ['fn_00004'], () => null);
|
|
assert.doesNotMatch(dropped['a.cpp'], /int b\(\)/);
|
|
assert.match(dropped['a.cpp'], /int folded\(\)/);
|
|
// One body shared by a pending and a finished function: only the pending annotation goes.
|
|
const kept = withoutFunctions({ 'a.cpp': file }, ['fn_00002'], () => null)['a.cpp'];
|
|
assert.doesNotMatch(kept, /fn_00002/);
|
|
assert.match(kept, /\/\/ FUNCTION: fn_00003\nint folded\(\)/);
|
|
});
|
|
|
|
test('an annotated declaration is a region of its own instead of stopping the split', () => {
|
|
const text = '// STUB: fn_00010\nvoid declared(int a);\n\n// FUNCTION: fn_00011\nint defined() {\n return 1;\n}\n';
|
|
const r = functionRegions(text);
|
|
assert.deepEqual([r.get('fn_00010').start, r.get('fn_00010').end], [0, 2]);
|
|
assert.deepEqual([r.get('fn_00011').start, r.get('fn_00011').end], [3, 7]);
|
|
const out = withoutFunctions({ 'a.cpp': text }, ['fn_00011'], () => null);
|
|
assert.equal(out['a.cpp'], '// STUB: fn_00010\nvoid declared(int a);\n\n');
|
|
});
|
|
|
|
test('keepCode keeps the pending code and drops only its annotations', () => {
|
|
const text = '// FUNCTION: fn_00001\nint helper(int x) {\n return x;\n}\n\n// FUNCTION: fn_00002\nint user() {\n return helper(2);\n}\n';
|
|
const out = withoutFunctions({ 'a.cpp': text }, ['fn_00001'], () => 'int helper() {\n return 1;\n}\n', { keepCode: true });
|
|
assert.equal(out['a.cpp'], 'int helper(int x) {\n return x;\n}\n\n// FUNCTION: fn_00002\nint user() {\n return helper(2);\n}\n');
|
|
});
|
|
|
|
test('keepCode leaves annotations that are already on main', () => {
|
|
const text = '// FUNCTION: fn_00001\nint helper(int x) {\n return x;\n}\n\n// FUNCTION: fn_00002\nint user() {\n return helper(2);\n}\n';
|
|
const base = '// FUNCTION: fn_00001\nint helper() {\n return 1;\n}\n';
|
|
assert.equal(withoutFunctions({ 'a.cpp': text }, ['fn_00001'], () => base, { keepCode: true })['a.cpp'], text);
|
|
});
|