From 61c0ba971be1421d1856bc5bfa9a6fb2d3ebd861 Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Thu, 5 Oct 2023 09:41:12 +0200 Subject: [PATCH 1/2] bugfix: match completions for type aliases scala 3 --- .../pc/completions/MatchCaseCompletions.scala | 7 ++- .../scala/tests/pc/CompletionMatchSuite.scala | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) 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 0d701c94cc2..e256a137618 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 @@ -39,7 +39,6 @@ object CaseKeywordCompletion: * @param selector `selector` of `selector match { cases }` or `EmptyTree` when * not in a match expression (for example `List(1).foreach { case@@ }`. * @param completionPos the position of the completion - * @param typedtree typed tree of the file, used for generating auto imports * @param indexedContext * @param config * @param parent the parent tree node of the pattern match, for example `Apply(_, _)` when in @@ -88,7 +87,7 @@ object CaseKeywordCompletion: new Parents(NoType, definitions) case sel => new Parents(sel.tpe, definitions) - val selectorSym = parents.selector.typeSymbol + val selectorSym = parents.selector.metalsDealias.typeSymbol // Special handle case when selector is a tuple or `FunctionN`. if definitions.isTupleClass(selectorSym) || definitions.isFunctionClass( @@ -240,8 +239,8 @@ object CaseKeywordCompletion: clientSupportsSnippets, ) val tpe = selector.tpe.widen.bounds.hi match - case tr @ TypeRef(_, _) => tr.underlying - case t => t + case tr @ TypeRef(_, _) => tr.underlying.metalsDealias + case t => t.metalsDealias val sortedSubclasses = val subclasses = diff --git a/tests/cross/src/test/scala/tests/pc/CompletionMatchSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionMatchSuite.scala index be1e3ad46de..b9f0c18400b 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionMatchSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionMatchSuite.scala @@ -757,4 +757,52 @@ class CompletionMatchSuite extends BaseCompletionSuite { |""".stripMargin, ) + checkEdit( + "type-alias".tag(IgnoreScala2), + s"""|object O { + | type Id[A] = A + | + | enum Animal: + | case Cat, Dog + | + | val animal: Id[Animal] = ??? + | + | animal ma@@ + |} + |""".stripMargin, + s"""object O { + | type Id[A] = A + | + | enum Animal: + | case Cat, Dog + | + | val animal: Id[Animal] = ??? + | + | animal match + |\tcase Animal.Cat => $$0 + |\tcase Animal.Dog => + | + |} + |""".stripMargin, + filter = _.contains("exhaustive"), + ) + + check( + "type-alias2".tag(IgnoreScala2), + s"""|object O { + | type Id[A] = A + | + | enum Animal: + | case Cat, Dog + | + | val animal: Id[Animal] = ??? + | + | animal match { + | \tcase Animal.C@@ + | } + |} + |""".stripMargin, + "Cat: Animal", + ) + } From a51392d9cdcb1fbb03c2b3484b684e966200c8f8 Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Fri, 6 Oct 2023 16:49:59 +0200 Subject: [PATCH 2/2] add tests and fix `case` case --- .../pc/completions/MatchCaseCompletions.scala | 12 ++-- .../scala/tests/pc/CompletionCaseSuite.scala | 47 +++++++++++++++ .../scala/tests/pc/CompletionMatchSuite.scala | 60 ++++++++++++++++--- 3 files changed, 106 insertions(+), 13 deletions(-) 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 e256a137618..1b349b57f09 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 @@ -87,7 +87,7 @@ object CaseKeywordCompletion: new Parents(NoType, definitions) case sel => new Parents(sel.tpe, definitions) - val selectorSym = parents.selector.metalsDealias.typeSymbol + val selectorSym = parents.selector.widen.metalsDealias.typeSymbol // Special handle case when selector is a tuple or `FunctionN`. if definitions.isTupleClass(selectorSym) || definitions.isFunctionClass( @@ -150,7 +150,9 @@ object CaseKeywordCompletion: if isValid(ts) then visit(autoImportsGen.inferSymbolImport(ts)) ) // Step 2: walk through known subclasses of sealed types. - val sealedDescs = subclassesForType(parents.selector.widen.bounds.hi) + val sealedDescs = subclassesForType( + parents.selector.widen.metalsDealias.bounds.hi + ) sealedDescs.foreach { sym => val symbolImport = autoImportsGen.inferSymbolImport(sym) visit(symbolImport) @@ -238,9 +240,9 @@ object CaseKeywordCompletion: completionPos, clientSupportsSnippets, ) - val tpe = selector.tpe.widen.bounds.hi match - case tr @ TypeRef(_, _) => tr.underlying.metalsDealias - case t => t.metalsDealias + val tpe = selector.tpe.widen.metalsDealias.bounds.hi match + case tr @ TypeRef(_, _) => tr.underlying + case t => t val sortedSubclasses = val subclasses = diff --git a/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala index be33b8027ea..43c32b3cab0 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala @@ -693,4 +693,51 @@ class CompletionCaseSuite extends BaseCompletionSuite { |case Sports(time, intensity) => exhaustive-enum-tags3.Activity""".stripMargin, ) + check( + "type-alias-case".tag(IgnoreScala2), + s"""|object O: + | type Id[A] = A + | + | enum Animal: + | case Cat, Dog + | + | val animal: Id[Animal] = ??? + | + | animal match + | cas@@ + |""".stripMargin, + """|case Animal.Cat => + |case Animal.Dog => + |""".stripMargin, + ) + + check( + "type-alias-sealed-trait-case", + s"""|object O { + | type Id[A] = A + | + |sealed trait Animal + |object Animal { + | case class Cat() extends Animal + | case object Dog extends Animal + |} + | + | val animal: Id[Animal] = ??? + | + | animal match { + | cas@@ + | } + |} + |""".stripMargin, + """|case Cat() => `type-alias-sealed-trait-case`.O.Animal + |case Dog => `type-alias-sealed-trait-case`.O.Animal + |""".stripMargin, + compat = Map( + "3" -> + """|case Cat() => type-alias-sealed-trait-case.O.Animal + |case Dog => type-alias-sealed-trait-case.O.Animal + |""".stripMargin + ), + ) + } diff --git a/tests/cross/src/test/scala/tests/pc/CompletionMatchSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionMatchSuite.scala index b9f0c18400b..229595d8929 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionMatchSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionMatchSuite.scala @@ -787,22 +787,66 @@ class CompletionMatchSuite extends BaseCompletionSuite { filter = _.contains("exhaustive"), ) - check( - "type-alias2".tag(IgnoreScala2), + checkEdit( + "type-alias-sealed-trait", s"""|object O { | type Id[A] = A | - | enum Animal: - | case Cat, Dog + |sealed trait Animal + |object Animal { + | case object Cat extends Animal + | case object Dog extends Animal + |} | | val animal: Id[Animal] = ??? | - | animal match { - | \tcase Animal.C@@ - | } + |animal ma@@ |} |""".stripMargin, - "Cat: Animal", + s""" + |import O.Animal.Cat + |import O.Animal.Dog + |object O { + | type Id[A] = A + | + |sealed trait Animal + |object Animal { + | case object Cat extends Animal + | case object Dog extends Animal + |} + | + | val animal: Id[Animal] = ??? + | + |animal match { + |\tcase Cat => $$0 + |\tcase Dog => + |} + |} + |""".stripMargin, + compat = Map( + "3" -> + s""" + |import O.Animal.Cat + |import O.Animal.Dog + |object O { + | type Id[A] = A + | + |sealed trait Animal + |object Animal { + | case object Cat extends Animal + | case object Dog extends Animal + |} + | + | val animal: Id[Animal] = ??? + | + |animal match + |\tcase Cat => $$0 + |\tcase Dog => + | + |} + |""".stripMargin + ), + filter = _.contains("exhaustive"), ) }