Skip to content

Commit

Permalink
feat: provide LSP API support
Browse files Browse the repository at this point in the history
Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Sep 27, 2024
1 parent ae5a957 commit 8172067
Show file tree
Hide file tree
Showing 14 changed files with 565 additions and 179 deletions.
93 changes: 93 additions & 0 deletions docs/LSPApi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# LSP server support

The LSPCustomizedServerSupport API allows customizing the behavior of LSP features to customize:

* [LSP completion support](#customize-lsp-completion-support)
* [LSP diagnostic support](#customize-lsp-diagnostic-support)
* [LSP formatting support](#customize-lsp-formatting-support)

These custom supports are done:

* by extending the default classes `LSPCustomized*Support` (e.g. creating a new class `MyLSPCustomizedFormattingSupport` that extends
[LSPCustomizedFormattingSupport](https://github.com/redhat-developer/lsp4ij/blob/main/src/main/java/com/redhat/devtools/lsp4ij/server/customization/LSPCustomizedFormattingSupport.java) to customize formatting support)
and overriding some methods to customize the behavior.
* registering your custom classes with `LanguageServerFactory#createServerSupport(@NotNull Project)`:

```java
package my.language.server;

import com.intellij.openapi.project.Project;
import com.redhat.devtools.lsp4ij.LanguageServerFactory;
import com.redhat.devtools.lsp4ij.client.features.LSPCustomizedServerSupport;
import org.jetbrains.annotations.NotNull;

public class MyLanguageServerFactory implements LanguageServerFactory {

@Override
public @NotNull LSPCustomizedServerSupport createServerSupport(@NotNull Project project) {
return new LSPCustomizedServerSupport(project)
.withCompletionSupport(new MyLSPCustomizedCompletionSupport()) // customize LSP completion support
.withDiagnosticSupport(new MyLSPCustomizedDiagnosticSupport()) // customize LSP diagnostic support
.withFormattingSupport(new MyLSPCustomizedFormattingSupport()); // customize LSP formatting support
}
}
```

## Customize LSP completion support

TODO

## Customize LSP diagnostic support

Here is an example of code that avoids creating an IntelliJ annotation when the LSP diagnostic code is equal to `ignore`:

```java
package my.language.server;

import com.intellij.lang.annotation.HighlightSeverity;
import com.redhat.devtools.lsp4ij.client.features.LSPCustomizedDiagnosticSupport;
import org.eclipse.lsp4j.Diagnostic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class MyLSPCustomizedDiagnosticSupport extends LSPCustomizedDiagnosticSupport {

@Override
public @Nullable HighlightSeverity getHighlightSeverity(@NotNull Diagnostic diagnostic) {
if (diagnostic.getCode() != null &&
diagnostic.getCode().isLeft() &&
"ignore".equals(diagnostic.getCode().getLeft())) {
// return a null HighlightSeverity when LSP diagnostic code is equals
// to 'ignore' to avoid creating an IntelliJ annotation
return null;
}
return super.getHighlightSeverity(diagnostic);
}

}
```

## Customize LSP formatting support

Here is an example of code that allows to execute the LSP formatter even if there is a specific formatter registered by an IntelliJ plugin

TODO: revisit this API to manage range formatting too.

```java
package my.language.server;

import com.intellij.psi.PsiFile;
import com.redhat.devtools.lsp4ij.client.features.LSPCustomizedFormattingSupport;
import com.redhat.devtools.lsp4ij.client.features.LSPCustomizedServerSupport;
import org.jetbrains.annotations.NotNull;

public class MyLSPCustomizedFormattingSupport extends LSPCustomizedFormattingSupport {

@Override
public boolean canSupportFormatting(@NotNull PsiFile file, boolean hasCustomFormatter) {
// By default, LSPCustomizedFormattingSupport return false if it has custom formatter with psi
// returns true even if there is custom formatter
return true;
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.intellij.openapi.project.Project;
import com.redhat.devtools.lsp4ij.client.LanguageClientImpl;
import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider;
import com.redhat.devtools.lsp4ij.client.features.LSPServerFeatures;
import org.eclipse.lsp4j.services.LanguageServer;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -50,4 +51,7 @@ public interface LanguageServerFactory {
return LanguageServer.class;
}

@NotNull default LSPServerFeatures createServerSupport(@NotNull Project project) {
return new LSPServerFeatures(project);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.redhat.devtools.lsp4ij.lifecycle.LanguageServerLifecycleManager;
import com.redhat.devtools.lsp4ij.lifecycle.NullLanguageServerLifecycleManager;
import com.redhat.devtools.lsp4ij.server.*;
import com.redhat.devtools.lsp4ij.client.features.LSPServerFeatures;
import com.redhat.devtools.lsp4ij.server.definition.LanguageServerDefinition;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.Launcher;
Expand Down Expand Up @@ -108,6 +109,8 @@ public class LanguageServerWrapper implements Disposable {

private FileOperationsManager fileOperationsManager;

private LSPServerFeatures serverSupport;

/* Backwards compatible constructor */
public LanguageServerWrapper(@NotNull Project project, @NotNull LanguageServerDefinition serverDefinition) {
this(project, serverDefinition, null);
Expand Down Expand Up @@ -1174,4 +1177,11 @@ public boolean isSignatureTriggerCharactersSupported(String charTyped) {
}
return triggerCharacters.contains(charTyped);
}

public LSPServerFeatures getServerSupport() {
if (serverSupport == null) {
serverSupport = getServerDefinition().createServerSupport(getProject());
}
return serverSupport;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.lsp4ij.client.features;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

/**
* Abstract class for any LSP customization feature support.
*/
@ApiStatus.Experimental
public abstract class AbstractLSPFeature {

private LSPServerFeatures serverSupport;

/**
* Returns the LSP server support.
*
* @return the LSP server support.
*/
public @NotNull LSPServerFeatures getServerSupport() {
return serverSupport;
}

/**
* Set the LSP server support.
*
* @param serverSupport the LSP server support.
*/
public void setServerSupport(@NotNull LSPServerFeatures serverSupport) {
this.serverSupport = serverSupport;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.lsp4ij.client.features;

import org.jetbrains.annotations.ApiStatus;

/**
* LSP customization completion support.
*/
@ApiStatus.Experimental
public class LSPCompletionFeature extends AbstractLSPFeature {

}
Loading

0 comments on commit 8172067

Please sign in to comment.