effekt-lang / effekt-lang/effekt

LSP code actions for pattern-matching

Open
#472 2 comments 2 reactions 0 assignees View on GitHub
area:lsp feature quality-of-life
Dominant language
Scala
Stars
469
Forks
41
Avg merge
1d 16h
Merged PRs (30d)
23

Description

Follow-up to #463 & #470
It would be nice to offer code actions for pattern-matching, specifically:

#### 1. a quick-fix for a missing case in a pattern match

After #470, the compiler suggests: `Non-exhaustive pattern matching, missing case Fork(Fork(_, _, Fork(_, _, _)), _, _))`, which really means that the user might want to add `case Fork(Fork(_, _, Fork(_, _, _)), _, _)) => <>`.

What we'd really want here is a quick-fix like in Scala 3: https://github.com/scala/scala3/blob/e0c030ccd44089e70629b59d76962c1dfc8dbb16/compiler/src/dotty/tools/dotc/reporting/messages.scala#L871-L891 which automatically inserts the missing case(s).

In order to do that, we need to pair a `Message` (a LSP `Diagnostic`) with a corresponding `TreeAction` (a LSP `CodeAction`). As far as I can tell, we would need to dynamically register CodeActions based on the Diagnostics we currently have, as it's the job of the "CodeActionContext" to store the relevant diagnostics. This would probably require some changes in Kiama.

I don't know whether we should also name the patterns (we definitely can, since we force the user to name the fields) or whether we should just leave ignore patterns (`_`) everywhere. 🤷‍♂️

#### 2. exhaustive autocompletion

Building up on **1.**, if we know the type of a variable, then we should also be able to get all of the constructors for that type.
It would be nice to _somehow_ -- either autocomplete on `x.match` like in IntelliJ, or perhaps by just right-clicking on an identifier -- be able to generate the whole exhaustive match.

```scala
x.match // [Autocomplete: Exhaustive pattern-matching]

// would get transformed to
x match {
case Cons(head, tail) => <>
case Nil() => <>
}
```

#### 3. case-of-case split on a pattern

Building up on **2.**, it would be absolutely amazing to be able to split by right-clicking on a variable _pattern_, similarly to Agda/Idris, creating a nested pattern match. This might be quite difficult to get right as it's a little bit more complicated to perform the editor changes (replace identifier, make a hole, copy whole line `k`-times, fill all holes with all `k` possible constructors).

```scala
x match {
case Cons(head, tail) => head
// ^^^^ right click here and select "case split"
case Nil() => 42
}

// would get transformed to
x match {
case Cons(head, Cons(head2, tail2)) => head // !
case Cons(head, Nil()) => head // !
case Nil() => 42
}

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.