I didn’t want to post my code, so I tried to reproduce the issue by leaving a semicolon out of blink.ino - but it gave the correct line number.
I then posted my code into the blink.ino sketch, and it too gave the correct line number!
I set about looking for every possible difference I could in the files within the project folder without success - then I noticed character encoding and line endings.
For anyone else that comes across this: Change your line endings from CRLF to LF! That’s all this issue was. I don’t know how I’ve managed to get this inconsistent across my projects, but I’m glad I’ve finally figured it out!