Skip to content

Commit

Permalink
improvement: Make including detail in completion label configurable
Browse files Browse the repository at this point in the history
Some LSP clients (such as Emacs using Eglot and Corfu) use the label field to insert a completion if
completionItem/resolve has not returned by the time the completion is selected. Including the contents of the detail
property in the label causes it to be included in the file itself in these clients. To remedy this, we define a
isDetailIncludedInLabel option under compilerOptions to make this behaviour toggleable. We also disable this behaviour
by default in Emacs, since this is where the undesirable behaviour was located.

Fixes #6849.
  • Loading branch information
Sorixelle committed Dec 2, 2024
1 parent 1e0d88e commit f0ccc7b
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ object InitializationOptions {
isSignatureHelpDocumentationEnabled = compilerObj.flatMap(
_.getBooleanOption("isSignatureHelpDocumentationEnabled")
),
isDetailIncludedInLabel = compilerObj.flatMap(
_.getBooleanOption("isDetailIncludedInLabel")
),
overrideDefFormat = compilerObj.flatMap(
_.getStringOption("overrideDefFormat")
),
Expand All @@ -210,7 +213,6 @@ object InitializationOptions {
compilerObj.flatMap(_.getBooleanOption("snippetAutoIndent")),
)
}

}

sealed trait CommandHTMLFormat {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ object MetalsServerConfig {
base.copy(
executeClientCommand = ExecuteClientCommandConfig.on,
compilers = base.compilers.copy(
snippetAutoIndent = false
snippetAutoIndent = false,
isDetailIncludedInLabel = false,
),
)
case _ =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ enum OverrideDefFormat {
*/
boolean isCompletionSnippetsEnabled();

/**
* Returns true if the completion's description should be included in the label.
*/
default boolean isDetailIncludedInLabel() {
return true;
}

/**
* The maximum delay for requests to respond.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package scala.meta.internal.pc
* @param isHoverDocumentationEnabled whether to include docstrings in a `textDocument/hover`.
* @param isSignatureHelpDocumentationEnabled whether the `SignatureHelp.documentation` field
* should be populated.
* @param isDetailIncludedInLabel whether the completion's description should be included in the
* label.
* @param overrideDefFormat whether the override should include a unicode icon or only ascii.
* @param parameterHintsCommand command identifier to trigger parameter hints.
* @param snippetAutoIndent whether the client defaults to adding the indentation of the reference
Expand All @@ -28,6 +30,7 @@ case class CompilerInitializationOptions(
isCompletionItemResolve: Option[Boolean],
isHoverDocumentationEnabled: Option[Boolean],
isSignatureHelpDocumentationEnabled: Option[Boolean],
isDetailIncludedInLabel: Option[Boolean],
overrideDefFormat: Option[String],
parameterHintsCommand: Option[String],
snippetAutoIndent: Option[Boolean]
Expand All @@ -44,6 +47,7 @@ object CompilerInitializationOptions {
None,
None,
None,
None,
None
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ case class PresentationCompilerConfigImpl(
snippetAutoIndent: Boolean = true,
isSignatureHelpDocumentationEnabled: Boolean = true,
isCompletionSnippetsEnabled: Boolean = true,
override val isDetailIncludedInLabel: Boolean = true,
isCompletionItemResolve: Boolean = true,
_isStripMarginOnTypeFormattingEnabled: () => Boolean = () => true,
timeoutDelay: Long = 20,
Expand Down Expand Up @@ -72,6 +73,9 @@ case class PresentationCompilerConfigImpl(
isCompletionItemResolve = options.isCompletionItemResolve.getOrElse(
this.isCompletionItemResolve
),
isDetailIncludedInLabel = options.isDetailIncludedInLabel.getOrElse(
this.isDetailIncludedInLabel
),
_parameterHintsCommand = options.parameterHintsCommand.orElse(
this._parameterHintsCommand
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ class CompletionProvider(
}

def labelWithSig =
if (member.sym.isMethod || member.sym.isValue) {
if (
compiler.metalsConfig.isDetailIncludedInLabel && (member.sym.isMethod || member.sym.isValue)
) {
ident + detail
} else {
ident
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,11 @@ class CompletionProvider(
// related issue https://github.com/lampepfl/dotty/issues/11941
lazy val kind: CompletionItemKind = completion.completionItemKind
val description = completion.description(printer)
val label = completion.labelWithDescription(printer)
val label =
if config.isDetailIncludedInLabel then
completion.labelWithDescription(printer)
else
completion.label
val ident = completion.insertText.getOrElse(completion.label)

def mkItem(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package tests.pc

import scala.meta.internal.pc.PresentationCompilerConfigImpl
import scala.meta.pc.PresentationCompilerConfig

import tests.BaseCompletionSuite

class CompletionWithoutDetailsSuite extends BaseCompletionSuite {

override def config: PresentationCompilerConfig =
PresentationCompilerConfigImpl().copy(
isDetailIncludedInLabel = false
)

check(
"scope",
"""
|object A {
| Lis@@
|}""".stripMargin,
"""|List
|List - java.awt
|List - java.util
|JList - javax.swing
|ListUI - javax.swing.plaf
|""".stripMargin,
compat = Map(
"2.13" ->
"""|List
|LazyList
|List - java.awt
|List - java.util
|JList - javax.swing
|""".stripMargin,
"3" ->
"""|List
|List - java.awt
|List - java.util
|List - scala.collection.immutable
|List[A](elems: A*): CC[A]
|""".stripMargin
),
includeDetail = false,
topLines = Some(5)
)

check(
"member",
"""
|object A {
| List.emp@@
|}""".stripMargin,
"""
|empty
|""".stripMargin,
includeDetail = false
)

check(
"extension",
"""
|object A {
| "".stripSu@@
|}""".stripMargin,
"""|stripSuffix
|""".stripMargin,
includeDetail = false
)

check(
"tparam",
"""
|class Foo[A] {
| def identity[B >: A](a: B): B = a
|}
|object Foo {
| new Foo[Int].ident@@
|}""".stripMargin,
"""|identity
|""".stripMargin,
includeDetail = false
)

check(
"tparam1",
"""
|class Foo[A] {
| def identity(a: A): A = a
|}
|object Foo {
| new Foo[Int].ident@@
|}""".stripMargin,
"""|identity
|""".stripMargin,
includeDetail = false
)

check(
"tparam2",
"""
|object A {
| Map.empty[Int, String].getOrEl@@
|}
|""".stripMargin,
"""|getOrElse
|""".stripMargin,
includeDetail = false
)

check(
"pkg",
"""
|import scala.collection.conc@@
|""".stripMargin,
"""|concurrent
|""".stripMargin,
includeDetail = false
)
}

0 comments on commit f0ccc7b

Please sign in to comment.