diff --git a/mtags/src/main/scala-2/scala/meta/internal/pc/CompletionProvider.scala b/mtags/src/main/scala-2/scala/meta/internal/pc/CompletionProvider.scala index 8c7c2fbfd2d..79d6cca8cc0 100644 --- a/mtags/src/main/scala-2/scala/meta/internal/pc/CompletionProvider.scala +++ b/mtags/src/main/scala-2/scala/meta/internal/pc/CompletionProvider.scala @@ -362,19 +362,20 @@ class CompletionProvider( val isIgnored = mutable.Set.empty[Symbol] val buf = List.newBuilder[Member] def visit(head: Member): Boolean = { - val id = - if (head.sym.isClass || head.sym.isModule) { - head.sym.fullName - } else { - head match { - case o: OverrideDefMember => - o.label - case named: NamedArgMember => - s"named-${semanticdbSymbol(named.sym)}" - case _ => - semanticdbSymbol(head.sym) + val id = head match { + case o: OverrideDefMember => + o.label + case named: NamedArgMember => + s"named-${semanticdbSymbol(named.sym)}" + case pattern: CasePatternMember => + s"case-pattern-${semanticdbSymbol(pattern.sym)}" + case _ => + if (head.sym.isClass || head.sym.isModule) { + head.sym.fullName + } else { + semanticdbSymbol(head.sym) } - } + } def isIgnoredWorkspace: Boolean = head.isInstanceOf[WorkspaceMember] && diff --git a/mtags/src/main/scala-2/scala/meta/internal/pc/MetalsGlobal.scala b/mtags/src/main/scala-2/scala/meta/internal/pc/MetalsGlobal.scala index 016e688fbd9..e926076743c 100644 --- a/mtags/src/main/scala-2/scala/meta/internal/pc/MetalsGlobal.scala +++ b/mtags/src/main/scala-2/scala/meta/internal/pc/MetalsGlobal.scala @@ -598,10 +598,12 @@ class MetalsGlobal( case Descriptor.None => Nil case Descriptor.Type(value) => - val member = owner.info.decl(TypeName(value).encode) :: Nil - if (sym.isJava) - owner.info.decl(TermName(value).encode) :: member - else member + val members = + if (sym.isJava) + owner.info.decl(TermName(value).encode) :: Nil + else Nil + // Put the type ahead of the Java-induced term for `inverseSemanticdbSymbol` + owner.info.decl(TypeName(value).encode) :: members case Descriptor.Term(value) => owner.info.decl(TermName(value).encode) :: Nil case Descriptor.Package(value) => diff --git a/mtags/src/main/scala-2/scala/meta/internal/pc/completions/Completions.scala b/mtags/src/main/scala-2/scala/meta/internal/pc/completions/Completions.scala index e876a8fe6a0..67f8618bd9e 100644 --- a/mtags/src/main/scala-2/scala/meta/internal/pc/completions/Completions.scala +++ b/mtags/src/main/scala-2/scala/meta/internal/pc/completions/Completions.scala @@ -78,6 +78,25 @@ trait Completions { this: MetalsGlobal => val commitCharacter: Option[String] = None ) extends ScopeMember(sym, NoType, true, EmptyTree) + class CasePatternMember( + override val filterText: String, + override val edit: l.TextEdit, + sym: Symbol, + override val label: Option[String] = None, + override val detail: Option[String] = None, + override val command: Option[String] = None, + override val additionalTextEdits: List[l.TextEdit] = Nil + ) extends TextEditMember( + filterText, + edit, + sym, + label, + detail, + command, + additionalTextEdits, + None + ) + val packageSymbols: mutable.Map[String, Option[Symbol]] = mutable.Map.empty[String, Option[Symbol]] def packageSymbolFromString(symbol: String): Option[Symbol] = 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 8f06d24841c..40e47b2becf 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 @@ -75,7 +75,7 @@ trait MatchCaseCompletions { this: MetalsGlobal => } override def isPrioritized(member: Member): Boolean = member match { - case m: TextEditMember => !m.filterText.contains("(exhaustive)") + case m: CasePatternMember => !m.filterText.contains("(exhaustive)") case _ => false } @@ -88,7 +88,7 @@ trait MatchCaseCompletions { this: MetalsGlobal => if (definitions.isTupleType(parents.selector)) { if (patternOnly.isEmpty) List( - new TextEditMember( + new CasePatternMember( "case () =>", new l.TextEdit( editRange, @@ -221,7 +221,7 @@ trait MatchCaseCompletions { this: MetalsGlobal => val detail = s" ${metalsToLongString(selectorSym.tpe, new ShortenedNames())} (${sealedMembers.length} cases)" - val exhaustive = new TextEditMember( + val exhaustive = new CasePatternMember( "case (exhaustive)", newText, selectorSym, @@ -306,7 +306,7 @@ trait MatchCaseCompletions { this: MetalsGlobal => val sortedSubclasses = sortSubclasses(subclassesResult, tpe, source) val members = sortedSubclasses.map(_._2) - val basicMatch = new TextEditMember( + val basicMatch = new CasePatternMember( "match", new l.TextEdit( editRange, @@ -339,7 +339,7 @@ trait MatchCaseCompletions { this: MetalsGlobal => ) val detail = s" ${metalsToLongString(tpe, new ShortenedNames())} (${members.length} cases)" - val exhaustiveMatch = new TextEditMember( + val exhaustiveMatch = new CasePatternMember( "match (exhaustive)", newText, tpe.typeSymbol, @@ -454,26 +454,38 @@ trait MatchCaseCompletions { this: MetalsGlobal => else pattern val cursorSuffix = (if (patternOnly.nonEmpty) "" else " ") + (if (clientSupportsSnippets) "$0" else "") - new TextEditMember( - filterText = label, - edit = new l.TextEdit( - editRange, - label + cursorSuffix - ), - sym = sym, - label = Some(label), - additionalTextEdits = autoImports + + val edit = new l.TextEdit( + editRange, + label + cursorSuffix ) + if (patternOnly.nonEmpty && name == pattern) { + new TextEditMember( + filterText = label, + edit = edit, + sym = sym, + label = Some(label), + additionalTextEdits = autoImports + ) + } else { + new CasePatternMember( + filterText = label, + edit = edit, + sym = sym, + label = Some(label), + additionalTextEdits = autoImports + ) + } } - def caseKeywordOnly: List[TextEditMember] = + def caseKeywordOnly: List[CasePatternMember] = if (patternOnly.isEmpty) { val label = "case" val suffix = if (clientSupportsSnippets) " $0 =>" else " " List( - new TextEditMember( + new CasePatternMember( label, new l.TextEdit(editRange, label + suffix), NoSymbol.newErrorSymbol(TermName("case")).setInfo(NoType), diff --git a/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala index 994352a9ab2..1837650976b 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionCaseSuite.scala @@ -910,4 +910,24 @@ class CompletionCaseSuite extends BaseCompletionSuite { |}""".stripMargin ) + check( + "underscore-and-object", + """package myPackage1 { + | class MyClass + | object MyClass { + | val TheValue = new MyClass + | } + |} + |object Test { + | val x = myPackage1.MyClass.TheValue + | x match { + | case My@@ + | } + |} + |""".stripMargin, + """_: MyClass myPackage1 + |MyClass - myPackage1 + |""".stripMargin + ) + } diff --git a/tests/cross/src/test/scala/tests/pc/CompletionPatternSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionPatternSuite.scala index 41bb6b6845a..f7dfb2d3d0c 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionPatternSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionPatternSuite.scala @@ -85,8 +85,8 @@ class CompletionPatternSuite extends BaseCompletionSuite { | case abc @ @@ => | } |}""".stripMargin, - """|None scala - |Some(value) scala + """|Some(value) scala + |None scala |""".stripMargin, topLines = Some(2) ) @@ -111,7 +111,7 @@ class CompletionPatternSuite extends BaseCompletionSuite { | case _: @@ => | } |}""".stripMargin, - """|None scala + """|Some[_] scala |""".stripMargin, compat = Map( "3" -> @@ -141,7 +141,7 @@ class CompletionPatternSuite extends BaseCompletionSuite { | case ab: @@ => | } |}""".stripMargin, - """|None scala + """|Some[_] scala |""".stripMargin, compat = Map( "3" -> diff --git a/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala index 58e7f20151b..964c2e5c2dd 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala @@ -1028,9 +1028,13 @@ class CompletionSuite extends BaseCompletionSuite { |} |""".stripMargin, """|Some(value) scala + |Some scala |""".stripMargin, compat = Map( - "2.11" -> "Some(x) scala", + "2.11" -> + """|Some(x) scala + |Some scala + |""".stripMargin, "3" -> """|Some(value) scala |Some scala @@ -1060,11 +1064,11 @@ class CompletionSuite extends BaseCompletionSuite { "adt", s"""|object Main { | Option(1) match { - | case No@@ + | case Non@@ |} |""".stripMargin, """|None scala - |NoManifest scala.reflect + |NonFatal - scala.util.control |""".stripMargin, topLines = Some(2) )