Skip to content

Latest commit

 

History

History
85 lines (49 loc) · 6.67 KB

architecture.md

File metadata and controls

85 lines (49 loc) · 6.67 KB

Architecture of Metals

This document describes the high-level architecture of Metals following the philosophy of rust-analyzer's ARCHITECTURE.md

Other resources

LSP endpoints

The most important file of this project is MetalsLanguageServer.scala. In this file, we define all of the LSP endpoints, for example, you will find the endpoint for textDocument/completion request as follows.

@JsonRequest("textDocument/completion")
def completion(...) = ...

In addition to the LSP endpoints, this file contains many components, for example private var semanticdbs: Semanticdbs = _. Those components will be initialized later at some points like on LSP's initialize request.

Presentation compiler

Metals features are powered by presentation compilers, if you hit Compilers.scala it is the client of compilers.

mtags module is the Scala version specific module used to interact with the Scala presentation compiler using Java defined interfaces. You can find the interfaces under mtags-interface project.

For example, ScalaPresentationCompiler.java in mtags-interface is the interface for ScalaPresentationCompiler.scala under scala-2 and scala-3 directories of mtags module.

For more details

SemanticDB

Metals uses semanticdb for many features (Providers that receive the instance of Semanticdbs) such as references and renames. Semanticdb offers us information from the compiler that are written to disk and easily consumable. Metals consumes SemanticDBs in two ways:

  • FileSystemsSemanticdbs consumes SemanticDBs on disks
  • InteractiveSemanticdbs will generate SemanticDB on the fly using the presentation compiler via mtags, in case FileSystemsSemanticdbs failed or when the build tool doesn't compiler specific files such as dependency sources or sbt files.

In addition, classes extend SemanticdbFeatureProvider index the semanticdb symbols, that will be updated by SemanticdbIndexer.

Build Server

Metals communicates with build server such as bloop and sbt using Build Server Protocol.

BspConnector.scala manages the connections between Metals and build server, and BuildServerConnection.scala represents the API wrapper for the build server.

For more details about sbt's BSP support in Metals, see the blog post.

Worksheet

Worksheet support is provided by mdoc, which is able to typecheck and evaluate each line of the input. The main class responsible for worksheets is WorksheetProvider.scala. It is responsible for downloading mdoc instance for each Scala version that is supported and running the evaluation in the file input.

Later the evaluations are published using decoration extension or via additional Text Edits for editors that do not support decorations. This is done in the two classes implementing WorksheetPublisher.scala:

Formatting

FormattingProvider.scala takes care of how Metals handles textDocument/formatting. It uses scalafmt as a code formatter downloading dynamically using scalafmt-dynamic. We don't embed a specific version of scalafmt into Metals so that users can switch scalafmt's version using .scalafmt.conf.

Note that FormattingProvider doesn't handle textDocument/rangeFormatting.

Scalafix

Scalafix support is implemented in the ScalafixProvider.scala. The class uses scalafix API scalafix.interfaces.Scalafix to run the rules and get text edits, which are later changed to LSP TextEdits and applied to the file using WorkspaceEdit.

Metals downloads separate version of Scalafix for each binary version of Scala. It can also download additional dependencies for each of the used rules.

Debbugging

Debugging is handled by Debug Adapter Protocol, which is a complementary protocol to LSP.

The main code for debugging resides in scala.meta.internal.metals.debug package with DebugProvider.scala being the main entrypoint.

DebugProvider sets up the communication between the debug server process started by the build server and the client. This communication is handled in DebugProxy.scala which translates some of the messages in order to enrich them with the information from Metals itself.

You can find more information about DAP here