Skip to content

parseCompilerLogOutput uses os.EOL, causing stale diagnostics on Windows and doesn't handle the new "Error in <project>:" header #1185

Description

@davkats

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:


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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions