Skip to main content

Integrating a new editor

Metals is a language server implemented in Scala that communicates with a single client over JSON-RPC.

Requirements#

Java 8, 11, 17 provided by OpenJDK or Oracle. Eclipse OpenJ9 is not supported, please make sure the JAVA_HOME environment variable points to a valid Java 8, 11 or 17 installation.

macOS, Linux or Windows. Metals is developed on many operating systems and every PR is tested on Ubuntu, Windows and MacOS.

Scala 2.13, 2.12, 2.11 and Scala 3. Metals supports these Scala versions:

  • Scala 2.13: 2.13.6, 2.13.5, 2.13.4, 2.13.3, 2.13.2, 2.13.1, 2.13.0

  • Scala 2.12: 2.12.15, 2.12.14, 2.12.13, 2.12.12, 2.12.11, 2.12.10, 2.12.9, 2.12.8

  • Scala 2.11: 2.11.12

  • Scala 3: 3.1.0-RC2, 3.0.2, 3.0.1, 3.0.0

Note that 2.11.x support is deprecated and it will be removed in future releases. It's recommended to upgrade to Scala 2.12 or Scala 2.13

Starting the server#

Use Coursier to obtain the JVM classpath of Metals:

coursier bootstrap org.scalameta:metals_2.12:0.10.7+17-f589e8b6-SNAPSHOT -o metals -f

(optional) It's recommended to enable JVM string de-duplication and provide a generous stack size and memory options.

coursier bootstrap \
--java-opt -XX:+UseG1GC \
--java-opt -XX:+UseStringDeduplication \
--java-opt -Xss4m \
--java-opt -Xms100m \
org.scalameta:metals_2.12:0.10.7+17-f589e8b6-SNAPSHOT -o metals -f

See Metals server properties for additional system properties that are supported by the server.

JSON-RPC communication takes place over standard input/output so the Metals server doesn't print anything to the console when it starts. Instead, before establishing a connection with the client, Metals logs notifications to a global directory:

# macOS
~/Library/Caches/org.scalameta.metals/global.log
# Linux
$XDG_CACHE_HOME/org.scalameta.metals/global.log
# Linux (alternative)
$HOME/.cache/org.scalameta.metals/global.log
# Windows
{FOLDERID_LocalApplicationData}\.cache\org.scalameta.metals\global.log

After establishing a connection with the client, Metals redirects logs to the .metals/metals.log file in the LSP workspace root directory.

Metals supports two kinds of JSON-RPC endpoints:

  • Language Server Protocol: for the main functionality of the server, including editor text synchronization and semantic features such as goto definition.
  • Metals extensions: for additional functionality that is missing in LSP but improves the user experience.

Configuring the server#

Over time the recommended way to configure Metals has shifted from heavily relying on the Metals server properties to being fully able to be configured via InitializationOptions which are exchanged during the initialize process. While Metals will still work being fully configured by server properties, we strongly recommend that instead you rely on the InitializationOptions which are thoroughly covered below in the [initialize](#initialize] section.

Language Server Protocol#

Consult the LSP specification to learn more more how LSP works. Metals uses the following endpoints from the specification.

initialize#

  • the rootUri field is used to configure Metals for that workspace directory. The working directory for where server is started has no significant meaning.
  • at this point, Metals uses only full text synchronization. In the future, it will be able to use incremental text synchronization.
  • didChangeWatchedFiles client capability is used to determine whether to register file watchers.

InitializationOptions#

During initialize we also have the ability to pass in InitializationOptions. This is the primary way to configure Metals. In Metals we have a few different "providers". Some are LSP extensions, such as metals/inputBox which you read about below, and others used to be server properties that have been migrated to InitializationOptions. M

The currently available settings for InitializationOptions are listed below.

"InitializationOptions": {
"compilerOptions":{
"completionCommand": string,
"isCompletionItemDetailEnabled": boolean,
"isCompletionItemDocumentationEnabled": boolean,
"isCompletionItemResolve": boolean,
"isHoverDocumentationEnabled": boolean,
"isSignatureHelpDocumentationEnabled": boolean,
"overrideDefFormat": "ascii" | "unicode",
"parameterHintsCommand": string,
"snippetAutoIndent": boolean,
}
"copyWorksheetOutputProvider": boolean,
"debuggingProvider": boolean,
"decorationProvider": boolean,
"didFocusProvider": boolean,
"disableColorOutput" boolean,
"doctorProvider": "json" | "html",
"executeClientCommandProvider": boolean,
"globSyntax": "vscode" | "uri"
"icons": "octicons" | "vscode" | "unicode",
"inlineDecorationProvider": boolean,
"inputBoxProvider": boolean,
"isExitOnShutdown" : boolean,
"isHttpEnabled": boolean,
"openFilesOnRenameProvider": boolean,
"openNewWindowProvider": boolean,
"quickPickProvider": boolean,
"renameFileThreshold": number,
"slowTaskProvider": boolean,
"statusBarProvider": "on" | "off" | "show-message" | "log-message",
"treeViewProvider": boolean
}

You can also always check these in the InitializationOptions.scala file where you'll find all of the options and descriptions.

compilerOptions.completionCommand#

An optional string value for a command identifier to trigger completion (textDocument/signatureHelp) in the editor.

Possible values:

  • "editor.action.triggerSuggest": currently used by Visual Studio Code and coc.nvim.
  • empty: for all other editors.
compilerOptions.isCompletionItemDetailEnabled#

Boolean value signifying whether or not the CompletionItem.detail field should be populated.

Default value: true

compilerOptions.isCompletionItemDocumentationEnabled#

Boolean value signifying whether or not the CompletionItem.documentation field should be populated.

Default value: true

compilerOptions.isCompletionItemResolve#

Boolean value signifying whether the client wants Metals to handle the completionItem/resolve request.

https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve

Default value: true

compilerOptions.isHoverDocumentationEnabled#

Boolean value signifying whether to include docstrings in a textDocument/hover request.

Default value: true

compilerOptions.isSignatureHelpDocumentationEnabled#

Boolean value signifying whether or not the SignatureHelp.documentation field should be populated.

Default value: true

compilerOptions.overrideDefFormat#

Whether or not the presentation compiler overrides should show unicode icon or just be in ascii format.

Possible Values:

  • "ascii" (default)
  • unicode show the "๐Ÿ”ผ" icon in overrides.
compilerOptions.parameterHintsCommand#

An optional string value for a command identifier to trigger parameter hints (textDocument/signatureHelp) in the editor. Metals uses this setting to populate CompletionItem.command for completion items that move the cursor inside an argument list. For example, when completing "".stripSu@@ into "".stripSuffix(@@), Metals will automatically trigger parameter hints if this setting is provided by the editor.

Possible values:

  • "editor.action.triggerParameterHints": Used by Visual Studio Code and coc.nvim.
  • empty: for all other editors.
compilerOptions.snippetAutoIndent#

Certain editors will automatically insert indentation equal to that of the reference line that the operation started on. This is relevant in the case of multiline textEdits such as the "implement all methods" completion.

Possible values:

  • on: (default): the client automatically adds in the indentation. This is the case for VS Code, Sublime, and coc.nvim.
  • off: the client does not add any indentation when receiving a multi-line textEdit
copyWorksheetOutputProvider#

Boolean value signifying whether or not the client supports running CopyWorksheetOutput server command and copying it's results into the local buffer.

Default value: false

debuggingProvider#

Boolean value to signify that the client supports the Debug Adapter Protocol.

Default value: false

decorationProvider#

Boolean value to signify that the client supports the Decoration Protocol.

Default value: false

didFocusProvider#

Boolean value to signify that the client supports the metals/didFocusTextDocument extension.

Default value: false

disableColorOutput#

Useful for certain DAP clients that are unable to handle color codes for output. This will remove the color codes coming from whatever DAP server is currently being used.

Default value: false

doctorProvider#

Format that you'd like Doctor to return information in.

Possible values:

  • html: (default): Metals will return html that can be rendered directly in the browser or web view
  • json: json representation of the information returned by Doctor
executeClientCommandProvider#

Possible values:

  • off (default): the metals/executeClientCommand notification is not supported. Client commands can still be handled by enabling -Dmetals.http=on.
  • on: the metals/executeClientCommand notification is supported and all Metals client commands are handled.
globSyntax#

Controls the glob syntax for registering file watchers on absolute directories. Registration happens via client/registerCapability for the workspace/didChangeWatchedFiles method, if the editor client supports it.

Possible values:

  • uri (default): URI-encoded file paths, with forward slash / for file separators regardless of the operating system. Includes file:// prefix.
  • vscode: use regular Path.toString for the absolute directory parts (/ on macOS+Linux and \ on Windows) and forward slashes / for relative parts. For example, C:\Users\IEUser\workspace\project/*.{scala,sbt,properties}. This mode is used by the VS Code client.
inlineDecorationProvider#

If the client implements the Metals Decoration Protocol and supports decorations to be shown inline and not only at the end of a line.

Default: false

icons#

Possible values:

  • none (default): don't display icons in messages.
  • vscode: use Octicons such as $(rocket) for status bar messages, as supported by th VS Code status bar.
  • unicode: use unicode emojis like ๐Ÿš€ for status bar messages.
inputBoxProvider#

Possible values:

  • off (default): the metals/inputBox request is not supported. In this case, Metals tries to fallback to window/showMessageRequest when possible.
  • on: the metals/inputBox request is fully supported.
isExitOnShutdown#

Possible values:

  • off (default): run System.exit only on the exit notification, as required by the LSP specification.
  • on: run System.exit after the shutdown request, going against the LSP specification. This option is enabled by default for Sublime Text to prevent the Metals process from staying alive after Sublime Text has quit with Cmd+Q. It's not possible for Sublime Text packages to register a callback when the editor has quit. See LSP#410 for more details.
isHttpEnabled#

Possible values:

  • off (default): don't start a server with the Metals HTTP client.
  • on: start a server with the [Metals HTTP client] to interact with the server through a basic web UI. This option is needed for editor clients that don't support necessary requests such as window/showMessageRequest.
openFilesOnRenameProvider#

Boolean value to signify whether or not the client opens files when doing a rename.

Default: false

openNewWindowProvider#

Boolean value signifying whether or not the client supports opening up a new window with the newly created project. Used in conjunction with the New Project Provider.

Default value: false

quickPickProvider#

Boolean value to signify whether or not the client implements the metals/quickPick extensions.

Default value: false

renameFileThreshold#

The max amount of files that you would like the client to open if the client is a openFilesOnRenameProvider.

Default value: 300

slowTaskProvider#

Possible values:

  • off (default): the metals/slowTask request is not supported.
  • on: the metals/slowTask request is fully supported.
  • status-bar: the metals/slowTask request is not supported, but send updates about slow tasks via metals/status.
statusBarProvider#

Possible values:

  • off (default): the metals/status notification is not supported.
  • on: the metals/status notification is supported.
  • log-message: translate metals/status notifications to window/logMessage notifications.
  • show-message: translate metals/status notifications to window/showMessage show notifications however the client displays messages to the user.
treeViewProvider#

Boolean value signifying whether or not the client supports the Tree View Protocol.

Default value: false

Experimental Capabilities#

All of the features that used to be set with experimental can now all be set via InitializationOptions. This is the preferred way to configure Metals.

initialized#

Triggers build server initialization and workspace indexing. The initialized notification is critical for any Metals functionality to work.

shutdown#

It is very important that the client sends a shutdown request in order for Metals to clean up open resources.

  • persists incremental compilation analysis files. Without a shutdown hook, Metals will need to re-compile the entire workspace on next startup.
  • stops ongoing processes such as sbt bloopInstall
  • closes database connections

exit#

Kills the process using System.exit.

$/cancelRequest#

Used by metals/slowTask to notify when a long-running process has finished.

client/registerCapability#

If the client declares the workspace.didChangeWatchedFiles capability during the initialize request, then Metals follows up with a client/registerCapability request to register file watchers for certain glob patterns.

textDocument/didOpen#

Triggers compilation in the build server for the build target containing the opened document. Related, see metals/didFocusTextDocument.

textDocument/didChange#

Required to know the text contents of the current unsaved buffer.

textDocument/didClose#

Cleans up resources.

textDocument/didSave#

Triggers compilation in the build server and analyses if the build needs to be re-imported.

textDocument/publishDiagnostics#

Metals forwards diagnostics from the build server to the editor client. Additionally, Metals publishes Information diagnostics for unexpected compilation errors when navigating external library sources.

textDocument/definition#

Metals supports goto definition for workspace sources in addition to external library sources.

  • Library sources live under the directory .metals/readonly and they are marked as read-only to prevent the user from editing them.
  • The destination location can either be a Scala or Java source file. It is recommended to have a Java language server installed to navigate Java sources.

textDocument/references#

Metals finds symbol references for workspace sources but not external library dependencies.

LSP does not support streaming references so when project sources have not been compiled at the point of a request, Metals returns immediately with potentially incomplete results and triggers a background cascade compilation to find new symbol references. If new symbol references are discovered after the background compilation completes, Metals sends a notification via metals/status and window/logMessage asking the user to run "find references" again.

textDocument/documentSymbol#

Returns DocumentSymbol[] if the client declares support for hierarchical document symbol or SymbolInformation[] otherwise.

textDocument/formatting#

Formats the sources with the Scalafmt version that is declared in .scalafmt.conf.

  • when .scalafmt.conf is missing, Metals sends a window/showMessageRequest to create the file.
  • when .scalafmt.conf exists but doesn't declare a version setting, Metals sends a metals/inputBox when supported (with fallback to window/showMessageRequest when unsupported) to prepend version=$VERSION to the .scalafmt.conf file.
  • the first format request is usually slow because Metals needs to download Scalafmt artifacts from Maven Central. While the download happens, Metals adds a message in the status bar via metals/status and detailed download progress information is logged to .metals/metals.log.

workspace/didChangeWatchedFiles#

Optional. Metals uses a built-in file watcher for critical functionality such as Goto Definition so it is OK if an editor does not send workspace/didChangeWatchedFiles notifications.

Metals listens to workspace/didChangeWatchedFiles notifications from the editor for nice-to-have but non-critical file watching events. Metals automatically registers for the following glob patterns if the editor supports dynamic registration for file watching.

{
"watchers": [
{
"globPattern": "file:///to/workspace/*.sbt"
},
{
"globPattern": "file:///to/workspace/pom.xml"
},
{
"globPattern": "file:///to/workspace/*.sc"
},
{
"globPattern": "file:///to/workspace/*?.gradle"
},
{
"globPattern": "file:///to/workspace/*.gradle.kts"
},
{
"globPattern": "file:///to/workspace/project/*.{scala,sbt}"
},
{
"globPattern": "file:///to/workspace/project/project/*.{scala,sbt}"
},
{
"globPattern": "file:///to/workspace/project/build.properties"
}
]
}

The editor is responsible for manually watching these file patterns if the editor does not support dynamic file watching registration but can still send workspace/didChangeWatchedFiles notifications.

workspace/executeCommands#

Used to trigger a Metals server command.

workspace/didChangeConfiguration#

Used to update Metals user configuration.

window/logMessage#

Used to log non-critical and non-actionable information. The user is only expected to use the logs for troubleshooting or finding metrics for how long certain events take.

window/showMessage#

Used to send critical but non-actionable notifications to the user. For non-critical notifications, see metals/status.

window/showMessageRequest#

Used to send critical and actionable notifications to the user. To notify the user about long running tasks that can be cancelled, the extension metals/slowTask is used instead.

Metals server properties#

There are various Metals server properties that can be configured through JVM system properties. A system property is passed to the server like this:

# with `java` binary
java -Dmetals.statistics=all ...
# with `coursier bootstrap`
coursier bootstrap --java-opt -Dmetals.statistics=all ...

Below are the available server properties:

-Dmetals.verbose#

Possible values:

  • off (default): don't log unnecessary details.
  • on: emit very detailed logs, should only be used when debugging problems.

-Dmetals.statistics#

By default, Metals logs only the most relevant metrics like time it takes to run sbt and import a workspace. The enable further metrics, update this property with a comma separated list of the following supported values:

  • memory: print memory usage of the navigation index after build import.
  • definition: print total time to respond to textDocument/definition requests.

Set the value to -Dmetals.statistics=all to enable all statistics.

-Dmetals.h2.auto-server#

Possible values:

  • on (default): use H2 AUTO_SERVER=TRUE mode to support multiple concurrent Metals servers in the same workspace. If this option is enabled, the Metals H2 database communicate to other concurrently running Metals servers via TCP through a free port. In case of failure to establish a AUTO_SERVER=TRUE connection, Metals falls back to AUTO_SERVER=FALSE.
  • off: do not use use AUTO_SERVER=TRUE. By disabling this option, it's not possible to run concurrent Metals servers in the same workspace directory. For example, it's not possible to have both VS Code and Vim installed with Metals running in the same directory. In case there are multiple Metals servers running in the same workspace directory, Metals falls back to using an in-memory database resulting in a degraded user experience.

-Dmetals.pc.debug#

Possible values:

  • off (default): do not log verbose debugging information for the presentation compiler.
  • on: log verbose debugging information for the presentation compiler.

-Dbloop.sbt.version#

Version number of the sbt-bloop plugin to use for the "Install build" command. Default value is -Dbloop.sbt.version=1.4.9.

The below properties are also available as user configuration options. It's preferable to set these there:

-Dmetals.bloop-port#

Port number of the Bloop server to connect to. Should only be used if Bloop server was setup in a custom way. Default value is 8212.

Possible values are any allowed port number that the Bloop server is able to run on.

Metals user configuration#

Users can customize the Metals server through the LSP workspace/didChangeConfiguration notification. Unlike server properties, it is normal for regular Metals users to configure these options.

User configuration options can optionally be provided via server properties using the -Dmetals. prefix. System properties may be helpful for editor clients that don't support workspace/didChangeConfiguration. In case user configuration is defined both via system properties and workspace/didChangeConfiguration, then workspace/didChangeConfiguration takes precedence.

Java Home directory#

The Java Home directory used for indexing JDK sources and locating the java binary.

Default: JAVA_HOME environment variable with fallback to user.home system property.

Example:

{
"metals": {
"javaHome": "/Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home"
}
}

sbt script#

Optional absolute path to an sbt executable to use for running sbt bloopInstall. By default, Metals uses java -jar sbt-launch.jar with an embedded launcher while respecting .jvmopts and .sbtopts. Update this setting if your sbt script requires more customizations like using environment variables.

Default: empty string "".

Example:

{
"metals": {
"sbtScript": "/usr/local/bin/sbt"
}
}

Gradle script#

Optional absolute path to a gradle executable to use for running gradle bloopInstall. By default, Metals uses gradlew with 5.3.1 gradle version. Update this setting if your gradle script requires more customizations like using environment variables.

Default: empty string "".

Example:

{
"metals": {
"gradleScript": "/usr/local/bin/gradle"
}
}

Maven script#

Optional absolute path to a maven executable to use for generating bloop config. By default, Metals uses mvnw maven wrapper with 3.6.1 maven version. Update this setting if your maven script requires more customizations

Default: empty string "".

Example:

{
"metals": {
"mavenScript": "/usr/local/bin/mvn"
}
}

Mill script#

Optional absolute path to a mill executable to use for running mill mill.contrib.Bloop/install. By default, Metals uses mill wrapper script with 0.5.0 mill version. Update this setting if your mill script requires more customizations like using environment variables.

Default: empty string "".

Example:

{
"metals": {
"millScript": "/usr/local/bin/mill"
}
}

Scalafmt config path#

Optional custom path to the .scalafmt.conf file. Should be an absolute path and use forward slashes / for file separators (even on Windows).

Default: empty string "".

Example:

{
"metals": {
"scalafmtConfigPath": "project/.scalafmt.conf"
}
}

Scalafix config path#

Optional custom path to the .scalafix.conf file. Should be an absolute path and use forward slashes / for file separators (even on Windows).

Default: empty string "".

Example:

{
"metals": {
"scalafixConfigPath": "project/.scalafix.conf"
}
}

Ammonite JVM Properties#

Optional list of JVM properties to pass along to the Ammonite server. Each property needs to be a separate item.\n\nExample: -Xmx1G or -Xms100M"

Default: [].

Example:

{
"metals": {
"ammoniteJvmProperties": ["-Xmx1G"]
}
}

Excluded Packages#

Packages that will be excluded from completions, imports, and symbol searches.

Note that this is in addition to some default packages that are already excluded. The default excluded packages are listed below:

META-INF
images
toolbarButtonGraphics
jdk
sun
oracle
java.awt.desktop
org.jcp
org.omg
org.graalvm
com.oracle
com.sun
com.apple
apple

If there is a need to remove one of the defaults, you are able to do so by including the package in your list and prepending -- to it.

Example:

["--sun"]

Default: [].

Example:

{
"metals": {
"excludedPackages": ["akka.actor.typed.javadsl"]
}
}

Don't generate Bloop plugin file for sbt#

If true, Metals will not generate metals.sbt files under the assumption that sbt-bloop is already manually installed in the sbt build. Build import will fail with a 'not valid command bloopInstall' error in case Bloop is not manually installed in the build when using this option.

Default: false

Example:

{
"metals": {
"bloopSbtAlreadyInstalled": false
}
}

Version of Bloop#

This version will be used for the Bloop build tool plugin, for any supported build tool, while importing in Metals as well as for running the embedded server

Default: 1.4.9

Example:

{
"metals": {
"bloopVersion": "1.4.0-RC1"
}
}

Should display lenses with links to super methods#

Super method lenses are visible above methods definition that override another methods. Clicking on a lens jumps to super method definition. Disabled lenses are not calculated for opened documents which might speed up document processing.

Default: false

Example:

{
"metals": {
"superMethodLensesEnabled": false
}
}

Should display type annotations for inferred types#

When this option is enabled, each method that can have inferred types has them displayed either as additional decorations if they are supported by the editor or shown in the hover.

Default: false

Example:

{
"metals": {
"showInferredType": false
}
}

Should display implicit parameter at usage sites#

When this option is enabled, each method that has implicit arguments has them displayed either as additional decorations if they are supported by the editor or shown in the hover.

Default: false

Example:

{
"metals": {
"showImplicitArguments": false
}
}

Should display implicit conversion at usage sites#

When this option is enabled, each place where an implicit method or class is used has it displayed either as additional decorations if they are supported by the editor or shown in the hover.

Default: false

Example:

{
"metals": {
"showImplicitConversionsAndClasses": false
}
}

Should try adjust indentation on range formatting.#

When this option is enabled, when user pastes any snippet into a Scala file, Metals will try to adjust the indentation to that of the current cursor.

Default: false

Example:

{
"metals": {
"enableIndentOnPaste": false
}
}

Remote language server#

A URL pointing to an endpoint that implements a remote language server.

See https://scalameta.org/metals/docs/contributors/remote-language-server.html for documentation on remote language servers.

Default: empty string "".

Example:

{
"metals": {
"remoteLanguageServer": "https://language-server.company.com/message"
}
}

Default fallback Scala version#

The Scala compiler version that is used as the default or fallback in case a file doesn't belong to any build target or the specified Scala version isn't supported by Metals. This applies to standalone Scala files, worksheets, and Ammonite scripts.

Default: 2.12.15

Example:

{
"metals": {
"fallbackScalaVersion": 2.12.15
}
}

Metals server commands#

The client can trigger one of the following commands through the workspace/executeCommand request.

Analyze stacktrace#

Command: "analyze-stacktrace"

Arguments: [string], where the string is a stacktrace.

Converts provided stacktrace in the parameter to a format that contains links to locations of places where the exception was raised.

If the configuration parameter of the client (support-commands-in-html) is true then client is requested to display html with links already pointing to proper locations in user codebase. Otherwise client will display simple scala file but with code lenses that direct user to proper location in codebase.

Switch build server#

Command: "bsp-switch"

Arguments: null

Prompt the user to select a new build server to connect to.

This command does nothing in case there are less than two installed build servers on the computer. In case the user has multiple BSP servers installed then Metals will prompt the user to select which server to use.

Connect to build server#

Command: "build-connect"

Arguments: null

Establish a new connection to the build server and reindex the workspace.

This command can be helpful in scenarios when Metals feels unresponsive, for example when reopening Metals after the computer it has been sleeping.

Cancel compilation#

Command: "compile-cancel"

Arguments: null

Cancel the currently ongoing compilation, if any.

Cascade compile#

Command: "compile-cascade"

Arguments: null

Compile the current open files along with all build targets in this workspace that depend on those files.

By default, Metals compiles only the current build target and its dependencies when saving a file. Run the cascade compile task to additionally compile the inverse dependencies of the current build target. For example, if you change the API in main sources and run cascade compile then it will also compile the test sources that depend on main.

Clean compile workspace#

Command: "compile-clean"

Arguments: null

Recompile all build targets in this workspace.

By default, Metals compiles the files incrementally. In case of any compile artifacts corruption this command might be run to make sure everything is recompiled correctly.

Copy Worksheet Output#

Command: "copy-worksheet-output"

Arguments: [uri], the uri of the worksheet that you'd like to copy the contents of.

Copy the contents of a worksheet to your local buffer.

Note: This command returns the contents of the worksheet, and the LSP client is in charge of taking that content and putting it into your local buffer.

Show TASTy#

Command: "show-tasty"

Arguments: [string], where the string is a path to a Scala 3 source or a tasty file.

If the file is a Scala 3 source, this command will try to find the relevant tasty file for it, read it and display it in a human readable format. If the argument already points to a TASTy file, it will be read directly.

Extract member definition#

Command: "extract-member-definition"

Arguments: [uri, line, character], uri of the document that the command needs to be invoked on together with line number and character/column where the definition is.

Whenever a user chooses a code action to extract a definition of a Class/Trait/Object/Enum this command is later ran to extract the code and create a new file with it

Generate BSP Config#

Command: "generate-bsp-config"

Arguments: [string], name of the build server.

Checks to see if your build tool can serve as a BSP server. If so, generate the necessary BSP config to connect to the server. If there is more than one build tool for a workspace, you can then choose the desired one and that one will be used to generate the config.

After the config is generated, Metals will attempt to auto-connect to it.

The build servers that Metals knows how to detect and start:

  • sbt

Note: while Metals does know how to start Bloop, Bloop will be started when you trigger a build import or when you use bsp-switch to switch to Bloop.

Goto location for position#

Command: "goto-position"

Arguments: [location], where the location is a lsp location object.

Move the cursor to the location provided in arguments. It simply forwards request to client.

Go to super method/field definition#

Command: "goto-super-method"

Arguments: Object with document and position

Example:

{
document: "file:///home/dev/foo/Bar.scala",
position: {line: 5, character: 12}
}

Jumps to super method/field definition of a symbol under cursor according to inheritance rules. When A {override def x()} <:< B <:< C {def x()} and on method 'A.x' it will jump directly to 'C.x' as method x() is not overridden in B. If symbol is a reference of a method it will jump to a definition. If symbol under cursor is invalid or does not override anything then command is ignored.

Note: document in json argument must be absolute path.

Goto location for symbol#

Command: "goto"

Arguments: [string], where the string is a SemanticDB symbol.

Move the cursor to the definition of the argument symbol.

Import build#

Command: "build-import"

Arguments: null

Import the latest changes from the build to for example pick up new library dependencies.

By default, Metals automatically prompts you to import the build when sources of the build change. Use this command to manually trigger an import build instead of relying on the automatic prompt.

Insert inferred type of a value#

Command: "insert-inferred-type"

Arguments: [uri, line, character], uri to the document that the command needs to be invoked on together with line number and character/column.

Whenever a user chooses code action to insert the inferred type this command is later ran to calculate the type and insert it in the correct location.

Create new scala file#

Command: "new-scala-file"

Arguments: [string[]], where the first is a directory location for the new file. The second and third positions correspond to the file name and file type to allow for quick creation of a file if all are present.

Create and open new file with either scala class, object, trait, package object or worksheet.

Note: requires 'metals/inputBox' capability from language client.

New Scala Project#

Command: "new-scala-project"

Arguments: null

Create a new Scala project using one of the available g8 templates. This includes simple projects as well as samples for most of the popular Scala frameworks. The command reuses the Metals quick pick extension to work and can function with window/showMessageRequest, however the experience will not be optimal in that case. Some editors might also offer to open the newly created project via openNewWindowProvider, but it is not necessary for the main functionality to work.

Reset Choice Popup#

Command: "reset-choice"

Arguments: [string?], where string is a choice value.

ResetChoicePopup command allows you to reset a decision you made about different settings. E.g. If you choose to import workspace with sbt you can decide to reset and change it again.

Provided string is optional but if present it must be one of defined in PopupChoiceReset.scala If a choice is not provided it will execute interactive mode where user is prompt to select which choice to reset.

Restart build server#

Command: "build-restart"

Arguments: null

Unconditionally stop the current running Bloop server and start a new one using Bloop launcher

Run doctor#

Command: "doctor-run"

Arguments: null

Open the Metals doctor to troubleshoot potential problems with the build.

This command can be helpful in scenarios where features are not working as expected such as compile errors are not appearing or completions are not correct.

Scan sources#

Command: "sources-scan"

Arguments: null

Walk all files in the workspace and index where symbols are defined.

Is automatically run once after initialized notification and incrementally updated on file watching events. A language client that doesn't support file watching can run this manually instead. It should not be much slower than walking the entire file tree and reading *.scala files to string, indexing itself is cheap.

Start Ammonite build server#

Command: "ammonite-start"

Arguments: null

Start Ammonite build server

Start debug adapter#

Command: "debug-adapter-start"

Arguments: DebugSessionParameters object Example:

{
"targets": ["mybuild://workspace/foo/?id=foo"],
dataKind: "scala-main-class",
data: {
className: "com.foo.App"
}
}

or DebugUnresolvedMainClassParams object Example:

{
mainClass: "com.foo.App",
buildTarget: "foo",
args: ["bar"],
jvmOptions: ["-Dfile.encoding=UTF-16"],
env: {"NUM" : "123"},
envFile: ".env"
}

or DebugUnresolvedTestClassParams object Example:

{
testClass: "com.foo.FooSuite",
buildTarget: "foo"
}

Start debug adapter

Stop Ammonite build server#

Command: "ammonite-stop"

Arguments: null

Stop Ammonite build server

Go to super method/field definition in hierarchy#

Command: "super-method-hierarchy"

Arguments: Object with document and position

Example:

{
document: "file:///home/dev/foo/Bar.scala",
position: {line: 5, character: 12}
}

When user executes this command it will calculate inheritance hierarchy of a class that contains given method. Then it will filter out classes not overriding given method and a list using 'metalsQuickPick' will be displayed to which super method user would like to go to. Command has no effect on other symbols than method definition. QuickPick will show up only if more than one result is found.

Note: document in json argument must be absolute path.

Metals client commands#

The Metals server can send one of the following client commands if the client supports the metals/executeClientCommand notification,

Open a specified folder either in the same or new window#

Command: "metals-open-folder"

Arguments: An object with uri and newWindow fields. Example:

{
"uri": "file://path/to/directory",
"newWindow": true
}

Open a new window with the specified directory.

Run doctor#

Command: "metals-doctor-run"

Arguments: string, the HTML to display in the focused window.

Focus on a window displaying troubleshooting help from the Metals doctor.

If doctorProvider is set to "json" then the schema is as follows:

export interface DoctorOutput {
/** Metals Doctor title */
title: string;
/**
* Contains decisions that were made about what build tool or build server
* the user has chosen. There is also other brief information about understanding
* the Doctor placed in here as well.
*/
headerText: string;
/**
* If build targets are detected in your workspace, they will be listed here with
* the status of related functionality of Metals for each build target.
*/
targets?: DoctorBuildTarget[];
/** Messages given if build targets cannot be found */
messages?: DoctorRecommendation[];
}
export interface DoctorBuildTarget {
/** Name of the build target */
buildTarget: string;
/** Scala version of the build target */
scalaVersion: string;
/** Status of diagnostics */
diagnostics: string;
/** Status of goto definitions */
gotoDefinition: string;
/** Status of completions */
completions: string;
/** Status of find references */
findReferences: string;
/** Any recommendations in how to fix any issues that are found above */
recommendation: string;
}
export interface DoctorRecommendation {
/** Title of the recommendation */
title: string;
/** Recommendations related to the found issue. */
recommendations: string[]
}

Reload doctor#

Command: "metals-doctor-reload"

Arguments: string, the HTML to display in the focused window.

Reload the HTML contents of an open Doctor window, if any. Should be ignored if there is no open doctor window. If doctorProvider is set to "json", then the schema is the same as found above in "metals-run-doctor"

Toggle logs#

Command: "metals-logs-toggle"

Arguments: null

Focus or remove focus on the output logs reported by the server via window/logMessage.

In VS Code, this opens the "output" channel for the Metals extension.

Open problems#

Command: "metals-diagnostics-focus"

Arguments: null

Focus on the window that lists all published diagnostics.

In VS Code, this opens the "problems" window.

Goto location#

Command: "metals-goto-location"

Arguments: First required parameter is LSP Location object with uri and range fields. Second parameter is optional and has signature otherWindow: Boolean. It gives a hint to client that if possible it would be good to open location in another buffer/window. Example:

[{
"uri": "file://path/to/Definition.scala",
"range": {
"start": {"line": 194, "character": 0},
"end": {"line": 194, "character": 1}
}
},
false
]

Move the cursor focus to the provided location

Echo command#

Command: "metals-echo-command"

Arguments: string, the command ID to execute on the client.

A client command that should be forwarded back to the Metals server.

Metals may register commands in client UIs like tree view nodes that should be forwarded back to the Metals server if the client clicks on the UI elements.

Refresh model#

Command: "metals-model-refresh"

Arguments: null

Notifies the client that the model has been updated and it should be refreshed (e.g. by resending code lens request)

Metals HTTP client#

Metals has an optional web interface that can be used to trigger server commands and respond to server requests. This interface is not intended for regular users, it exists only to help editor plugin authors integrate with Metals.

Metals http client

The server is enabled by passing the -Dmetals.http=on system property. The server runs by default at http://localhost:5031. When the port 5031 is taken the next free increment is chosen instead (5032, 5033, ...).

Metals LSP extensions#

Editor clients can opt into receiving Metals-specific JSON-RPC requests and notifications. Metals extensions are not defined in LSP and are not strictly required for the Metals server to function but it is recommended to implement them to improve the user experience.

To enable Metals extensions, start the main process with the system property -Dmetals.extensions=true.

Debug Adapter Protocol#

Metals implements and additional protocol for running and debugging inside the editor, see the Debug Adapter Protocol.

Tree View Protocol#

Metals implements several custom JSON-RPC endpoints related to rendering tree views in the editor client, the Tree View Protocol.

Decoration Protocol#

Metals implements an LSP extension to display non-editable text in the editor, see the Decoration Protocol.

metals/slowTask#

The Metals slow task request is sent from the server to the client to notify the start of a long running process with unknown estimated total time. A cancel: true response from the client cancels the task. A $/cancelRequest request from the server indicates that the task has completed.

Metals slow task

The difference between metals/slowTask and window/showMessageRequest is that slowTask is time-sensitive and the interface should display a timer for how long the task has been running while showMessageRequest is static.

Request:

  • method: metals/slowTask
  • params: MetalsSlowTaskParams defined as follows:
interface MetalsSlowTaskParams {
/** The name of this slow task */
message: string;
/**
* If true, the log output from this task does not need to be displayed to the user.
*
* In VS Code, the Metals "Output channel" is not toggled when this flag is true.
*/
quietLogs?: boolean;
/** Time that has elapsed since the begging of the task. */
secondsElapsed?: number;
}

Response:

  • result: MetalsSlowTaskResponse defined as follows
interface MetalsSlowTaskResult {
/**
* If true, cancel the running task.
* If false, the user dismissed the dialogue but want to
* continue running the task.
*/
cancel: boolean;
}

metals/status#

The Metals status notification is sent from the server to the client to notify about non-critical and non-actionable events that are happening in the server. Metals status notifications are a complement to window/showMessage and window/logMessage. Unlike window/logMessage, status notifications should always be visible in the user interface. Unlike window/showMessage, status notifications are not critical meaning that they should not demand too much attention from the user.

In general, Metals uses status notifications to update the user about ongoing events in the server such as batch compilation in the build server or when a successful connection was established with the build server.

Metals status bar

The "๐Ÿš€ Imported build" and "๐Ÿ”„ Compiling explorer" messages at the bottom of the window are metals/status notifications.

Notification:

  • method: metals/status
  • params: MetalsStatusParams defined as follows:
interface MetalsStatusParams {
/** The text to display in the status bar. */
text: string;
/** If true, show the status bar. */
show?: boolean;
/** If true, hide the status bar. */
hide?: boolean;
/** If set, display this message when user hovers over the status bar. */
tooltip?: string;
/** If set, execute this command when the user clicks on the status bar item. */
command?: string;
}

metals/didFocusTextDocument#

The Metals did focus notification is sent from the client to the server when the editor changes focus to a new text document. Unlike textDocument/didOpen, the did focus notification is sent even when the text document is already open.

Metals did focus

Observe that the compilation error appears as soon as UserTest.scala is focused even if the text document was already open before. The LSP textDocument/didOpen notification is only sent the first time a document so it is not possible for the language server to re-trigger compilation when moves focus back to UserTest.scala that depends on APIs defined in User.scala.

Notification:

  • method: metals/didFocusTextDocument
  • params: string, the URI of the document where the focused was moved to.

metals/executeClientCommand#

The Metals execute client command is sent from the server to the client to trigger an action inside the editor. This notification is a copy of the workspace/executeCommand except

  • execute client command is a notification, not a request
  • execute client command is initiated from the server, not the client

See Metals client commands for the list of supported client commands.

Notification:

  • method: metals/executeClientCommand
  • params: ExecuteCommandParams, as defined in LSP.

metals/inputBox#

The Metals input box request is sent from the server to the client to let the user provide a string value for a given prompt. Unlike window/showMessageRequest, the metals/inputBox request allows the user to provide a custom response instead of picking a pre-selected value.

Request:

  • method: metals/inputBox
  • params: MetalsInputBoxParams defined as follows. Note, matches InputBoxOptions in the Visual Studio Code API:
export interface MetalsInputBoxParams {
/**
* The value to prefill in the input box.
*/
value?: string;
/**
* The text to display underneath the input box.
*/
prompt?: string;
/**
* An optional string to show as place holder in the input box to guide the user what to type.
*/
placeHolder?: string;
/**
* Set to `true` to show a password prompt that will not show the typed value.
*/
password?: boolean;
/**
* Set to `true` to keep the input box open when focus moves to another part of the editor or to another window.
*/
ignoreFocusOut?: boolean;
}
  • result: MetalsInputBoxResult defined as follows:
export interface MetalsInputBoxResult {
value?: string;
cancelled?: boolean;
}

metals/quickPick#

The Metals quick pick request is sent from the server to the client to let the user provide a string value by picking one out of a number of given options. It is similar to window/showMessageRequest, but the metals/quickPick request has richer parameters, that can be used to filter items to pick, like description and detail.

Request:

  • method: metals/quickPick
  • params: MetalsQuickInputParams defined as follows. It partially matches QuickPickOptions in the Visual Studio Code API, but it also contains items of MetalsQuickPickItem, which, in it's turn, partially matches QuickPickItem, but these interfaces do not contain options for picking many items:
export interface MetalsQuickPickParams {
/**
* An array of items that can be selected from.
*/
items: MetalsQuickPickItem[];
/**
* An optional flag to include the description when filtering the picks.
*/
matchOnDescription?: boolean;
/**
* An optional flag to include the detail when filtering the picks.
*/
matchOnDetail?: boolean;
/**
* An optional string to show as place holder in the input box to guide the user what to pick on.
*/
placeHolder?: string;
/**
* Set to `true` to keep the picker open when focus moves to another part of the editor or to another window.
*/
ignoreFocusOut?: boolean;
}
export interface MetalsQuickPickItem {
/**
* An id for this items that should be return as a result of the picking.
*/
id: string;
/**
* A human readable string which is rendered prominent.
*/
label: string;
/**
* A human readable string which is rendered less prominent.
*/
description?: string;
/**
* A human readable string which is rendered less prominent.
*/
detail?: string;
/**
* Always show this item.
*/
alwaysShow?: boolean;
}
  • result: MetalsQuickPickResult defined as follows:
export interface MetalsQuickPickResult {
itemId?: string;
cancelled?: boolean;
}

metals/windowStateDidChange#

The metals/windowStateDidChange notification is sent from the client to the server to indicate whether the editor application window is focused or not. When the editor window is not focused, Metals tries to avoid triggering expensive computation in the background such as compilation.

Notification:

  • method: metals/windowStateDidChange
  • params: WindowStateDidChangeParams defined as follows:
interface WindowStateDidChangeParams( {
/** If true, the editor application window is focused. False, otherwise. */
focused: boolean;
}

metals/openWindow#

The metals/openWindow params are used with the New Scala Project functionality. After the new project has been created, if the editor has the ability to open the project in a new window then these params are used with the the metals-open-folder command.

interface MetalsOpenWindowParams {
/** Location of the newly created project. */
uri: string;
/** Whether or not to open the project in a new window. */
openNewWindow: boolean;
}