Skip to content

Commit

Permalink
docs: Getting started documentation
Browse files Browse the repository at this point in the history
Fixes #24

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Dec 8, 2023
1 parent 6b6e01d commit 6410051
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 3 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ LSP4IJ provides:
* `com.redhat.devtools.lsp4ij.languageMapping` to associate an Intellij language with a language server definition.
* an `LSP Consoles view` to tracks LSP requests, responses and notifications in a console:

![LSP console](https://github.com/redhat-developer/lsp4ij/blob/HEAD/docs/images/LSPConsole.png?raw=true)
![LSP console](./docs/images/LSPConsole.png?raw=true)

* a `Language Servers settings page` to configure the LSP trace level, the debug port to use to debug language server:

![Language Server settings](https://github.com/redhat-developer/lsp4ij/blob/HEAD/docs/images/LanguageServerSettings.png?raw=true)
![Language Server settings](./docs/images/LanguageServerSettings.png?raw=true)

You can start with [Getting started](./docs/GettingStarted.md)

<!-- Plugin description end -->

## Who is using LSP4IJ?
Expand Down
157 changes: 157 additions & 0 deletions docs/GettingStarted.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Getting started

This section explains step by step how to add your own LSP language server in your IntelliJ plugin.

## Reference LSP4IJ

### plugin.xml

The first step is to reference LSP4IJ. LSP4IJ uses `com.redhat.devtools.lsp4ij` as plugin Id.

You need [to declare dependency in your plugin.xml](https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html#3-dependency-declaration-in-pluginxml) like this:

```xml
<idea-plugin>
...

<depends>com.redhat.devtools.lsp4ij</depends>

...
</idea-plugin>
```

### Exclude all LSP4J dependencies

LSP4IJ depends on [Eclipse LSP4J](https://github.com/eclipse-lsp4j/lsp4j) (Java binding for the [Language Server Protocol](https://microsoft.github.io/language-server-protocol) and the [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol).). It uses a given version of LSPJ and their classes are loaded in the LSP4IJ plugin class loader.

Your IntelliJ Plugin should use `the same LSP4J classes than LSP4IJ` to avoid some `ClassCastException` errors. To do that you need to `exclude all LSP4J dependencies` from your plugin.

Here a sample used in [Quarkus Tools](https://github.com/redhat-developer/intellij-quarkus) in [build.gradle.kts](https://github.com/redhat-developer/intellij-quarkus/blob/main/build.gradle.kts) to exclude LSP4J dependency from the [Qute Language Server](https://github.com/redhat-developer/quarkus-ls/tree/master/qute.ls) which have a dependency to LSP4J:

```
implementation("com.redhat.microprofile:com.redhat.qute.ls:0.17.0) {
exclude("org.eclipse.lsp4j")
}
```

## Declare server


### StreamConnectionProvider Implementation

You need to implement the [StreamConnectionProvider](https://github.com/redhat-developer/lsp4ij/blob/main/src/main/java/com/redhat/devtools/lsp4ij/server/StreamConnectionProvider.java) API which manages:

* start of your language server
* returns the input/error stream of LSP requests, responses, notifications.

Generally, the language server is started with a process by using a runtime like Java, NodeJS, etc. In this case you need to extend [ProcessStreamConnectionProvider](https://github.com/redhat-developer/lsp4ij/blob/main/src/main/java/com/redhat/devtools/lsp4ij/server/ProcessStreamConnectionProvider.java)

Here a basic sample which starts the `path/to/my/language/server/main.js` language server written in JavaScript with NodeJS runtime "path/to/nodejs/node.exe":

```java
package my.language.server;

import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider;

import java.util.Arrays;
import java.util.List;

public class MyLanguageServer extends ProcessStreamConnectionProvider {

public MyLanguageServer() {
List<String> commands = Arrays.asList("path/to/nodejs/node.exe", "path/to/my/language/server/main.js");
super.setCommands(commands);
}
}
```

If your language server is written in Java, to build the command, you can use [JavaProcessCommandBuilder](https://github.com/redhat-developer/lsp4ij/blob/main/src/main/java/com/redhat/devtools/lsp4ij/server/JavaProcessCommandBuilder.java):

```java
package my.language.server;

import com.intellij.openapi.project.Project;
import com.redhat.devtools.lsp4ij.server.JavaProcessCommandBuilder;
import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider;

import java.util.Arrays;
import java.util.List;

public class MyLanguageServer extends ProcessStreamConnectionProvider {

public MyLanguageServer(Project project) {
List<String> commands = new JavaProcessCommandBuilder(project, "myLanguageServerId")
.setJar("path/to/my/language/server/main.java")
.create();
super.setCommands(commands);
}
}
```

This builder takes care of filling command with Java runtime and generate the command with debug if the settings of the language server `myLanguageServerId` defines a debug port.

You can see a full sample with [QuteServer](https://github.com/redhat-developer/intellij-quarkus/blob/main/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java)

### LanguageClientImpl

It is not required but you can override the [LanguageClientImpl](https://github.com/redhat-developer/lsp4ij/blob/main/src/main/java/com/redhat/devtools/lsp4ij/client/LanguageClientImpl.java) to for instance:

* some IJ listeners when language client is created
* override some LSP methods

```java
package my.language.server;

import com.intellij.openapi.project.Project;
import com.redhat.devtools.lsp4ij.client.LanguageClientImpl;

public class MyLanguageClient extends LanguageClientImpl {
public MyLanguageClient(Project project) {
super(project);
}
}
```

If your language server manages custom LSP requests, it is advised to extend [IndexAwareLanguageClient](https://github.com/redhat-developer/lsp4ij/blob/main/src/main/java/com/redhat/devtools/lsp4ij/client/IndexAwareLanguageClient.java)

You can see a full sample with [QuteLanguageClient](https://github.com/redhat-developer/intellij-quarkus/blob/main/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteLanguageClient.java)

## Declare server with extension point

The last step is to declare the server in your plugin.xml to use your `my.language.server.MyLanguageServer` and `my.language.server.MyLanguageClient`:

```
<idea-plugin>
<extensions defaultExtensionNs="com.redhat.devtools.lsp4ij">
<server id="myLanguageServerId"
label="My Language Server"
class="my.language.server.MyLanguageServer"
clientImpl="my.language.server.MyLanguageClient"
scope="project">
<description><![CDATA[
Some description written in HTML to display it in LSP consoles and Language Servers settings.
]]>
</description>
</server>
</extensions>
</idea-plugin>
```

Once the declaration is done, your server should appear in the LSP console:

![My LanguageServer in LSP Console](./images/MyLanguageServerInLSPConsole.png)

## Declare language mapping with extension point

TODO
* declare mapping
* DocumentMatcher

## Declare IJ features

* externalAnnotator, completion, etc are declared an language any with LSP4IJ => nothing to do
* IJ inlayHint, hover doesn't support any language, so you need to declare them in you plugin.xml


Binary file added docs/images/MyLanguageServerInLSPConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</change-notes>
<description>
<![CDATA[
<p>LSP4IJ is a free and open-source <a href="https://microsoft.github.io/language-server-protocol/">Language Server protocol (LSP)</a> client compatible with all flavors of IntelliJ.</p>
<p><a href="https://github.com/redhat-developer/lsp4ij" >LSP4IJ</a> is a free and open-source <a href="https://microsoft.github.io/language-server-protocol/">Language Server protocol (LSP)</a> client compatible with all flavors of IntelliJ.</p>
<p>It currently doesn't provide any useful functionality on its own but is instead used as a dependency for other extensions, willing to integrate language servers with IntelliJ products.</p>
Expand All @@ -29,6 +29,8 @@
<li>An <code>LSP Consoles view</code> to track LSP requests, responses, and notifications in a console.</li>
<li>A <code>Language Servers settings page</code> to configure the LSP trace level and the debug port to use to debug the language server.</li>
</ul>
<p>You can start with <a href="https://github.com/redhat-developer/lsp4ij/blob/main/docs/GettingStarted.md">Getting started</a></p>
]]>
</description>

Expand Down

0 comments on commit 6410051

Please sign in to comment.