diff --git a/mtags/src/main/scala/scala/meta/internal/pc/CompletionProvider.scala b/mtags/src/main/scala/scala/meta/internal/pc/CompletionProvider.scala index 68e6ed9d096..ceb04179982 100644 --- a/mtags/src/main/scala/scala/meta/internal/pc/CompletionProvider.scala +++ b/mtags/src/main/scala/scala/meta/internal/pc/CompletionProvider.scala @@ -16,8 +16,7 @@ import org.eclipse.{lsp4j => l} class CompletionProvider( val compiler: MetalsGlobal, - params: OffsetParams, - clientSupportsSnippets: Boolean + params: OffsetParams ) { import compiler._ @@ -45,6 +44,8 @@ class CompletionProvider( ) val pos = unit.position(params.offset) val isSnippet = isSnippetEnabled(pos, params.text()) + val clientSupportsSnippets = + compiler.metalsConfig.isCompletionSnippetsEnabled() val (i, completion, editRange, query) = safeCompletionsAt(pos) val start = inferIdentStart(pos, params.text()) val end = inferIdentEnd(pos, params.text()) diff --git a/mtags/src/main/scala/scala/meta/internal/pc/Completions.scala b/mtags/src/main/scala/scala/meta/internal/pc/Completions.scala index 4cb5b6979bd..00853f1e57f 100644 --- a/mtags/src/main/scala/scala/meta/internal/pc/Completions.scala +++ b/mtags/src/main/scala/scala/meta/internal/pc/Completions.scala @@ -19,6 +19,9 @@ import scala.meta.internal.tokenizers.Chars */ trait Completions { this: MetalsGlobal => + val clientSupportsSnippets = + metalsConfig.isCompletionSnippetsEnabled() + /** * A member for symbols on the classpath that are not in scope, produced via workspace/symbol. */ @@ -765,11 +768,11 @@ trait Completions { this: MetalsGlobal => if (text.charAt(lit.pos.start - 1) != 's') List(new l.TextEdit(lit.pos.withEnd(lit.pos.start).toLSP, "s")) else Nil - val dolarEdits = for { + val dollarEdits = for { i <- lit.pos.start to (lit.pos.end - CURSOR.length()) if text.charAt(i) == '$' && i != interpolator.dollar } yield new l.TextEdit(pos.source.position(i).withEnd(i).toLSP, "$") - interpolatorEdit ++ dolarEdits + interpolatorEdit ++ dollarEdits } def newText(sym: Symbol): String = { @@ -793,6 +796,7 @@ trait Completions { this: MetalsGlobal => val filter: String = text.substring(lit.pos.start, pos.point - interpolator.name.length) + override def contribute: List[Member] = { metalsScopeMembers(pos).collect { case s: ScopeMember @@ -985,7 +989,7 @@ trait Completions { this: MetalsGlobal => allParams.exists(param => param.name.startsWith(prefix)) val isExplicitlyCalled = suffix.startsWith(prefix) val hasParamsToFill = allParams.count(!_.hasDefault) > 1 - if ((shouldShow || isExplicitlyCalled) && hasParamsToFill) { + if ((shouldShow || isExplicitlyCalled) && hasParamsToFill && clientSupportsSnippets) { val editText = allParams.zipWithIndex .collect { case (param, index) if !param.hasDefault => @@ -1202,7 +1206,11 @@ trait Completions { this: MetalsGlobal => private def signature = printer.defaultMethodSignature() private def edit = new l.TextEdit( range, - s"$filterText$signature = $${0:???}" + if (clientSupportsSnippets) { + s"$filterText$signature = $${0:???}" + } else { + s"$filterText$signature = ???" + } ) } @@ -1259,7 +1267,11 @@ trait Completions { this: MetalsGlobal => "match", new l.TextEdit( editRange, - "match {\n\tcase$0\n}" + if (clientSupportsSnippets) { + "match {\n\tcase$0\n}" + } else { + "match" + } ), completionsSymbol("match"), label = Some("match"), @@ -1273,7 +1285,11 @@ trait Completions { this: MetalsGlobal => tail .map(_.edit.getNewText()) .mkString( - s"match {\n\t${head.edit.getNewText} $$0\n\t", + if (clientSupportsSnippets) { + "match {\n\t${head.edit.getNewText} $$0\n\t" + } else { + "match {\n\t${head.edit.getNewText}\n\t" + }, "\n\t", "\n}" ) @@ -1408,7 +1424,10 @@ trait Completions { this: MetalsGlobal => if (definitions.isTupleType(parents.selector)) { result += new TextEditMember( "case () =>", - new l.TextEdit(editRange, "case ($0) =>"), + new l.TextEdit( + editRange, + if (clientSupportsSnippets) "case ($0) =>" else "case () =>" + ), parents.selector.typeSymbol, label = Some(s"case ${parents.selector} =>"), command = metalsConfig.parameterHintsCommand().asScala @@ -1466,8 +1485,10 @@ trait Completions { this: MetalsGlobal => val label = s"case $pattern =>" new TextEditMember( filterText = label, - edit = - new l.TextEdit(editRange, label + (if (isSnippet) " $0" else "")), + edit = new l.TextEdit( + editRange, + label + (if (isSnippet && clientSupportsSnippets) " $0" else "") + ), sym = sym, label = Some(label), additionalTextEdits = autoImports @@ -1482,7 +1503,8 @@ trait Completions { this: MetalsGlobal => s"case _: $name", new l.TextEdit( editRange, - if (isSnippet) s"case $${0:_}: $name$suffix => " + if (isSnippet && clientSupportsSnippets) + s"case $${0:_}: $name$suffix => " else s"case _: $name$suffix =>" ), sym, diff --git a/mtags/src/main/scala/scala/meta/internal/pc/MetalsGlobal.scala b/mtags/src/main/scala/scala/meta/internal/pc/MetalsGlobal.scala index 9892b8de8fe..712b30d1772 100644 --- a/mtags/src/main/scala/scala/meta/internal/pc/MetalsGlobal.scala +++ b/mtags/src/main/scala/scala/meta/internal/pc/MetalsGlobal.scala @@ -573,11 +573,11 @@ class MetalsGlobal( def snippetCursor: String = sym.paramss match { case Nil => - "$0" + if (clientSupportsSnippets) "$0" else "" case Nil :: Nil => - "()$0" + if (clientSupportsSnippets) "()$0" else "()" case _ => - "($0)" + if (clientSupportsSnippets) "($0)" else "" } def isDefined: Boolean = diff --git a/mtags/src/main/scala/scala/meta/internal/pc/ScalaPresentationCompiler.scala b/mtags/src/main/scala/scala/meta/internal/pc/ScalaPresentationCompiler.scala index a5d356874ed..fd2f1653c04 100644 --- a/mtags/src/main/scala/scala/meta/internal/pc/ScalaPresentationCompiler.scala +++ b/mtags/src/main/scala/scala/meta/internal/pc/ScalaPresentationCompiler.scala @@ -85,8 +85,7 @@ case class ScalaPresentationCompiler( params: OffsetParams ): CompletableFuture[CompletionList] = access.withInterruptableCompiler(emptyCompletion, params.token) { global => - new CompletionProvider(global, params, config.isCompletionSnippetsEnabled) - .completions() + new CompletionProvider(global, params).completions() } // NOTE(olafur): hover and signature help use a "shared" compiler instance because