-
-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Outline for glossary and initial set of terms * Add more glossary entries (#635) --------- Co-authored-by: Cameron Duley <[email protected]>
- Loading branch information
1 parent
1e2aa3e
commit 81441fa
Showing
4 changed files
with
111 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,33 @@ | ||
# Architecture | ||
|
||
## Project Structure | ||
|
||
Lexical is designed to keep your application isolated from lexical's code. Because of this, lexical is structured as an umbrella app, with the following sub-apps: | ||
|
||
* `core`: Contains all code common to the other applications. | ||
* `common`: Contains all code common to the other applications. | ||
* `proto`: Used by `protocol` to generate the Elixir representation of LSP data structures. | ||
* `protocol`: Code related to speaking the language server protocol. | ||
* `remote_control`: The application that's injected into a project's code, which | ||
gives lexical an API to do things in the context of your app. | ||
gives lexical an API to do things in the context of your app. | ||
* `server` The language server itself. | ||
|
||
Lexical is an umbrella app so we can control how many dependencies the remote control app has. By separating lexical into sub-applications, each is built as a separate archive, and we can pick and choose which of these applications (and their dependencies) are injected into the project's VM, thus reducing how much contamination the project sees. If lexical was a standard application, adding dependencies to lexical would cause those dependencies to appear in the project's VM, which might cause build issues, version conflicts in mix or other inconsistencies. | ||
|
||
Since the `remote_control` app only depends on `common`, `path_glob` and `elixir_sense`, only those applications pollute the project's vm. Keeping `remote_control`'s dependencies to a minimum is a design goal of this architecture. | ||
|
||
|
||
## Language Server | ||
The language server (the `server` app) is the entry point to Lexical. When started by the `start_lexical.sh` command, it sets up a [transport](`Lexical.Server.Transport`) that [reads JsonRPC from standard input and writes responses to standard output](`Lexical.Server.Transport.StdIO`). | ||
|
||
The language server (the `server` app) is the entry point to Lexical. When started by the `start_lexical.sh` command, it sets up a [transport](`Lexical.Server.Transport`) that [reads JsonRPC from standard input and writes responses to standard output](`Lexical.Server.Transport.StdIO`). | ||
|
||
When a message is received, it is parsed into either a [LSP Request](`Lexical.Protocol.Requests`) or a [LSP Notification](`Lexical.Protocol.Notifications`) and then it's handed to the [language server](`Lexical.Server`) to process. | ||
|
||
The only messages the [lexical server process](`Lexical.Server`) handles directly are those related to the lifecycle of the language server itself. All other messages are delegated to a _Provider Handler_. This delegation is accomplished by the server process adding the request to the [provider queue](`Lexical.Server.Provider.Queue`). The provider queue asks the `Lexical.Server.Provider.Handlers.for_request/1` function which handler is configured to handle the request, creates a task for the handler and starts it. | ||
The only messages the [lexical server process](`Lexical.Server`) handles directly are those related to the lifecycle of the language server itself: | ||
|
||
- Synchronizing document states. | ||
- Processing LSP configuration changes. | ||
- Performing initialization and shutdown. | ||
|
||
A _Provider Handler_ is just a module that defines a function of arity 2 that takes the request to handle and a `Lexical.Server.Provider.Env`. These functions can reply to the request, ignore it, or do some other action. | ||
All other messages are delegated to a _Provider Handler_. This delegation is accomplished by the server process adding the request to the [provider queue](`Lexical.Server.Provider.Queue`). The provider queue asks the `Lexical.Server.Provider.Handlers.for_request/1` function which handler is configured to handle the request, creates a task for the handler and starts it. | ||
|
||
A _Provider Handler_ is just a module that defines a function of arity 2 that takes the request to handle and a `Lexical.Server.Provider.Env`. These functions can reply to the request, ignore it, or do some other action. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Glossary | ||
This project uses a considerable amount of jargon, some adopted from the Language Server Protocol and some specific to Lexical. | ||
|
||
This glossary attempts to define jargon used in this codebase. | ||
Though it is not exhaustive, we hope it helps contributors more easily navigate and understand existing code and the goal, and that it provides some guidance for naming new things. | ||
|
||
**You can help!** If you run across a new term while working on Lexical and you think it should be defined here, please [open an issue](https://github.com/lexical-lsp/lexical/issues) suggesting it! | ||
|
||
## Language Server Protocol (LSP) | ||
|
||
This section covers features, names, and abstractions used by Lexical that have a correspondence to the Language Server Protocol. For a definitive reference, see the [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/specification-current). | ||
|
||
### Messages, Requests, Responses, and Notifications | ||
|
||
LSP defines a general heirarchy of the types of messages langauge servers and clients and may exchange, and the expected behaviours associated with them. | ||
|
||
There's 3 top-level types of messages: [Requests](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage), [Responses](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#responseMessage), and [Notifications](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage): | ||
|
||
- [Requests](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage) are sent from client to server and vice versa, and must always be answered with a [Response](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#responseMessage). | ||
|
||
- [Notifications](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage) are likewise bi-directional and work like events. They expressly do not receive responses per LSP's specification. | ||
|
||
From these 3 top-level types, LSP defines more specific more concrete, actionable messages such as: | ||
- [Completion Requests](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion) | ||
- [Goto Definition Requests](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition) | ||
- [WillSaveTextDocument Notifications](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_willSave) | ||
|
||
... and many more. These can serve as good reference for the specific features you're working on. | ||
|
||
Lexical maps these in the modules [`Lexical.Protocol.Requests`](https://github.com/lexical-lsp/lexical/blob/main/apps/protocol/lib/lexical/protocol/requests.ex), [`Lexical.Protocol.Responses`](https://github.com/lexical-lsp/lexical/blob/main/apps/protocol/lib/lexical/protocol/responses.ex), and[ `Lexical.Protocol.Notifications`](https://github.com/lexical-lsp/lexical/blob/main/apps/protocol/lib/lexical/protocol/notifications.ex). | ||
|
||
Finally, it's worth noting all messages are JSON, specifically [JSON-RPC version 2.0](https://www.jsonrpc.org/specification). | ||
|
||
### Document(s) | ||
|
||
A single file identified by a URI and contains textual content. Formally referred to as [Text Documents](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocuments) in LSP and modeled as [`Lexical.Document`](https://github.com/lexical-lsp/lexical/blob/main/projects/lexical_shared/lib/lexical/document.ex) structs in Lexical. | ||
|
||
### Diagnostics | ||
|
||
Represents a diagnostic, such as a compiler error or warning. Diagnostic objects are only valid in the scope of a resource. | ||
|
||
### Completions and Code Intelligence | ||
|
||
Auto-completion suggestions that appear in an editor's IntelliSense. For example, a user that's typed `IO.in|` may be suggested `IO.inspect(|)` as one of a few possible completions. | ||
|
||
### Code Actions | ||
|
||
A code action represents a change that can be performed in code. In VSCode they typically appear as "quick fixes" next to an error or warning, but they aren't exclusive to that. In fact, VSCode frequently requests available code actions while users are browsing and editing code. | ||
|
||
LSP defines a protocol for language servers to tell clients what actions they're capable of performing, and for clients to request those actions be taken. See for example LSP's [CodeActionClientCapabilities interface](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#codeActionClientCapabilities). | ||
|
||
## Concepts exclusive to Lexical | ||
|
||
This section briefly summarizes abstractions introduced by Lexical. Detailed information can be found in the respective moduledocs. | ||
|
||
### The Project struct | ||
|
||
An Elixir struct that represents the current state of an elixir project. See `Lexical.Project`. | ||
|
||
### The Convertible protocol | ||
|
||
Some LSP data structures cannot be trivially converted to Elixir terms. | ||
|
||
The `Lexical.Convertible` protocol helps centralize the necessary conversion logic where this is the case. | ||
|
||
### The Transport Behaviour | ||
|
||
A behaviour responsible for reading, writing, serializing, and deserializing messages between the LSP client and Lexical language server. | ||
|
||
The behaviour is defined in `Lexical.Server.Transport`, with the implementation for stdio in `Lexical.Server.Transport.StdIO`. | ||
|
||
### The Translatable protocol and Translation modules | ||
|
||
The `Lexical.Completion.Translatable` protocol specifies how Elixir language constructs (such as behaviour callbacks) are converted into LSP constructs (such as [completion items](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItem)). | ||
|
||
See `Lexical.Server.CodeIntelligence.Completion.Translations` for various implementations. | ||
|
||
### Code Mods | ||
|
||
A variety of modules that change existing code in some way. They take a document, modify it, and return diffs. | ||
|
||
Examples of code mods include: | ||
* Formatting code in a file (`> Format Document`/`shift`+`alt`+`f` in VSCode). | ||
* Prefixing unused variables with an `_`. | ||
|
||
Code mods are defined in the `remote_control` sub-app and are executed in the project's virutal machine. |