UNPKG

10.3 kBMarkdownView Raw
1# Atom Language Server Protocol Client
2
3[![Build Status](https://github.com/atom-ide-community/atom-languageclient/workflows/CI/badge.svg)](https://github.com/atom-ide-community/atom-languageclient/actions) [![Dependency Status](https://david-dm.org/atom-ide-community/atom-languageclient.svg)](https://david-dm.org/atom-ide-community/atom-languageclient)
4
5This repo was moved from [atom/atom-languageclient](https://github.com/atom/atom-languageclient)
6
7Provide integration support for adding Language Server Protocol servers to Atom.
8
9## Background
10
11[Language Server Protocol (LSP)](https://microsoft.github.io/language-server-protocol/) is a JSON-RPC based mechanism whereby a client (IDE) may connect to an out-of-process server that can provide rich analysis, refactoring and interactive features for a given programming language.
12
13## Implementation
14
15This npm package can be used by Atom package authors wanting to integrate LSP-compatible language servers with Atom. It provides:
16
17- Conversion routines between Atom and LSP types
18- A TypeScript wrapper around JSON-RPC for **v3** of the LSP protocol
19- All necessary TypeScript input and return structures for LSP, notifications etc.
20- A number of adapters to translate communication between Atom/Atom-IDE and the LSP's capabilities
21- Automatic wiring up of adapters based on the negotiated capabilities of the language server
22- Helper functions for downloading additional non-npm dependencies
23
24## Capabilities
25
26The language server protocol consists of a number of capabilities. Some of these already have a counterpoint we can connect up to today while others do not. The following table shows each capability in v2 and how it is exposed via Atom;
27
28| Capability | Atom interface |
29| --------------------------------- | --------------------------- |
30| window/showMessage | Notifications package |
31| window/showMessageRequest | Notifications package |
32| window/logMessage | Atom-IDE console |
33| telemetry/event | Ignored |
34| workspace/didChangeWatchedFiles | Atom file watch API |
35| textDocument/publishDiagnostics | Linter v2 push/indie |
36| textDocument/completion | AutoComplete+ |
37| completionItem/resolve | AutoComplete+ (Atom 1.24+) |
38| textDocument/hover | Atom-IDE data tips |
39| textDocument/signatureHelp | Atom-IDE signature help |
40| textDocument/definition | Atom-IDE definitions |
41| textDocument/findReferences | Atom-IDE findReferences |
42| textDocument/documentHighlight | Atom-IDE code highlights |
43| textDocument/documentSymbol | Atom-IDE outline view |
44| workspace/symbol | TBD |
45| textDocument/codeAction | Atom-IDE code actions |
46| textDocument/codeLens | TBD |
47| textDocument/formatting | Format File command |
48| textDocument/rangeFormatting | Format Selection command |
49| textDocument/onTypeFormatting | Atom-IDE on type formatting |
50| textDocument/onSaveFormatting | Atom-IDE on save formatting |
51| textDocument/prepareCallHierarchy | Atom-IDE outline view |
52| textDocument/rename | TBD |
53| textDocument/didChange | Send on save |
54| textDocument/didOpen | Send on open |
55| textDocument/didSave | Send after save |
56| textDocument/willSave | Send before save |
57| textDocument/didClose | Send on close |
58
59## Developing packages
60
61The underlying JSON-RPC communication is handled by the [vscode-jsonrpc npm module](https://www.npmjs.com/package/vscode-jsonrpc).
62
63### Minimal example (Nodejs-compatible LSP exe)
64
65A minimal implementation can be illustrated by the Omnisharp package here which has only npm-managed dependencies, and the LSP is a JavaScript file. You simply provide the scope name, language name and server name as well as start your process and `AutoLanguageClient` takes care of interrogating your language server capabilities and wiring up the appropriate services within Atom to expose them.
66
67```javascript
68const { AutoLanguageClient } = require("atom-languageclient")
69
70class CSharpLanguageClient extends AutoLanguageClient {
71 getGrammarScopes() {
72 return ["source.cs"]
73 }
74 getLanguageName() {
75 return "C#"
76 }
77 getServerName() {
78 return "OmniSharp"
79 }
80
81 startServerProcess() {
82 return super.spawnChildNode([require.resolve("omnisharp-client/languageserver/server")])
83 }
84}
85
86module.exports = new CSharpLanguageClient()
87```
88
89You can get this code packaged up with the necessary package.json etc. from the [ide-csharp](https://github.com/atom/ide-csharp) provides C# support via [Omnisharp (node-omnisharp)](https://github.com/OmniSharp/omnisharp-node-client) repo.
90
91Note that you will also need to add various entries to the `providedServices` and `consumedServices` section of your package.json (for now). You can [obtain these entries here](https://github.com/atom/ide-csharp/tree/master/package.json).
92
93### Minimal example (General LSP exe)
94
95If the LSP is a general executable (not a JavaScript file), you should use `spawn` inside `startServerProcess`.
96
97```javascript
98const { AutoLanguageClient } = require("atom-languageclient")
99
100class DLanguageClient extends AutoLanguageClient {
101 getGrammarScopes() {
102 return ["source.d"]
103 }
104 getLanguageName() {
105 return "D"
106 }
107 getServerName() {
108 return "serve-d"
109 }
110
111 startServerProcess(projectPath) {
112 return super.spawn(
113 "serve-d", // the `name` or `path` of the executable
114 // if the `name` is provided it checks `bin/platform-arch/exeName` by default, and if doesn't exists uses the `exeName` on the PATH
115 [], // args passed to spawn the exe
116 { cwd: projectPath } // child process spawn options
117 )
118 }
119}
120
121module.exports = new DLanguageClient()
122```
123
124### Using other connection types
125
126The default connection type is _stdio_ however both _ipc_ and _sockets_ are also available.
127
128#### IPC
129
130To use ipc simply return _ipc_ from getConnectionType(), e.g.
131
132```javascript
133class ExampleLanguageClient extends AutoLanguageClient {
134 getGrammarScopes() {
135 return ["source.js", "javascript"]
136 }
137 getLanguageName() {
138 return "JavaScript"
139 }
140 getServerName() {
141 return "JavaScript Language Server"
142 }
143
144 getConnectionType() {
145 return "ipc"
146 }
147
148 startServerProcess() {
149 const startServer = require.resolve("@example/js-language-server")
150 return super.spawnChildNode([startServer, "--node-ipc"], {
151 stdio: [null, null, null, "ipc"],
152 })
153 }
154}
155```
156
157#### Sockets
158
159Sockets are a little more complex because you need to allocate a free socket. The [ide-php package](https://github.com/atom/ide-php/blob/master/lib/main.js) contains an example of this.
160
161### Debugging
162
163Atom-LanguageClient can log all sent and received messages nicely formatted to the Developer Tools Console within Atom. To do so simply enable it with `atom.config.set('core.debugLSP', true)`, e.g.
164
165### Tips
166
167Some more elaborate scenarios can be found in the [ide-java](https://github.com/atom/ide-java) package which includes:
168
169- Downloading and unpacking non-npm dependencies (in this case a .tar.gz containing JAR files)
170- Platform-specific start-up configuration
171- Wiring up custom extensions to the protocol (language/status to Atom Status-Bar, language/actionableNotification to Atom Notifications)
172
173### Available packages
174
175Right now we have the following experimental Atom LSP packages in development. They are mostly usable but are missing some features that either the LSP server doesn't support or expose functionality that is as yet unmapped to Atom (TODO and TBD in the capabilities table above).
176
177### Official packages
178
179- [ide-csharp](https://github.com/atom/ide-csharp) provides C# support via [Omnisharp (node-omnisharp)](https://github.com/OmniSharp/omnisharp-node-client)
180- [ide-flowtype](https://github.com/flowtype/ide-flowtype) provides Flow support via [Flow Language Server](https://github.com/flowtype/flow-language-server)
181- [ide-java](https://github.com/atom/ide-java) provides Java support via [Java Eclipse JDT](https://github.com/eclipse/eclipse.jdt.ls)
182- [ide-typescript](https://github.com/atom/ide-typescript) provides TypeScript and Javascript support via [SourceGraph Typescript Language Server](https://github.com/sourcegraph/javascript-typescript-langserver)
183
184### Community packages
185
186Our [full list of Atom IDE packages](https://github.com/atom-ide-community/atom-languageclient/wiki/List-of-Atom-packages-using-Atom-LanguageClient) includes the community packages.
187
188### Other language servers
189
190Additional LSP servers that might be of interest to be packaged with this for Atom can be found at [LangServer.org](http://langserver.org)
191
192## Contributing
193
194### Running from source
195
196If you want to run from source you will need to perform the following steps (you will need node and npm intalled):
197
1981. Check out the source
1992. From the source folder type `npm link` to build and link
2003. From the folder where your package lives type `npm link atom-languageclient`
201
202If you want to switch back to the production version of atom-languageclient type `npm unlink atom-languageclient` from the folder where your package lives.
203
204### Before sending a PR
205
206We have various unit tests and some linter rules - you can run both of these locally using `npm test` to ensure your CI will get a clean build.
207
208### Guidance
209
210Always feel free to help out! Whether it's [filing bugs and feature requests](https://github.com/atom-ide-community/atom-languageclient/issues/new) or working on some of the [open issues](https://github.com/atom-ide-community/atom-languageclient/issues), Atom's [contributing guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md) will help get you started while the [guide for contributing to packages](https://github.com/atom/atom/blob/master/docs/contributing-to-packages.md) has some extra information.
211
212## License
213
214MIT License. See [the license](LICENSE.md) for more details.