Line counter should track all line ends, not just at end of segment
martypdx opened this issue · comments
Motivation
Want to use lineEnd
anywhere code chunk with source maps:
// normally calculated from state.indent, lineEnd, etc.
state.write(`\n `);
Expected behavior
state.line
increments for each occurance of lineEnd
in code
Actual behavior
state.line
only increments once when newLine is at end of code chunk
Here's a possible algorithm:
function testTrack(code, lineEnd) {
const state = { line: 1, column: 0 };
// these lines replace those in writeAndMap
if(code.length > 0) {
const segments = code.split(lineEnd);
state.line += (segments.length - 1) * lineEnd.length;
state.column += segments.at(-1).length;
}
return state;
}
test('track new line', ({ expect }) => {
expect(testTrack(` `, `\n`)).toEqual({ column: 4, line: 1, });
expect(testTrack(`\n `, `\n`)).toEqual({ column: 4, line: 2, });
expect(testTrack(` \n`, `\n`)).toEqual({ column: 0, line: 2, });
expect(testTrack(` \n `, `\n`)).toEqual({ column: 4, line: 2, });
expect(testTrack(`\n\n`, `\n`)).toEqual({ column: 0, line: 3, });
expect(testTrack(`\n\n `, `\n`)).toEqual({ column: 4, line: 3, });
expect(testTrack(` \n\n `, `\n`)).toEqual({ column: 4, line: 3, });
expect(testTrack(` \n\n`, `\n`)).toEqual({ column: 0, line: 3, });
expect(testTrack(`\n \n`, `\n`)).toEqual({ column: 0, line: 3, });
});
test('track \r\n', ({ expect }) => {
expect(testTrack(` `, `\r\n`)).toEqual({ column: 4, line: 1, });
expect(testTrack(`\r\n `, `\r\n`)).toEqual({ column: 4, line: 3, });
expect(testTrack(` \r\n`, `\r\n`)).toEqual({ column: 0, line: 3, });
expect(testTrack(` \r\n `, `\r\n`)).toEqual({ column: 4, line: 3, });
expect(testTrack(`\r\n\r\n`, `\r\n`)).toEqual({ column: 0, line: 5, });
expect(testTrack(`\r\n\r\n `, `\r\n`)).toEqual({ column: 4, line: 5, });
expect(testTrack(` \r\n\r\n `, `\r\n`)).toEqual({ column: 4, line: 5, });
expect(testTrack(` \r\n\r\n`, `\r\n`)).toEqual({ column: 0, line: 5, });
expect(testTrack(`\r\n \r\n`, `\r\n`)).toEqual({ column: 0, line: 5, });
});
Ugh, but it doesn't count in a string literal, right? Like let s = '\n';
How about doing this instead?
state.write('\n');
state.write(' ');
Yep, that's I ended up doing:
Process (write to state) line endings independently before the new line indentation.
To me, this limitation is fine, so feel free to close. Probably good to add a note in the docs.
Makes sense, it should indeed be clarified in the documentation.
Note that alternate approaches would considerably slow down the code generation.