Skip to content

Case split plugin - #5014

Draft
Aster89 wants to merge 1 commit into
haskell:masterfrom
Aster89:master
Draft

Case split plugin#5014
Aster89 wants to merge 1 commit into
haskell:masterfrom
Aster89:master

Conversation

@Aster89

@Aster89 Aster89 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

This PR is for introducing the so called case-split plugin, as requested in #5013.

(In the following, me is myself and we is myself, @fendor, @MangoIV, and @AndreasPK.)

The change as of now needs lots of refinements (obviously beside getting rid of all the trace* calls I've peppered the code with, and beside squashing all commits together), especially these:

  • currently, it's not clear to me how to affect the maximum number of patterns that are inserted by the plugin without also affecting the maximum number of uncovered patterns in the diagnostic error message;
    • ideally the two numbers should be independent, i.e., the diagnostic error message would still show maxUncoveredPatterns uncovered patterns, but the plugin would nonetheless insert _all_¹ uncovered patterns;
    • we agreed a good first strategy is to have the plugin honor maxUncoveredPatterns, because it's the least invasive approach, it doesn't require any additional code, one can only improve from there, and nothing prevents the user from triggering the plugin more than once to uncover more and more patterns (as noticed by Andreas, this could actually be the gist of some solution to the whole problem, i.e. trigger the plugin repeatedly until no uncovered pattern remains);
  • as shown by several tests (e.g. T16.hs), the indentation of the patterns inserted by the plugins is sometimes too much, although correct,
    • and this is because I haven't fully grasped how deltaPos and related abstractions work; need to chat with @alanz about this;
  • a few tests are not passing, testifying some decisions I haven't taken yet/use cases I haven't really a clear idea about:
    • I would assume the plugin should work for \case just as it does for case (see T12.hs), but maybe this is as much a generalization as having the plugin work with function definitions, so I guess we can drop this test, or maybe assume it as failing and link a new enhancement request to it?
    • The plugin works even if the expression being scrutinized is _, but the test doesn't pass (see T18.hs); I still don't know why;
    • how should the plugin behave when the type is not known, e.g. see T19.hs? I think it should just not offer any action.
    • when two case expressions, both incomplete, are nested (e.g. T14.hs), the plugin should offer an action for each incomplete case trigger for the innermost case expression which the cursor is on;
  • the arrow should be -> or its unicode counterpart, honoring the -XUnicodeSyntax flag or previous patterns.

¹ Not really all, we don't want to split an all Ints, for instance, nor on an actual data with 100 ctors, presumably. Or do we?

@dschrempf

Copy link
Copy Markdown
Collaborator

Everybody is eagerly anticipating this change, thank you!

Given the many WIP commits, I just wanted to ask if you could sqaush or reword them. I guess you had this in mind anyways.

@Aster89

Aster89 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Everybody is eagerly anticipating this change, thank you!

Glad to hear that!

Given the many WIP commits, I just wanted to ask if you could sqaush or reword them. I guess you had this in mind anyways.

Yep, see 3rd paragraph at the top :P

@dschrempf

Copy link
Copy Markdown
Collaborator

Ah, the second sub-clause :-P my attention had already shifted before that one, I apologize :-)! Thanks!

@fendor fendor changed the title Case split plugin - Fixes #5013 Case split plugin Jul 14, 2026
@fendor
fendor marked this pull request as draft July 20, 2026 09:21
Comment thread ghcide/src/Development/IDE/Core/Compile.hs

@MangoIV MangoIV left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

First pass. I think after you clean up the main logic a bit more and add some documentation there, I can take another look. :)

Very good work, looking forward to having this in HLS!

Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated

@MangoIV MangoIV left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

another small round :)

Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs
pure (old, new)

where
go :: forall d m. (MonadState Bool m, MonadReader Bool m, Data d) => d -> m d

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can use for instance ExceptT for now. Is it clear why that's better?
And if you want to, you can try

newtype ExceptCT e m a 
  = MkExceptC {unExceptCT :: forall b. (e -> m b) -> (a -> m b) -> m b} 

and see if that's faster. But that doesn't have to be done now.

Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
Comment thread plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs Outdated
@Aster89
Aster89 force-pushed the master branch 2 times, most recently from e8152da to 9d9f1ff Compare August 1, 2026 17:38
@Aster89
Aster89 force-pushed the master branch 2 times, most recently from 11c2716 to 5ea6895 Compare August 4, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants