Skip to content

Add the ability to track warnings through re-compilation#368

Open
jkeuhlen wants to merge 1 commit into
mainfrom
TrackWarnings
Open

Add the ability to track warnings through re-compilation#368
jkeuhlen wants to merge 1 commit into
mainfrom
TrackWarnings

Conversation

@jkeuhlen
Copy link
Copy Markdown

@jkeuhlen jkeuhlen commented Jul 14, 2025

  • Labeled the PR with patch, minor, or major to request a version bump when it's merged.
  • Updated the user manual in docs/.
  • Added integration / regression tests in tests/.

This PR adds support for a "Track warnings" feature which keeps track of warnings that might disappear due to GHC's recompilation processes:
image

GHC has a behavior that causes "ephemeral warnings" to disappear during development. When a file with warnings is recompiled due to dependency changes (without the file itself
changing), GHC only re-emits warnings for files that were directly modified. This means warnings from unchanged files vanish from the output, making it easy for developers to
lose track of warnings that still need to be addressed.

Example scenario:

  1. ModuleA.hs has an unused import warning
  2. ModuleB.hs (dependency) is modified
  3. GHC recompiles both modules but only shows warnings for ModuleB.hs
  4. The warning in ModuleA.hs disappears from output despite still being present

Solution

This PR introduces a --track-warnings flag that maintains an in-memory store of warnings per file. The system:

  • Captures warnings during compilation and stores them by file path
  • Persists warnings across dependency-driven recompilations when files haven't changed
  • Clears warnings when files are directly modified or removed
  • Prevents duplicates by filtering out warnings already shown in current compilation
  • Integrates with error logs so tracked warnings appear in editor-compatible output files

Usage

Enable warning tracking

ghciwatch --track-warnings

Or via environment variable

GHCIWATCH_TRACK_WARNINGS=1 ghciwatch

The feature is off by default to maintain backward compatibility. When enabled, developers get a complete view of all warnings across their codebase, eliminating the
frustrating experience of warnings disappearing during active development.

@github-actions github-actions Bot added the patch Bug fixes or non-functional changes label Jul 14, 2025
Comment thread src/cli.rs Outdated
Comment thread src/ghci/error_log.rs Outdated
Comment thread src/ghci/mod.rs Outdated
Comment thread src/ghci/mod.rs Outdated
Comment thread src/ghci/mod.rs
if warning_count > 0 {
tracing::info!(
"{} Finished {} in {:.2?} ({} warning{} tracked)",
"Compilation succeeded".if_supports_color(Stdout, |text| text.yellow()),
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One big design change here is that I purposefully picked a new phrase + color to signify "Compilation has finished successfully, but there are warnings present." Yellow + the succinct message here (distinct from the normal "All good!" is meant to signify that.

@jkeuhlen jkeuhlen marked this pull request as ready for review July 15, 2025 23:03
Comment thread src/ghci/warning_formatter.rs Outdated
Comment thread src/ghci/warning_formatter.rs Outdated
// Detect different types of lines and apply appropriate coloring

// Source code lines with line numbers (e.g., " 28 | import Data.Coerce (coerce)")
if let Some(pipe_pos) = line.find(" | ") {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kinda hacky, there should at least be a comment here. Ideally we'd integrate this into the parser but I understand that's a more invasive change.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah if there was a struct I could plug into with the various pieces of a GHC message, that would be really helpful. We could store original color information there as well.

I'd like to put that off for a follow up (and left one comment-based pointer for that at the top here). Do you think another comment here would suffice for now?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment here.

/// - Files that were directly changed: always update warnings (or clear if none)
/// - Files that were recompiled due to dependencies: only update if warnings exist
/// - Files that weren't recompiled: keep existing warnings
pub fn update_warnings_from_log(&mut self, log: &CompilationLog) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the only method that uses current_changed_files, would it make sense to make that variable a parameter to this function instead of a field on the struct?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could go either way? Do you feel strongly one way or the other?

My thinking here is that the struct keeps track of the things relevant for the feature: warnings and the files currently being changed (to determine which warnings are displayed). The latter could be thought of as an implementation detail but I wasn't sure if we'd want to surface the file list elsewhere externally too in the future.

Comment thread src/ghci/mod.rs Outdated
Comment thread src/ghci/mod.rs Outdated
Comment thread src/ghci/warning_formatter.rs Outdated
@jkeuhlen jkeuhlen requested a review from 9999years July 18, 2025 21:29
@9999years 9999years removed their request for review November 24, 2025 18:44
@9999years 9999years requested a review from a team as a code owner March 11, 2026 23:28
@9999years 9999years requested review from 9999years and lf- March 11, 2026 23:28
@lf- lf- removed their request for review March 12, 2026 19:16
// Detect different types of lines and apply appropriate coloring

// Source code lines with line numbers (e.g., " 28 | import Data.Coerce (coerce)")
// TODO: This is a pretty hacky way to find the lines to color. In the future, if we have all of this structured from the parser, we can store the original colors alongside the warning text and re-emit it directly.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we should emit this from the parser, we're parsing it anyways

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch Bug fixes or non-functional changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants