From 4b38ed02f8172c04ad57387856235eaf9f67797f Mon Sep 17 00:00:00 2001 From: Jakub Ciesluk <323892@uwr.edu.pl> Date: Fri, 16 Jun 2023 10:37:30 +0200 Subject: [PATCH] improvement: Add `case` keyword completion --- .../pc/completions/MatchCaseCompletions.scala | 21 +++++++++++- .../pc/completions/MatchCaseCompletions.scala | 32 +++++++++++++++---- .../scala/tests/pc/CompletionCaseSuite.scala | 18 +++++++++-- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/mtags/src/main/scala-2/scala/meta/internal/pc/completions/MatchCaseCompletions.scala b/mtags/src/main/scala-2/scala/meta/internal/pc/completions/MatchCaseCompletions.scala index 29705fc9f5b..eb24f0adcc1 100644 --- a/mtags/src/main/scala-2/scala/meta/internal/pc/completions/MatchCaseCompletions.scala +++ b/mtags/src/main/scala-2/scala/meta/internal/pc/completions/MatchCaseCompletions.scala @@ -181,7 +181,10 @@ trait MatchCaseCompletions { this: MetalsGlobal => } } val members = result.result() - val edits = members.map(_._2) + val edits = { + if (members.isEmpty) completionGenerator.caseKeywordOnly + else members.map(_._2) + } // In `List(foo).map { cas@@} we want to provide also `case (exhaustive)` completion // which works like exhaustive match, so we need to collect only members from this step includeExhaustive match { @@ -462,6 +465,22 @@ trait MatchCaseCompletions { this: MetalsGlobal => ) } + def caseKeywordOnly: List[TextEditMember] = + if (patternOnly.isEmpty) { + val label = "case" + val suffix = + if (clientSupportsSnippets) " $0 =>" + else " " + List( + new TextEditMember( + label, + new l.TextEdit(editRange, label + suffix), + NoSymbol.newErrorSymbol(TermName("case")).setInfo(NoType), + label = Some(label) + ) + ) + } else Nil + private def tryInfixPattern(sym: Symbol): Option[String] = { sym.primaryConstructor.paramss match { case (a :: b :: Nil) :: Nil => diff --git a/mtags/src/main/scala-3/scala/meta/internal/pc/completions/MatchCaseCompletions.scala b/mtags/src/main/scala-3/scala/meta/internal/pc/completions/MatchCaseCompletions.scala index d3542b72fc5..c646d4a457b 100644 --- a/mtags/src/main/scala-3/scala/meta/internal/pc/completions/MatchCaseCompletions.scala +++ b/mtags/src/main/scala-3/scala/meta/internal/pc/completions/MatchCaseCompletions.scala @@ -165,13 +165,17 @@ object CaseKeywordCompletion: (si, label) } } - val caseItems = res.map((si, label) => - completionGenerator.toCompletionValue( - si.sym, - label, - autoImportsGen.renderImports(si.importSel.toList), - ) - ) + val caseItems = + if res.isEmpty then completionGenerator.caseKeywordOnly + else + res.map((si, label) => + completionGenerator.toCompletionValue( + si.sym, + label, + autoImportsGen.renderImports(si.importSel.toList), + ) + ) + includeExhaustive match // In `List(foo).map { cas@@} we want to provide also `case (exhaustive)` completion // which works like exhaustive match. @@ -446,6 +450,20 @@ class CompletionValueGenerator( end if end labelForCaseMember + def caseKeywordOnly: List[CompletionValue.Keyword] = + if patternOnly.isEmpty then + val label = "case" + val suffix = + if clientSupportsSnippets then " $0 =>" + else " " + List( + CompletionValue.Keyword( + label, + Some(label + suffix), + ) + ) + else Nil + def toCompletionValue( sym: Symbol, label: String, diff --git a/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala index 74f7719c571..c069ea76aac 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala @@ -581,7 +581,7 @@ class CompletionCaseSuite extends BaseCompletionSuite { ) check( - "private-member".tag(IgnoreScala2), + "private-member".tag(IgnoreScala2.and(IgnoreForScala3CompilerPC)), """ |package example |import scala.collection.immutable.Vector @@ -591,7 +591,8 @@ class CompletionCaseSuite extends BaseCompletionSuite { | ca@@ | } |}""".stripMargin, - "" + """|case + |""".stripMargin ) check( @@ -779,4 +780,17 @@ class CompletionCaseSuite extends BaseCompletionSuite { "case (Int, Int) => scala" ) + check( + "keyword-only".tag(IgnoreForScala3CompilerPC), + """ + |sealed trait Alpha + |object A { + | List.empty[Alpha].groupBy{ + | ca@@ + | } + |}""".stripMargin, + """|case + |""".stripMargin + ) + }