The full sources of the “compiler” is here.
The basic idea is that I parse each lines of the original rescript code and the compiled code looking for corresponding tests. It is done in a way that multiple tests can have the same string.
const TEST_RE = /(describe|it|test|only|skip|todo)\(("([^"]*)")/;
And then I interploate corresponding line numbers between the two files:
const map = new SourceMapGenerator({ file: path });
// rescript line, compiled line
function sm(rline: number, cline: number) {
map.addMapping({
source: path,
generated: { line: cline, column: 0 },
original: { line: rline, column: 0 },
});
}
let ri = 1;
let ci = 1;
for (const [rline, cline] of smap) {
let dr = rline - ri;
let dc = cline - ci;
if (dr > dc) {
for (let i = 1; i <= dr; i++) {
sm(ri + i, Math.ceil(ci + (i * dc) / dr));
}
} else {
for (let i = 1; i <= dc; i++) {
sm(Math.ceil(ri + (i * dr) / dc), ci + i);
}
}
ri = rline;
ci = cline;
}
The smap array is built by first parsing rescript and then matching the lines in the compiled source.
At the end, I send the compiled JS sources with the source maps to vitest.