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
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:
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.
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 usingos.EOL.On Windows, the ReScript compiler writes
.compiler.logusing LF (\n) line endings, whileos.EOLis\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 matchesos.EOLon Linux and macOS. The mismatch only occurs on Windows, whereos.EOLis\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
These lines are currently treated as parse errors even though the actual diagnostic immediately follows and is parsed correctly.
Environment
v1.73.11(Pre-release)v1.72.012.3.024.18.0Investigation
The problem is inside
parseCompilerLogOutput().Current code:
I added logging of the raw compiler log.
When the project builds successfully,
.compiler.logcontains: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
(or equivalently
split(/\r\n|[\n\r]/))the parser correctly detects
#Start(...)and#Done(...).After this change:
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:
The parser reports the header as a parse error because
Error in <project>:is not handled anywhere inparseCompilerLogOutput().As a result, the language server displays the warning:
even though the actual diagnostic is parsed correctly. The only unrecognized line is the project header.
It seems sufficient to simply ignore it:
The actual diagnostic immediately follows, so no information is lost.
Why
os.EOLis not appropriate hereos.EOLdescribes 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 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:
This correctly handles:
without depending on the platform where the parser is running or the line endings used by the file.
References:
os.EOLdocumentation: https://nodejs.org/api/os.html#oseolI 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.