rescript-lang / rescript-lang/rescript-vscode
parseCompilerLogOutput uses os.EOL, causing stale diagnostics on Windows and doesn't handle the new "Error in <project>:" header
Nobody has claimed this yet.
- Dominant language
- ReScript
- Stars
- 354
- Forks
- 63
- Avg merge
- 11h 29m
- Merged PRs (30d)
- 1
Description
Summary
I found two related issues in the compiler log parser while debugging another Windows issue in the language server.
The primary issue is that parseCompilerLogOutput() splits the compiler log using os.EOL.
On Windows, the ReScript compiler writes .compiler.log using LF (\n) line endings, while os.EOL is \r\n. As a result, the parser treats the entire file as a single line.
This was likely difficult to notice because the parser behaves correctly on Unix-like systems. The compiler emits LF (\n) line endings on every platform, which matches os.EOL on Linux and macOS. The mismatch only occurs on Windows, where os.EOL is \r\n.
This prevents it from detecting #Done(...) after successful builds, so previously reported compiler diagnostics are not cleared until another compilation produces updated diagnostics.
After fixing the line splitting locally, I also noticed another parser issue: the current compiler output contains lines such as
Error in <project>:
These lines are currently treated as parse errors even though the actual diagnostic immediately follows and is parsed correctly.
Environment
- OS: Windows 10 x64
- VS Code extension:
v1.73.11(Pre-release) - Language Server:
v1.72.0 - ReScript:
12.3.0 - Node:
24.18.0
Investigation
The problem is inside parseCompilerLogOutput().
Current code:
const lines = content.split(os.EOL);
I added logging of the raw compiler log.
When the project builds successfully, .compiler.log contains:
#Start(1784551270096)
#Done(1784551270250)
The file itself is correct. A ReScript maintainer previously stated that the compiler intentionally emits LF (\n) line endings on every platform, and this still appears to be the case in ReScript 12.3.0 based on my testing.
However, because it uses LF line endings, split(os.EOL) produces a single string on Windows instead of separate lines.
After replacing it with
const lines = content.split(/\r\n|\n|\r/);
(or equivalently split(/\r\n|[\n\r]/))
the parser correctly detects #Start(...) and #Done(...).
After this change:
- diagnostics are cleared correctly after successful builds;
- old diagnostics no longer remain visible;
- new diagnostics replace previous ones correctly.
Additional parser issue
After fixing the line splitting, another parser issue became visible.
Unlike the line-ending issue above, this issue appears to be platform-independent. I only noticed it after fixing the Windows-specific line splitting issue.
Current compiler output starts with:
Error in shopify-admin-extension:
Syntax error!
C:\...
The parser reports the header as a parse error because Error in <project>: is not handled anywhere in parseCompilerLogOutput().
As a result, the language server displays the warning:
There are more compiler warning/errors that we could not parse.
even though the actual diagnostic is parsed correctly. The only unrecognized line is the project header.
It seems sufficient to simply ignore it:
} else if (line.startsWith("Error in ")) {
// Project header emitted by the compiler.
}
The actual diagnostic immediately follows, so no information is lost.
Why os.EOL is not appropriate here
os.EOL describes the native newline sequence of the operating system.
It does not describe the line endings used by an arbitrary file.
This is also consistent with ReScript itself. In a discussion on the ReScript forum, a maintainer stated that the compiler intentionally emits LF (\n) line endings on every platform, including Windows:
"The ReScript printer currently always emits \n newlines."
The discussion is from 2021, but this behavior appears to be unchanged based on testing with ReScript 12.3.0, the VS Code extension 1.73.11 (pre-release), and the language server 1.72.0.
For parsing file contents, splitting on all standard newline sequences is generally recommended:
content.split(/\r\n|\n|\r/)
This correctly handles:
- Windows (CRLF)
- Unix/Linux/macOS (LF)
- legacy CR files
without depending on the platform where the parser is running or the line endings used by the file.
References:
- ReScript forum (compiler always emits LF): https://forum.rescript-lang.org/t/eol-characters-in-compiled-files-in-windows-vs-mac/2011
- Node.js
os.EOLdocumentation: https://nodejs.org/api/os.html#oseol - Discussion about cross-platform line splitting: https://stackoverflow.com/questions/21895233/how-to-split-string-with-newline-n-in-node
I verified locally that changing the line splitting fixes the stale diagnostics issue, and handling the Error in <project>: header removes the unnecessary "There are more compiler warning/errors that we could not parse." warning.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating parseCompilerLogOutput() and inspect how it splits compiler log content and handles unrecognized lines. Verify the parser with successful and diagnostic compiler logs on Windows-style and LF line endings. Done means successful builds clear stale diagnostics, new diagnostics replace old ones, and the Error in : header no longer produces an unnecessary parse warning.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, vscode
- Domain
- developer-experience, tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100