From 5f2d875af3fe4d8e80910b5563a809ee125b4ba6 Mon Sep 17 00:00:00 2001
From: azerr
Date: Sat, 5 Oct 2024 14:45:01 +0200
Subject: [PATCH] feat: Support documentSelector in registerCapability
Fixes #517
Signed-off-by: azerr
---
.../lsp4ij/DocumentContentSynchronizer.java | 58 +--
.../redhat/devtools/lsp4ij/LSPIJUtils.java | 17 -
.../devtools/lsp4ij/LanguageServerItem.java | 385 ------------------
.../lsp4ij/LanguageServerWrapper.java | 113 ++---
.../features/AbstractLSPDocumentFeature.java | 1 -
.../client/features/AbstractLSPFeature.java | 3 +
.../client/features/LSPClientFeatures.java | 185 ++++++++-
.../client/features/LSPCodeActionFeature.java | 37 +-
.../client/features/LSPCodeLensFeature.java | 64 +--
.../client/features/LSPColorFeature.java | 39 --
.../client/features/LSPCompletionFeature.java | 33 +-
.../features/LSPDeclarationFeature.java | 29 +-
.../client/features/LSPDefinitionFeature.java | 29 +-
.../client/features/LSPDiagnosticFeature.java | 4 +
.../features/LSPDocumentColorFeature.java | 58 +++
.../features/LSPDocumentHighlightFeature.java | 28 +-
.../features/LSPDocumentLinkFeature.java | 25 +-
.../features/LSPDocumentSymbolFeature.java | 24 +-
.../features/LSPFoldingRangeFeature.java | 29 +-
.../client/features/LSPFormattingFeature.java | 48 ++-
.../client/features/LSPHoverFeature.java | 42 +-
.../features/LSPImplementationFeature.java | 26 +-
.../client/features/LSPInlayHintFeature.java | 42 +-
.../client/features/LSPReferencesFeature.java | 26 +-
.../client/features/LSPRenameFeature.java | 38 +-
.../features/LSPSemanticTokensFeature.java | 12 +-
.../features/LSPSignatureHelpFeature.java | 28 +-
.../features/LSPTypeDefinitionFeature.java | 25 +-
.../client/features/LSPUsageFeature.java | 16 +-
.../features/LSPWorkspaceSymbolFeature.java | 14 +-
.../features/AbstractLSPGoToAction.java | 10 +-
.../LSPLazyCodeActionIntentionAction.java | 4 +-
.../features/codeLens/LSPCodeLensSupport.java | 11 +-
.../features/color/LSPColorSupport.java | 4 +-
.../declaration/LSPGoToDeclarationAction.java | 8 +-
.../diagnostics/LSPDiagnosticAnnotator.java | 2 +-
.../diagnostics/LSPDiagnosticsForServer.java | 13 +-
.../LSPFormattingAndRangeBothService.java | 2 +-
.../formatting/LSPFormattingOnlyService.java | 4 +-
.../formatting/LSPFormattingSupport.java | 6 +-
.../LSPGoToImplementationAction.java | 8 +-
.../inlayhint/LSPInlayHintsProvider.java | 2 +-
.../inlayhint/LSPInlayHintsSupport.java | 9 +-
.../references/LSPGoToReferenceAction.java | 10 +-
.../features/rename/LSPRenameHandler.java | 2 +-
.../LSPGoToTypeDefinitionAction.java | 8 +-
.../internal/ClientCapabilitiesFactory.java | 48 +--
.../CodeActionCapabilityRegistry.java | 90 ++++
.../CodeLensCapabilityRegistry.java | 82 ++++
.../CompletionCapabilityRegistry.java | 82 ++++
.../DeclarationCapabilityRegistry.java | 66 +++
.../DefinitionCapabilityRegistry.java | 66 +++
.../DocumentColorCapabilityRegistry.java | 66 +++
.../DocumentFormattingCapabilityRegistry.java | 66 +++
.../DocumentHighlightCapabilityRegistry.java | 67 +++
.../DocumentLinkCapabilityRegistry.java | 66 +++
...mentRangeFormattingCapabilityRegistry.java | 67 +++
.../DocumentSymbolCapabilityRegistry.java | 66 +++
.../ExtendedDocumentSelector.java | 71 ++++
.../FoldingRangeCapabilityRegistry.java | 66 +++
.../capabilities/HoverCapabilityRegistry.java | 66 +++
.../ImplementationCapabilityRegistry.java | 66 +++
.../InlayHintCapabilityRegistry.java | 87 ++++
.../ReferencesCapabilityRegistry.java | 66 +++
.../RenameCapabilityRegistry.java | 87 ++++
.../SignatureHelpCapabilityRegistry.java | 66 +++
.../TextDocumentServerCapabilityRegistry.java | 149 +++++++
.../TypeDefinitionCapabilityRegistry.java | 66 +++
.../definition/LanguageServerDefinition.java | 166 +++++++-
.../lsp4ij/usages/LSPUsageSupport.java | 11 +-
70 files changed, 2576 insertions(+), 804 deletions(-)
delete mode 100644 src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPColorFeature.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDocumentColorFeature.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CodeActionCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CodeLensCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CompletionCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DeclarationCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DefinitionCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentColorCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentFormattingCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentHighlightCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentLinkCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentRangeFormattingCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentSymbolCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ExtendedDocumentSelector.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/FoldingRangeCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/HoverCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ImplementationCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/InlayHintCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ReferencesCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/RenameCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/SignatureHelpCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/TextDocumentServerCapabilityRegistry.java
create mode 100644 src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/TypeDefinitionCapabilityRegistry.java
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/DocumentContentSynchronizer.java b/src/main/java/com/redhat/devtools/lsp4ij/DocumentContentSynchronizer.java
index 9b22ad5b1..89a110ac0 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/DocumentContentSynchronizer.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/DocumentContentSynchronizer.java
@@ -10,20 +10,17 @@
******************************************************************************/
package com.redhat.devtools.lsp4ij;
-import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.net.URI;
import java.util.ArrayList;
@@ -50,8 +47,9 @@ public class DocumentContentSynchronizer implements DocumentListener {
public DocumentContentSynchronizer(@NotNull LanguageServerWrapper languageServerWrapper,
@NotNull URI fileUri,
+ @NotNull VirtualFile file,
@NotNull Document document,
- TextDocumentSyncKind syncKind) {
+ @Nullable TextDocumentSyncKind syncKind) {
this.languageServerWrapper = languageServerWrapper;
this.fileUri = fileUri.toASCIIString();
this.syncKind = syncKind != null ? syncKind : TextDocumentSyncKind.Full;
@@ -62,7 +60,7 @@ public DocumentContentSynchronizer(@NotNull LanguageServerWrapper languageServer
textDocument.setUri(this.fileUri);
textDocument.setText(document.getText());
- @NotNull String languageId = getLanguageId(document, languageServerWrapper);
+ @NotNull String languageId = languageServerWrapper.getServerDefinition().getLanguageId(file, languageServerWrapper.getProject());
textDocument.setLanguageId(languageId);
textDocument.setVersion(++version);
didOpenFuture = languageServerWrapper
@@ -89,54 +87,6 @@ public DocumentContentSynchronizer(@NotNull LanguageServerWrapper languageServer
changeEvents = new ArrayList<>();
}
- /**
- * Returns the LSP language id defined in mapping otherwise the {@link Language#getID()} otherwise the {@link FileType#getName()} otherwise 'unknown'.
- *
- * @param document the document.
- * @param languageServer the language server.
- * @return the LSP language id.
- */
- private static @NotNull String getLanguageId(@NotNull Document document, @NotNull LanguageServerWrapper languageServer) {
- VirtualFile file = FileDocumentManager.getInstance().getFile(document);
- if (file == null) {
- return FileTypes.UNKNOWN.getName().toLowerCase();
- }
-
- Project project = languageServer.getProject();
-
- // 1. Try to get the LSP languageId by using language mapping
- Language language = LSPIJUtils.getFileLanguage(file, project);
- String languageId = languageServer.getLanguageId(language);
- if (languageId != null) {
- return languageId;
- }
-
- // 2. Try to get the LSP languageId by using the fileType mapping
- FileType fileType = file.getFileType();
- languageId = languageServer.getLanguageId(fileType);
- if (languageId != null) {
- return languageId;
- }
-
- // 3. Try to get the LSP languageId by using the file name pattern mapping
- languageId = languageServer.getLanguageId(file.getName());
- if (languageId != null) {
- return languageId;
- }
-
- // At this step there is no mapping
-
- // We return the language Id if it exists or file type name
- // with 'lower case' to try to map the recommended languageId specified at
- // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem
- if (language != null) {
- // The language exists, use its ID with lower case
- return language.getID().toLowerCase();
- }
- // Returns the existing file type or 'unknown' with lower case
- return file.getName().toLowerCase();
- }
-
@Override
public void documentChanged(@NotNull DocumentEvent event) {
DocumentListener.super.documentChanged(event);
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/LSPIJUtils.java b/src/main/java/com/redhat/devtools/lsp4ij/LSPIJUtils.java
index 80dc64844..f744e274c 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/LSPIJUtils.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/LSPIJUtils.java
@@ -321,23 +321,6 @@ private static Language doGetFileLanguage(@NotNull VirtualFile file, @NotNull Pr
return LanguageUtil.getLanguageForPsi(project, file);
}
- private static T toTextDocumentPositionParamsCommon(T param, int offset, Document document) {
- Position start = toPosition(offset, document);
- param.setPosition(start);
- TextDocumentIdentifier id = new TextDocumentIdentifier();
- URI uri = toUri(document);
- if (uri != null) {
- id.setUri(uri.toASCIIString());
- }
- param.setTextDocument(id);
- return param;
- }
-
- public static HoverParams toHoverParams(int offset, Document document) {
- return toTextDocumentPositionParamsCommon(new HoverParams(), offset, document);
- }
-
-
/**
* Returns the Uri of the virtual file corresponding to the specified document.
*
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/LanguageServerItem.java b/src/main/java/com/redhat/devtools/lsp4ij/LanguageServerItem.java
index 36845cb7a..7f0516d11 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/LanguageServerItem.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/LanguageServerItem.java
@@ -112,96 +112,6 @@ public ServerCapabilities getServerCapabilities() {
return serverCapabilities;
}
- /**
- * Returns true if the language server can support resolve completion and false otherwise.
- *
- * @return true if the language server can support resolve completion and false otherwise.
- */
- public boolean isResolveCompletionSupported() {
- return isResolveCompletionSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support signature help and false otherwise.
- *
- * @return true if the language server can support signature help and false otherwise.
- */
- public boolean isSignatureHelpSupported() {
- return isSignatureHelpSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support resolve code lens and false otherwise.
- *
- * @return true if the language server can support resolve code lens and false otherwise.
- */
- public boolean isResolveCodeLensSupported() {
- return isResolveCodeLensSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support resolve inlay hint and false otherwise.
- *
- * @return true if the language server can support resolve inlay hint and false otherwise.
- */
- public boolean isResolveInlayHintSupported() {
- return isResolveInlayHintSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support references and false otherwise.
- *
- * @return true if the language server can support references and false otherwise.
- */
- public boolean isReferencesSupported() {
- return isReferencesSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support implementation and false otherwise.
- *
- * @return true if the language server can support implementation and false otherwise.
- */
- public boolean isImplementationSupported() {
- return isImplementationSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support declaration and false otherwise.
- *
- * @return true if the language server can support declaration and false otherwise.
- */
- public boolean isDeclarationSupported() {
- return isDeclarationSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support definition and false otherwise.
- *
- * @return true if the language server can support definition and false otherwise.
- */
- public boolean isDefinitionSupported() {
- return isDefinitionSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support type definition and false otherwise.
- *
- * @return true if the language server can support type definition and false otherwise.
- */
- public boolean isTypeDefinitionSupported() {
- return isTypeDefinitionSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support formatting and false otherwise.
- *
- * @return true if the language server can support formatting and false otherwise.
- */
- public boolean isDocumentFormattingSupported() {
- return isDocumentFormattingSupported(getServerCapabilities());
- }
-
/**
* Returns true if the language server can support range formatting and false otherwise.
*
@@ -211,207 +121,6 @@ public boolean isDocumentRangeFormattingSupported() {
return isDocumentRangeFormattingSupported(getServerCapabilities());
}
- /**
- * Returns true if the language server can support completion and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support completion and false otherwise.
- */
- public static boolean isCompletionSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- serverCapabilities.getCompletionProvider() != null;
- }
-
- /**
- * Returns true if the language server can support resolve completion and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support resolve completion and false otherwise.
- */
- public static boolean isResolveCompletionSupported(@Nullable ServerCapabilities serverCapabilities) {
- var completionProvider = serverCapabilities != null ? serverCapabilities.getCompletionProvider() : null;
- return completionProvider != null && hasCapability(completionProvider.getResolveProvider());
- }
-
- /**
- * Returns true if the language server can support signature help and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support signature help and false otherwise.
- */
- public static boolean isSignatureHelpSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- serverCapabilities.getSignatureHelpProvider() != null;
- }
-
- /**
- * Returns true if the language server can support code lens and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support code lens and false otherwise.
- */
- public static boolean isCodeLensSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- serverCapabilities.getCodeLensProvider() != null;
- }
-
- /**
- * Returns true if the language server can support resolve code lens and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support resolve code lens and false otherwise.
- */
- public static boolean isResolveCodeLensSupported(@Nullable ServerCapabilities serverCapabilities) {
- var codeLensProvider = serverCapabilities != null ? serverCapabilities.getCodeLensProvider() : null;
- return codeLensProvider != null && hasCapability(codeLensProvider.getResolveProvider());
- }
-
- /**
- * Returns true if the language server can support inlay hint and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support inlay hint and false otherwise.
- */
- public static boolean isInlayHintSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getInlayHintProvider());
- }
-
- /**
- * Returns true if the language server can support resolve inlay hint and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support resolve inlay hint and false otherwise.
- */
- public static boolean isResolveInlayHintSupported(@Nullable ServerCapabilities serverCapabilities) {
- var inlayHintProvider = serverCapabilities != null ? serverCapabilities.getInlayHintProvider() : null;
- if (inlayHintProvider != null && inlayHintProvider.isRight()) {
- return hasCapability(inlayHintProvider.getRight().getResolveProvider());
- }
- return false;
- }
-
- /**
- * Returns true if the language server can support color and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support color and false otherwise.
- */
- public static boolean isColorSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getColorProvider());
- }
-
- /**
- * Returns true if the language server can support declaration and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support declaration and false otherwise.
- */
- public static boolean isDeclarationSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getDeclarationProvider());
- }
-
- /**
- * Returns true if the language server can support definition and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support definition and false otherwise.
- */
- public static boolean isDefinitionSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getDefinitionProvider());
- }
-
- /**
- * Returns true if the language server can support type definition and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support type definition and false otherwise.
- */
- public static boolean isTypeDefinitionSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getTypeDefinitionProvider());
- }
-
- /**
- * Returns true if the language server can support document highlight and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support document highlight and false otherwise.
- */
- public static boolean isDocumentHighlightSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getDocumentHighlightProvider());
- }
-
- /**
- * Returns true if the language server can support document link and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support document link and false otherwise.
- */
- public static boolean isDocumentLinkSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- serverCapabilities.getDocumentLinkProvider() != null;
- }
-
- /**
- * Returns true if the language server can support document link and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support document link and false otherwise.
- */
- public static boolean isHoverSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getHoverProvider());
- }
-
- /**
- * Returns true if the language server can support references and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support references and false otherwise.
- */
- public static boolean isReferencesSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getReferencesProvider());
- }
-
- /**
- * Returns true if the language server can support references and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support references and false otherwise.
- */
- public static boolean isImplementationSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getImplementationProvider());
- }
-
- /**
- * Returns true if the language server can support folding range and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support folding range and false otherwise.
- */
- public static boolean isFoldingRangeSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getFoldingRangeProvider());
- }
-
- /**
- * Returns true if the language server can support formatting and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support formatting and false otherwise.
- */
- public static boolean isDocumentFormattingSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getDocumentFormattingProvider());
- }
-
/**
* Returns true if the language server can support range formatting and false otherwise.
*
@@ -423,62 +132,6 @@ public static boolean isDocumentRangeFormattingSupported(@Nullable ServerCapabil
hasCapability(serverCapabilities.getDocumentRangeFormattingProvider());
}
- /**
- * Returns true if the language server can support code action and false otherwise.
- *
- * @return true if the language server can support code action and false otherwise.
- */
- public boolean isCodeActionSupported() {
- return isCodeActionSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support code action and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support code action and false otherwise.
- */
- public static boolean isCodeActionSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getCodeActionProvider());
- }
-
- /**
- * Returns true if the language server can support resolve code action and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support resolve code action and false otherwise.
- */
- public static boolean isCodeActionResolveSupported(@Nullable ServerCapabilities serverCapabilities) {
- Either codeActionProvider = serverCapabilities != null ? serverCapabilities.getCodeActionProvider() : null;
- if (codeActionProvider != null && codeActionProvider.isRight()) {
- return hasCapability(codeActionProvider.getRight().getResolveProvider());
- }
- return false;
- }
-
- /**
- * Returns true if the language server can support semantic tokens and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support semantic tokens and false otherwise.
- */
- public static boolean isSemanticTokensSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- serverCapabilities.getSemanticTokensProvider() != null;
- }
-
- /**
- * Returns true if the language server can support rename and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support rename and false otherwise.
- */
- public static boolean isRenameSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getRenameProvider());
- }
-
/**
* Returns true if the language server can support prepare rename and false otherwise.
*
@@ -564,42 +217,4 @@ public SemanticTokensColorsProvider getSemanticTokensColorsProvider() {
return getClientFeatures().getSemanticTokensFeature();
}
- /**
- * Returns true if the language server can support document symbol and false otherwise.
- *
- * @return true if the language server can support document symbol and false otherwise.
- */
- public static boolean isDocumentSymbolSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getDocumentSymbolProvider());
- }
-
- /**
- * Returns true if the language server can support workspace symbol and false otherwise.
- *
- * @return true if the language server can support workspace symbol and false otherwise.
- */
- public boolean isWorkspaceSymbolSupported() {
- return isWorkspaceSymbolSupported(getServerCapabilities());
- }
-
- /**
- * Returns true if the language server can support workspace symbol and false otherwise.
- *
- * @param serverCapabilities the server capabilities.
- * @return true if the language server can support workspace symbol and false otherwise.
- */
- public static boolean isWorkspaceSymbolSupported(@Nullable ServerCapabilities serverCapabilities) {
- return serverCapabilities != null &&
- hasCapability(serverCapabilities.getWorkspaceSymbolProvider());
- }
-
- public static boolean isUsageSupported(ServerCapabilities serverCapabilities) {
- return LanguageServerItem.isDeclarationSupported(serverCapabilities) ||
- LanguageServerItem.isTypeDefinitionSupported(serverCapabilities) ||
- LanguageServerItem.isDefinitionSupported(serverCapabilities) ||
- LanguageServerItem.isReferencesSupported(serverCapabilities) ||
- LanguageServerItem.isImplementationSupported(serverCapabilities);
- }
-
}
\ No newline at end of file
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/LanguageServerWrapper.java b/src/main/java/com/redhat/devtools/lsp4ij/LanguageServerWrapper.java
index 6c235c0fc..ac49f9bf2 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/LanguageServerWrapper.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/LanguageServerWrapper.java
@@ -12,12 +12,10 @@
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.gson.JsonObject;
-import com.intellij.lang.Language;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
-import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
@@ -26,12 +24,13 @@
import com.intellij.psi.PsiFile;
import com.intellij.util.messages.MessageBusConnection;
import com.redhat.devtools.lsp4ij.client.LanguageClientImpl;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
import com.redhat.devtools.lsp4ij.features.files.operations.FileOperationsManager;
import com.redhat.devtools.lsp4ij.internal.ClientCapabilitiesFactory;
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.LSPClientFeatures;
+import com.redhat.devtools.lsp4ij.server.capabilities.TextDocumentServerCapabilityRegistry;
import com.redhat.devtools.lsp4ij.server.definition.LanguageServerDefinition;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.Launcher;
@@ -228,9 +227,7 @@ public synchronized void start() throws LanguageServerException {
initParams.setInitializationOptions(provider.getInitializationOptions(rootURI));
// Add error log
- provider.addLogErrorHandler(error -> {
- ServerMessageHandler.logMessage(this.getServerDefinition(), new MessageParams(MessageType.Error, error), getProject());
- });
+ provider.addLogErrorHandler(error -> ServerMessageHandler.logMessage(this.getServerDefinition(), new MessageParams(MessageType.Error, error), getProject()));
// Starting process...
updateStatus(ServerStatus.starting);
@@ -312,6 +309,7 @@ public synchronized void start() throws LanguageServerException {
fileOperationsManager = new FileOperationsManager(this);
fileOperationsManager.setServerCapabilities(serverCapabilities);
+ getClientFeatures().setServerCapabilities(serverCapabilities);
updateStatus(ServerStatus.started);
getLanguageServerLifecycleManager().onStatusChanged(this);
@@ -635,7 +633,7 @@ private CompletableFuture connect(@NotNull URI fileUri,
return CompletableFuture.completedFuture(null);
}
- VirtualFile fileToConnect = optionalFile;
+ final @NotNull VirtualFile fileToConnect = optionalFile;
return initializeFuture.thenComposeAsync(theVoid -> {
// Here, the "initialize" future is initialized
@@ -656,7 +654,7 @@ private CompletableFuture connect(@NotNull URI fileUri,
return ls2;
}
- DocumentContentSynchronizer synchronizer = createDocumentContentSynchronizer(fileUri, document);
+ DocumentContentSynchronizer synchronizer = createDocumentContentSynchronizer(fileUri, fileToConnect, document);
document.addDocumentListener(synchronizer);
LSPVirtualFileData data = new LSPVirtualFileData(new LanguageServerItem(languageServer, this), fileToConnect, synchronizer);
LanguageServerWrapper.this.connectedDocuments.put(fileUri, data);
@@ -692,6 +690,7 @@ private CompletableFuture getLanguageServerWhenDidOpen(Completab
@NotNull
private DocumentContentSynchronizer createDocumentContentSynchronizer(@NotNull URI fileUri,
+ @NotNull VirtualFile file,
@NotNull Document document) {
Either syncOptions = initializeFuture == null ? null
: this.serverCapabilities.getTextDocumentSync();
@@ -703,7 +702,7 @@ private DocumentContentSynchronizer createDocumentContentSynchronizer(@NotNull U
syncKind = syncOptions.getLeft();
}
}
- return new DocumentContentSynchronizer(this, fileUri, document, syncKind);
+ return new DocumentContentSynchronizer(this, fileUri, file, document, syncKind);
}
public void disconnect(URI path, boolean stopIfNoOpenedFiles) {
@@ -838,43 +837,6 @@ public ServerCapabilities getServerCapabilitiesSync() {
return serverCapabilities;
}
- /**
- * @return The language ID that this wrapper is dealing with if defined in the
- * language mapping for the language server
- */
- @Nullable
- public String getLanguageId(@Nullable Language language) {
- while (language != null) {
- String languageId = serverDefinition.getLanguageId(language);
- if (languageId != null) {
- return languageId;
- }
- language = language.getBaseLanguage();
- }
- return null;
- }
-
- /**
- * @return The language ID that this wrapper is dealing with if defined in the
- * file type mapping for the language server
- */
- @Nullable
- public String getLanguageId(@Nullable FileType fileType) {
- if (fileType == null) {
- return null;
- }
- return serverDefinition.getLanguageId(fileType);
- }
-
- /**
- * @return The language ID that this wrapper is dealing with if defined in the
- * file type mapping for the language server
- */
- @Nullable
- public String getLanguageId(@NotNull String filename) {
- return serverDefinition.getLanguageId(filename);
- }
-
public void registerCapability(RegistrationParams params) {
initializeFuture.thenRun(() -> {
params.getRegistrations().forEach(reg -> {
@@ -917,47 +879,17 @@ public void registerCapability(RegistrationParams params) {
} catch (Exception e) {
LOGGER.error("Error while getting 'workspace/executeCommand' capability", e);
}
- } else if (LSPRequestConstants.TEXT_DOCUMENT_FORMATTING.equals(reg.getMethod())) {
- // register 'textDocument/formatting' capability
- final Either documentFormattingProvider = serverCapabilities.getDocumentFormattingProvider();
- if (documentFormattingProvider == null || documentFormattingProvider.isLeft()) {
- serverCapabilities.setDocumentFormattingProvider(Boolean.TRUE);
- addRegistration(reg, () -> serverCapabilities.setDocumentFormattingProvider(documentFormattingProvider));
- } else {
- serverCapabilities.setDocumentFormattingProvider(documentFormattingProvider.getRight());
- addRegistration(reg, () -> serverCapabilities.setDocumentFormattingProvider(documentFormattingProvider));
- }
- } else if (LSPRequestConstants.TEXT_DOCUMENT_RANGE_FORMATTING.equals(reg.getMethod())) {
- // register 'textDocument/rangeFormatting' capability
- final Either documentRangeFormattingProvider = serverCapabilities.getDocumentRangeFormattingProvider();
- if (documentRangeFormattingProvider == null || documentRangeFormattingProvider.isLeft()) {
- serverCapabilities.setDocumentRangeFormattingProvider(Boolean.TRUE);
- addRegistration(reg, () -> serverCapabilities.setDocumentRangeFormattingProvider(documentRangeFormattingProvider));
- } else {
- serverCapabilities.setDocumentRangeFormattingProvider(documentRangeFormattingProvider.getRight());
- addRegistration(reg, () -> serverCapabilities.setDocumentRangeFormattingProvider(documentRangeFormattingProvider));
- }
- } else if (LSPRequestConstants.TEXT_DOCUMENT_CODE_ACTION.equals(reg.getMethod())) {
+ } else {
+ String method = reg.getMethod();
try {
- // Get old 'textDocument/codeAction' capability
- final Either beforeRegistration = serverCapabilities.getCodeActionProvider();
-
- // Register new 'textDocument/codeAction' capability
- CodeActionRegistrationOptions options = JSONUtils.getLsp4jGson()
- .fromJson((JsonObject) reg.getRegisterOptions(),
- CodeActionRegistrationOptions.class);
- CodeActionOptions codeActionOptions = new CodeActionOptions();
- codeActionOptions.setCodeActionKinds(options.getCodeActionKinds());
- codeActionOptions.setResolveProvider(options.getResolveProvider());
- // TODO: manage CodeActionRegistrationOptions#getDocumentSelector()
- serverCapabilities.setCodeActionProvider(Either.forRight(codeActionOptions));
-
- // Add registration handler to:
- // - unregister the new 'textDocument/codeAction' capability
- // - register the old 'textDocument/codeAction' capability
- addRegistration(reg, () -> serverCapabilities.setCodeActionProvider(beforeRegistration));
+ final TextDocumentServerCapabilityRegistry extends TextDocumentRegistrationOptions> registry = getClientFeatures().getCapabilityRegistry(method);
+ if (registry != null) {
+ // register 'textDocument/*' capability
+ final TextDocumentRegistrationOptions options = registry.registerCapability((JsonObject) reg.getRegisterOptions());
+ addRegistration(reg, () -> registry.unregisterCapability(options));
+ }
} catch (Exception e) {
- LOGGER.error("Error while getting 'textDocument/codeAction' capability", e);
+ LOGGER.error("Error while getting '" + method + "' capability", e);
}
}
});
@@ -1010,13 +942,13 @@ synchronized void registerCommands(List newCommands) {
public void unregisterCapability(UnregistrationParams params) {
params.getUnregisterations().forEach(reg -> {
String id = reg.getId();
- Runnable unregistrator;
+ Runnable unregisters;
synchronized (dynamicRegistrations) {
- unregistrator = dynamicRegistrations.get(id);
+ unregisters = dynamicRegistrations.get(id);
dynamicRegistrations.remove(id);
}
- if (unregistrator != null) {
- unregistrator.run();
+ if (unregisters != null) {
+ unregisters.run();
}
});
}
@@ -1193,11 +1125,12 @@ public LSPClientFeatures getClientFeatures() {
}
private synchronized LSPClientFeatures getOrCreateClientFeatures() {
- if (clientFeatures != null) {
+ if (clientFeatures != null) {
return clientFeatures;
}
LSPClientFeatures clientFeatures = getServerDefinition().createClientFeatures();
clientFeatures.setServerWrapper(this);
return clientFeatures;
}
+
}
\ No newline at end of file
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/AbstractLSPDocumentFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/AbstractLSPDocumentFeature.java
index 026931eda..22790edbe 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/AbstractLSPDocumentFeature.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/AbstractLSPDocumentFeature.java
@@ -43,7 +43,6 @@ public boolean isEnabled(@NotNull PsiFile file) {
*
*
* @param file the file.
- *
* @return true if the LSP feature is supported for the given file and false otherwise.
*/
public abstract boolean isSupported(@NotNull PsiFile file);
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/AbstractLSPFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/AbstractLSPFeature.java
index 953546c34..f5c553555 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/AbstractLSPFeature.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/AbstractLSPFeature.java
@@ -14,6 +14,7 @@
import com.intellij.openapi.project.Project;
import com.redhat.devtools.lsp4ij.ServerStatus;
import com.redhat.devtools.lsp4ij.server.definition.LanguageServerDefinition;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.services.LanguageServer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -100,4 +101,6 @@ public final void setClientFeatures(@NotNull LSPClientFeatures clientFeatures) {
public void dispose() {
clientFeatures = null;
}
+
+ public abstract void setServerCapabilities(@Nullable ServerCapabilities serverCapabilities);
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPClientFeatures.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPClientFeatures.java
index e03eea162..8ada6870f 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPClientFeatures.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPClientFeatures.java
@@ -12,9 +12,13 @@
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
+import com.redhat.devtools.lsp4ij.LSPRequestConstants;
import com.redhat.devtools.lsp4ij.LanguageServerWrapper;
import com.redhat.devtools.lsp4ij.ServerStatus;
+import com.redhat.devtools.lsp4ij.server.capabilities.TextDocumentServerCapabilityRegistry;
import com.redhat.devtools.lsp4ij.server.definition.LanguageServerDefinition;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.eclipse.lsp4j.TextDocumentRegistrationOptions;
import org.eclipse.lsp4j.services.LanguageServer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -32,7 +36,7 @@ public class LSPClientFeatures implements Disposable {
private LSPCodeLensFeature codeLensFeature;
- private LSPColorFeature colorFeature;
+ private LSPDocumentColorFeature documentColorFeature;
private LSPCompletionFeature completionFeature;
@@ -71,7 +75,7 @@ public class LSPClientFeatures implements Disposable {
private LSPUsageFeature usageFeature;
private LSPWorkspaceSymbolFeature workspaceSymbolFeature;
-
+
/**
* Returns the project.
*
@@ -187,22 +191,22 @@ public final LSPClientFeatures setCodeLensFeature(@NotNull LSPCodeLensFeature co
* @return the LSP color feature.
*/
@NotNull
- public final LSPColorFeature getColorFeature() {
- if (colorFeature == null) {
- setColorFeature(new LSPColorFeature());
+ public final LSPDocumentColorFeature getDocumentColorFeature() {
+ if (documentColorFeature == null) {
+ setDocumentColorFeature(new LSPDocumentColorFeature());
}
- return colorFeature;
+ return documentColorFeature;
}
/**
* Initialize the LSP color feature.
*
- * @param colorFeature the LSP color feature.
+ * @param documentColorFeature the LSP color feature.
* @return the LSP client features.
*/
- public final LSPClientFeatures setColorFeature(@NotNull LSPColorFeature colorFeature) {
- colorFeature.setClientFeatures(this);
- this.colorFeature = colorFeature;
+ public final LSPClientFeatures setDocumentColorFeature(@NotNull LSPDocumentColorFeature documentColorFeature) {
+ documentColorFeature.setClientFeatures(this);
+ this.documentColorFeature = documentColorFeature;
return this;
}
@@ -713,8 +717,8 @@ public void dispose() {
if (codeLensFeature != null) {
codeLensFeature.dispose();
}
- if (colorFeature != null) {
- colorFeature.dispose();
+ if (documentColorFeature != null) {
+ documentColorFeature.dispose();
}
if (completionFeature != null) {
completionFeature.dispose();
@@ -780,4 +784,161 @@ public void dispose() {
workspaceSymbolFeature.dispose();
}
}
+
+ public void setServerCapabilities(@NotNull ServerCapabilities serverCapabilities) {
+ if (codeActionFeature != null) {
+ codeActionFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (codeLensFeature != null) {
+ codeLensFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (completionFeature != null) {
+ completionFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (codeActionFeature != null) {
+ codeActionFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (codeActionFeature != null) {
+ codeActionFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (declarationFeature != null) {
+ declarationFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (definitionFeature != null) {
+ definitionFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (documentColorFeature != null) {
+ documentColorFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (documentLinkFeature != null) {
+ documentLinkFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (documentHighlightFeature != null) {
+ documentHighlightFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (documentSymbolFeature != null) {
+ documentSymbolFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (diagnosticFeature != null) {
+ diagnosticFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (foldingRangeFeature != null) {
+ foldingRangeFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (formattingFeature != null) {
+ formattingFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (implementationFeature != null) {
+ implementationFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (inlayHintFeature != null) {
+ inlayHintFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (hoverFeature != null) {
+ hoverFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (referencesFeature != null) {
+ referencesFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (renameFeature != null) {
+ renameFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (semanticTokensFeature != null) {
+ semanticTokensFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (signatureHelpFeature != null) {
+ signatureHelpFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (typeDefinitionFeature != null) {
+ typeDefinitionFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (usageFeature != null) {
+ usageFeature.setServerCapabilities(serverCapabilities);
+ }
+ if (workspaceSymbolFeature != null) {
+ workspaceSymbolFeature.setServerCapabilities(serverCapabilities);
+ }
+ }
+
+ @Nullable
+ public TextDocumentServerCapabilityRegistry extends TextDocumentRegistrationOptions> getCapabilityRegistry(String method) {
+ if (LSPRequestConstants.TEXT_DOCUMENT_CODE_ACTION.equals(method)) {
+ // register 'textDocument/codeAction' capability
+ return getCodeActionFeature().getCodeActionCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_CODE_LENS.equals(method)) {
+ // register 'textDocument/codeLens' capability
+ return getCodeLensFeature().getCodeLensCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_DOCUMENT_COLOR.equals(method)) {
+ // register 'textDocument/documentColor' capability
+ return getDocumentColorFeature().getDocumentColorCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_COMPLETION.equals(method)) {
+ // register 'textDocument/completion' capability
+ return getCompletionFeature().getCompletionCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_DECLARATION.equals(method)) {
+ // register 'textDocument/declaration' capability
+ return getDeclarationFeature().getDeclarationCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_DEFINITION.equals(method)) {
+ // register 'textDocument/definition' capability
+ return getDefinitionFeature().getDefinitionCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT.equals(method)) {
+ // register 'textDocument/documentHighlight' capability
+ return getDocumentHighlightFeature().getDocumentHighlightCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_DOCUMENT_LINK.equals(method)) {
+ // register 'textDocument/documentHighLink' capability
+ return getDocumentLinkFeature().getDocumentLinkCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_DOCUMENT_SYMBOL.equals(method)) {
+ // register 'textDocument/documentSymbol' capability
+ return getDocumentSymbolFeature().getDocumentSymbolCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_FOLDING_RANGE.equals(method)) {
+ // register 'textDocument/foldingRange' capability
+ return getFoldingRangeFeature().getFoldingRangeCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_FORMATTING.equals(method)) {
+ // register 'textDocument/formatting' capability
+ return getFormattingFeature().getFormattingCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_RANGE_FORMATTING.equals(method)) {
+ // register 'textDocument/rangeFormatting' capability
+ return getFormattingFeature().getRangeFormattingCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_HOVER.equals(method)) {
+ // register 'textDocument/hover' capability
+ return getHoverFeature().getHoverCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_IMPLEMENTATION.equals(method)) {
+ // register 'textDocument/implementation' capability
+ return getImplementationFeature().getImplementationCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_INLAY_HINT.equals(method)) {
+ // register 'textDocument/inlayHint' capability
+ return getInlayHintFeature().getInlayHintCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_REFERENCES.equals(method)) {
+ // register 'textDocument/references' capability
+ return getReferencesFeature().getReferencesCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_RENAME.equals(method)) {
+ // register 'textDocument/rename' capability
+ return getRenameFeature().getRenameCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_SIGNATURE_HELP.equals(method)) {
+ // register 'textDocument/signatureHelp' capability
+ return getSignatureHelpFeature().getSignatureHelpCapabilityRegistry();
+ }
+ if (LSPRequestConstants.TEXT_DOCUMENT_TYPE_DEFINITION.equals(method)) {
+ // register 'textDocument/typeDefinition' capability
+ return getTypeDefinitionFeature().getTypeDefinitionCapabilityRegistry();
+ }
+ return null;
+ }
+
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCodeActionFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCodeActionFeature.java
index 458827a51..07db8121f 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCodeActionFeature.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCodeActionFeature.java
@@ -12,11 +12,12 @@
import com.intellij.psi.PsiFile;
import com.redhat.devtools.lsp4ij.LanguageServerBundle;
-import com.redhat.devtools.lsp4ij.LanguageServerItem;
import com.redhat.devtools.lsp4ij.internal.StringUtils;
+import com.redhat.devtools.lsp4ij.server.capabilities.CodeActionCapabilityRegistry;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.Command;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,6 +28,8 @@
@ApiStatus.Experimental
public class LSPCodeActionFeature extends AbstractLSPDocumentFeature {
+ private CodeActionCapabilityRegistry codeActionCapabilityRegistry;
+
@Override
public boolean isSupported(@NotNull PsiFile file) {
return isCodeActionSupported(file);
@@ -35,14 +38,24 @@ public boolean isSupported(@NotNull PsiFile file) {
/**
* Returns true if the file associated with a language server can support codeAction and false otherwise.
*
- * @param file the file.
+ * @param file the file.
* @return true if the file associated with a language server can support codeAction and false otherwise.
*/
public boolean isCodeActionSupported(@NotNull PsiFile file) {
- // TODO implement documentSelector to use language of the given file
- return LanguageServerItem.isCodeActionSupported(getClientFeatures().getServerWrapper().getServerCapabilitiesSync());
+ return getCodeActionCapabilityRegistry().isCodeActionSupported(file);
+ }
+
+ /**
+ * Returns true if the file associated with a language server can support resolve codeAction and false otherwise.
+ *
+ * @param file the file.
+ * @return true if the file associated with a language server can support resolve codeAction and false otherwise.
+ */
+ public boolean isResolveCodeActionSupported(@NotNull PsiFile file) {
+ return getCodeActionCapabilityRegistry().isResolveCodeActionSupported(file);
}
+
/**
* Returns true if quick fixes are enabled and false otherwise.
*
@@ -125,4 +138,20 @@ public String getText(@NotNull Command command) {
public String getFamilyName(@NotNull Command command) {
return "LSP Command";
}
+
+ public CodeActionCapabilityRegistry getCodeActionCapabilityRegistry() {
+ if (codeActionCapabilityRegistry == null) {
+ var clientFeatures = getClientFeatures();
+ codeActionCapabilityRegistry = new CodeActionCapabilityRegistry(clientFeatures);
+ codeActionCapabilityRegistry.setServerCapabilities(clientFeatures.getServerWrapper().getServerCapabilitiesSync());
+ }
+ return codeActionCapabilityRegistry;
+ }
+
+ @Override
+ public void setServerCapabilities(@Nullable ServerCapabilities serverCapabilities) {
+ if(codeActionCapabilityRegistry != null) {
+ codeActionCapabilityRegistry.setServerCapabilities(serverCapabilities);
+ }
+ }
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCodeLensFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCodeLensFeature.java
index c86e50e18..14102efad 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCodeLensFeature.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCodeLensFeature.java
@@ -19,8 +19,10 @@
import com.redhat.devtools.lsp4ij.commands.CommandExecutor;
import com.redhat.devtools.lsp4ij.commands.LSPCommandContext;
import com.redhat.devtools.lsp4ij.internal.StringUtils;
+import com.redhat.devtools.lsp4ij.server.capabilities.CodeLensCapabilityRegistry;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.Command;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,6 +35,33 @@
@ApiStatus.Experimental
public class LSPCodeLensFeature extends AbstractLSPDocumentFeature {
+ private CodeLensCapabilityRegistry codeLensCapabilityRegistry;
+
+ @Override
+ public boolean isSupported(@NotNull PsiFile file) {
+ return isCodeLensSupported(file);
+ }
+
+ /**
+ * Returns true if the file associated with a language server can support codelens and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the file associated with a language server can support codelens and false otherwise.
+ */
+ public boolean isCodeLensSupported(@NotNull PsiFile file) {
+ return getCodeLensCapabilityRegistry().isCodeLensSupported(file);
+ }
+
+ /**
+ * Returns true if the file associated with a language server can support resolve codelens and false otherwise.
+ *
+ * @param file the file.
+ * @return true if the file associated with a language server can support resolve codelens and false otherwise.
+ */
+ public boolean isResolveCodeLensSupported(@NotNull PsiFile file) {
+ return getCodeLensCapabilityRegistry().isResolveCodeLensSupported(file);
+ }
+
public static class LSPCodeLensContext {
private final @NotNull PsiFile psiFile;
private final @NotNull LanguageServerItem languageServer;
@@ -120,30 +149,19 @@ public String getText(@NotNull CodeLens codeLens) {
return command.getTitle();
}
-
- @Override
- public boolean isSupported(@NotNull PsiFile file) {
- return isCodeLensSupported(file);
- }
-
- /**
- * Returns true if the file associated with a language server can support codelens and false otherwise.
- *
- * @param file the file.
- * @return true if the file associated with a language server can support codelens and false otherwise.
- */
- public boolean isCodeLensSupported(@NotNull PsiFile file) {
- // TODO implement documentSelector to use language of the given file
- return LanguageServerItem.isCodeLensSupported(getClientFeatures().getServerWrapper().getServerCapabilitiesSync());
+ public CodeLensCapabilityRegistry getCodeLensCapabilityRegistry() {
+ if (codeLensCapabilityRegistry == null) {
+ var clientFeatures = getClientFeatures();
+ codeLensCapabilityRegistry = new CodeLensCapabilityRegistry(clientFeatures);
+ codeLensCapabilityRegistry.setServerCapabilities(clientFeatures.getServerWrapper().getServerCapabilitiesSync());
+ }
+ return codeLensCapabilityRegistry;
}
- /**
- * Returns true if the file associated with a language server can support resolve codelens and false otherwise.
- *
- * @param file the file.
- * @return true if the file associated with a language server can support resolve codelens and false otherwise.
- */
- public boolean isResolveCodeLensSupported(@NotNull PsiFile file) {
- return LanguageServerItem.isResolveCodeLensSupported(getClientFeatures().getServerWrapper().getServerCapabilitiesSync());
+ @Override
+ public void setServerCapabilities(@Nullable ServerCapabilities serverCapabilities) {
+ if(codeLensCapabilityRegistry != null) {
+ codeLensCapabilityRegistry.setServerCapabilities(serverCapabilities);
+ }
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPColorFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPColorFeature.java
deleted file mode 100644
index a25671127..000000000
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPColorFeature.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * 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 com.intellij.psi.PsiFile;
-import com.redhat.devtools.lsp4ij.LanguageServerItem;
-import org.jetbrains.annotations.ApiStatus;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * LSP color feature.
- */
-@ApiStatus.Experimental
-public class LSPColorFeature extends AbstractLSPDocumentFeature {
-
- @Override
- public boolean isSupported(@NotNull PsiFile file) {
- return isColorSupported(file);
- }
-
- /**
- * Returns true if the file associated with a language server can support color and false otherwise.
- *
- * @param file the file.
- * @return true if the file associated with a language server can support color and false otherwise.
- */
- public boolean isColorSupported(@NotNull PsiFile file) {
- // TODO implement documentSelector to use language of the given file
- return LanguageServerItem.isColorSupported(getClientFeatures().getServerWrapper().getServerCapabilitiesSync());
- }
-}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCompletionFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCompletionFeature.java
index 4647400be..79a63ae74 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCompletionFeature.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPCompletionFeature.java
@@ -19,10 +19,12 @@
import com.redhat.devtools.lsp4ij.LanguageServerItem;
import com.redhat.devtools.lsp4ij.features.completion.CompletionPrefix;
import com.redhat.devtools.lsp4ij.internal.StringUtils;
+import com.redhat.devtools.lsp4ij.server.capabilities.CompletionCapabilityRegistry;
import com.redhat.devtools.lsp4ij.ui.IconMapper;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.CompletionItemTag;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,6 +37,8 @@
@ApiStatus.Experimental
public class LSPCompletionFeature extends AbstractLSPDocumentFeature {
+ private CompletionCapabilityRegistry completionCapabilityRegistry;
+
public static class LSPCompletionContext {
private final @NotNull CompletionParameters parameters;
@@ -84,12 +88,7 @@ public boolean isSupported(@NotNull PsiFile file) {
* @return true if the file associated with a language server can support completion and false otherwise.
*/
public boolean isCompletionSupported(@NotNull PsiFile file) {
- // TODO implement documentSelector to use language of the given file
- return LanguageServerItem.isCompletionSupported(getClientFeatures().getServerWrapper().getServerCapabilitiesSync());
- }
-
- public boolean isCompletionTriggerCharactersSupported(@NotNull PsiFile file, String completionChar) {
- return getClientFeatures().getServerWrapper().isCompletionTriggerCharactersSupported(completionChar);
+ return getCompletionCapabilityRegistry().isCompletionSupported(file);
}
/**
@@ -99,8 +98,12 @@ public boolean isCompletionTriggerCharactersSupported(@NotNull PsiFile file, Str
* @return true the file associated with a language server can support resolve completion and false otherwise.
*/
public boolean isResolveCompletionSupported(@Nullable PsiFile file) {
- // TODO implement documentSelector to use language of the given file
- return LanguageServerItem.isResolveCompletionSupported(getClientFeatures().getServerWrapper().getServerCapabilitiesSync());
+ return getCompletionCapabilityRegistry().isResolveCompletionSupported(file);
+ }
+
+ public boolean isCompletionTriggerCharactersSupported(@NotNull PsiFile file, String completionChar) {
+ // TODO: manage documentSelector for trigger character
+ return getClientFeatures().getServerWrapper().isCompletionTriggerCharactersSupported(completionChar);
}
/**
@@ -225,5 +228,19 @@ public void addLookupItem(@NotNull CompletionPrefix completionPrefix,
}
}
+ public CompletionCapabilityRegistry getCompletionCapabilityRegistry() {
+ if (completionCapabilityRegistry == null) {
+ var clientFeatures = getClientFeatures();
+ completionCapabilityRegistry = new CompletionCapabilityRegistry(clientFeatures);
+ completionCapabilityRegistry.setServerCapabilities(clientFeatures.getServerWrapper().getServerCapabilitiesSync());
+ }
+ return completionCapabilityRegistry;
+ }
+ @Override
+ public void setServerCapabilities(@Nullable ServerCapabilities serverCapabilities) {
+ if(completionCapabilityRegistry != null) {
+ completionCapabilityRegistry.setServerCapabilities(serverCapabilities);
+ }
+ }
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDeclarationFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDeclarationFeature.java
index 0a1fd79fe..179da3de8 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDeclarationFeature.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDeclarationFeature.java
@@ -11,9 +11,11 @@
package com.redhat.devtools.lsp4ij.client.features;
import com.intellij.psi.PsiFile;
-import com.redhat.devtools.lsp4ij.LanguageServerItem;
+import com.redhat.devtools.lsp4ij.server.capabilities.DeclarationCapabilityRegistry;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* LSP declaration feature.
@@ -21,19 +23,36 @@
@ApiStatus.Experimental
public class LSPDeclarationFeature extends AbstractLSPDocumentFeature {
+ private DeclarationCapabilityRegistry declarationCapabilityRegistry;
+
@Override
public boolean isSupported(@NotNull PsiFile file) {
return isDeclarationSupported(file);
}
/**
- * Returns true if the file associated with a language server can support codelens and false otherwise.
+ * Returns true if the file associated with a language server can support declaration and false otherwise.
*
* @param file the file.
- * @return true if the file associated with a language server can support codelens and false otherwise.
+ * @return true if the file associated with a language server can support declaration and false otherwise.
*/
public boolean isDeclarationSupported(@NotNull PsiFile file) {
- // TODO implement documentSelector to use language of the given file
- return LanguageServerItem.isDeclarationSupported(getClientFeatures().getServerWrapper().getServerCapabilitiesSync());
+ return getDeclarationCapabilityRegistry().isDeclarationSupported(file);
+ }
+
+ public DeclarationCapabilityRegistry getDeclarationCapabilityRegistry() {
+ if (declarationCapabilityRegistry == null) {
+ var clientFeatures = getClientFeatures();
+ declarationCapabilityRegistry = new DeclarationCapabilityRegistry(clientFeatures);
+ declarationCapabilityRegistry.setServerCapabilities(clientFeatures.getServerWrapper().getServerCapabilitiesSync());
+ }
+ return declarationCapabilityRegistry;
+ }
+
+ @Override
+ public void setServerCapabilities(@Nullable ServerCapabilities serverCapabilities) {
+ if (declarationCapabilityRegistry != null) {
+ declarationCapabilityRegistry.setServerCapabilities(serverCapabilities);
+ }
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDefinitionFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDefinitionFeature.java
index 5232a11b0..6ea36abb6 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDefinitionFeature.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDefinitionFeature.java
@@ -11,9 +11,11 @@
package com.redhat.devtools.lsp4ij.client.features;
import com.intellij.psi.PsiFile;
-import com.redhat.devtools.lsp4ij.LanguageServerItem;
+import com.redhat.devtools.lsp4ij.server.capabilities.DefinitionCapabilityRegistry;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* LSP definition feature.
@@ -21,19 +23,36 @@
@ApiStatus.Experimental
public class LSPDefinitionFeature extends AbstractLSPDocumentFeature {
+ private DefinitionCapabilityRegistry definitionCapabilityRegistry;
+
@Override
public boolean isSupported(@NotNull PsiFile file) {
return isDefinitionSupported(file);
}
/**
- * Returns true if the file associated with a language server can support codelens and false otherwise.
+ * Returns true if the file associated with a language server can support definition and false otherwise.
*
* @param file the file.
- * @return true if the file associated with a language server can support codelens and false otherwise.
+ * @return true if the file associated with a language server can support definition and false otherwise.
*/
public boolean isDefinitionSupported(@NotNull PsiFile file) {
- // TODO implement documentSelector to use language of the given file
- return LanguageServerItem.isDefinitionSupported(getClientFeatures().getServerWrapper().getServerCapabilitiesSync());
+ return getDefinitionCapabilityRegistry().isDefinitionSupported(file);
+ }
+
+ public DefinitionCapabilityRegistry getDefinitionCapabilityRegistry() {
+ if (definitionCapabilityRegistry == null) {
+ var clientFeatures = getClientFeatures();
+ definitionCapabilityRegistry = new DefinitionCapabilityRegistry(clientFeatures);
+ definitionCapabilityRegistry.setServerCapabilities(clientFeatures.getServerWrapper().getServerCapabilitiesSync());
+ }
+ return definitionCapabilityRegistry;
+ }
+
+ @Override
+ public void setServerCapabilities(@Nullable ServerCapabilities serverCapabilities) {
+ if (definitionCapabilityRegistry != null) {
+ definitionCapabilityRegistry.setServerCapabilities(serverCapabilities);
+ }
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDiagnosticFeature.java b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDiagnosticFeature.java
index 3429dca27..f4f16713c 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDiagnosticFeature.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDiagnosticFeature.java
@@ -249,4 +249,8 @@ public ProblemHighlightType getProblemHighlightType(@Nullable List canSupportFeature(ls.getServerCapabilitiesSync()));
+ .hasAny(file.getVirtualFile(), ls -> canSupportFeature(ls.getClientFeatures(), file));
}
- protected abstract boolean canSupportFeature(ServerCapabilities serverCapabilities);
+ protected abstract boolean canSupportFeature(@NotNull LSPClientFeatures clientFeatures, @NotNull PsiFile file);
@Override
public final @NotNull ActionUpdateThread getActionUpdateThread() {
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/codeAction/LSPLazyCodeActionIntentionAction.java b/src/main/java/com/redhat/devtools/lsp4ij/features/codeAction/LSPLazyCodeActionIntentionAction.java
index 97bc4640c..93a72194a 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/codeAction/LSPLazyCodeActionIntentionAction.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/codeAction/LSPLazyCodeActionIntentionAction.java
@@ -33,8 +33,6 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import static com.redhat.devtools.lsp4ij.LanguageServerItem.isCodeActionResolveSupported;
-
/**
* The lazy IJ Quick fix / Intention.
*/
@@ -84,7 +82,7 @@ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws
var languageServer = getLanguageServer();
if (codeAction != null) {
if (codeAction.getEdit() == null && codeAction.getCommand() == null
- && isCodeActionResolveSupported(languageServer.getServerCapabilities())) {
+ && languageServer.getClientFeatures().getCodeActionFeature().isResolveCodeActionSupported(file)) {
// Unresolved code action "edit" property. Resolve it.
languageServer
.getInitializedServer()
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/codeLens/LSPCodeLensSupport.java b/src/main/java/com/redhat/devtools/lsp4ij/features/codeLens/LSPCodeLensSupport.java
index 1e9a9a592..d578a518e 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/codeLens/LSPCodeLensSupport.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/codeLens/LSPCodeLensSupport.java
@@ -67,7 +67,7 @@ protected CompletableFuture> doLoad(CodeLensParams params, Ca
// Collect list of textDocument/codeLens future for each language servers
List>> codeLensPerServerFutures = languageServers
.stream()
- .map(languageServer -> getCodeLensesFor(params, languageServer, cancellationSupport))
+ .map(languageServer -> getCodeLensesFor(params, languageServer, file, cancellationSupport))
.toList();
// Merge list of textDocument/codelens future in one future which return the list of code lenses
@@ -80,7 +80,10 @@ protected CompletableFuture> doLoad(CodeLensParams params, Ca
});
}
- private static CompletableFuture> getCodeLensesFor(CodeLensParams params, LanguageServerItem languageServer, CancellationSupport cancellationSupport) {
+ private static CompletableFuture> getCodeLensesFor(@NotNull CodeLensParams params,
+ @NotNull LanguageServerItem languageServer,
+ @NotNull PsiFile file,
+ @NotNull CancellationSupport cancellationSupport) {
return cancellationSupport.execute(languageServer
.getTextDocumentService()
.codeLens(params), languageServer, LSPRequestConstants.TEXT_DOCUMENT_CODE_LENS)
@@ -95,14 +98,14 @@ private static CompletableFuture> getCodeLensesFor(CodeLensPa
.filter(LSPCodeLensSupport::isValidCodeLens)
.forEach(codeLens -> {
CompletableFuture resolvedCodeLensFuture = null;
- if (codeLens.getCommand() == null && languageServer.isResolveCodeLensSupported()) {
+ var codeLensFeature = languageServer.getClientFeatures().getCodeLensFeature();
+ if (codeLens.getCommand() == null && codeLensFeature.isResolveCodeLensSupported(file)) {
// - the codelens has no command, and the language server supports codeLens/resolve
// prepare the future which resolves the codelens.
resolvedCodeLensFuture = cancellationSupport.execute(languageServer
.getTextDocumentService()
.resolveCodeLens(codeLens), languageServer, LSPRequestConstants.TEXT_DOCUMENT_RESOLVE_CODE_LENS);
}
- var codeLensFeature = languageServer.getClientFeatures().getCodeLensFeature();
if (codeLensFeature.getText(codeLens) != null || resolvedCodeLensFuture != null) {
// The codelens content is filled or the codelens must be resolved
data.add(new CodeLensData(codeLens, languageServer, resolvedCodeLensFuture));
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/color/LSPColorSupport.java b/src/main/java/com/redhat/devtools/lsp4ij/features/color/LSPColorSupport.java
index 276291843..cd17d90e3 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/color/LSPColorSupport.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/color/LSPColorSupport.java
@@ -53,8 +53,8 @@ protected CompletableFuture> doLoad(@NotNull DocumentColorParams
@NotNull CancellationSupport cancellationSupport) {
return getLanguageServers(file,
- f -> f.getColorFeature().isEnabled(file),
- f -> f.getColorFeature().isSupported(file))
+ f -> f.getDocumentColorFeature().isEnabled(file),
+ f -> f.getDocumentColorFeature().isSupported(file))
.thenComposeAsync(languageServers -> {
// Here languageServers is the list of language servers which matches the given file
// and which have color capability
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/declaration/LSPGoToDeclarationAction.java b/src/main/java/com/redhat/devtools/lsp4ij/features/declaration/LSPGoToDeclarationAction.java
index 0816ed084..fe1cbe589 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/declaration/LSPGoToDeclarationAction.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/declaration/LSPGoToDeclarationAction.java
@@ -16,11 +16,11 @@
import com.intellij.psi.PsiFile;
import com.redhat.devtools.lsp4ij.LSPFileSupport;
import com.redhat.devtools.lsp4ij.LSPIJUtils;
-import com.redhat.devtools.lsp4ij.LanguageServerItem;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
import com.redhat.devtools.lsp4ij.features.AbstractLSPGoToAction;
import com.redhat.devtools.lsp4ij.usages.LSPUsageType;
import org.eclipse.lsp4j.Location;
-import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,8 +62,8 @@ protected CompletableFuture> getLocations(PsiFile psiFile, Docume
}
@Override
- protected boolean canSupportFeature(ServerCapabilities serverCapabilities) {
- return LanguageServerItem.isDeclarationSupported(serverCapabilities);
+ protected boolean canSupportFeature(@NotNull LSPClientFeatures clientFeatures, @NotNull PsiFile file) {
+ return clientFeatures.getDeclarationFeature().isDeclarationSupported(file);
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/diagnostics/LSPDiagnosticAnnotator.java b/src/main/java/com/redhat/devtools/lsp4ij/features/diagnostics/LSPDiagnosticAnnotator.java
index 9fe6adbbb..8a74f5f7f 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/diagnostics/LSPDiagnosticAnnotator.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/diagnostics/LSPDiagnosticAnnotator.java
@@ -98,7 +98,7 @@ private static void createAnnotation(@NotNull Diagnostic diagnostic,
List fixes = Collections.emptyList();
var codeActionFeature = clientFeatures.getCodeActionFeature();
if (codeActionFeature.isQuickFixesEnabled(file)) {
- fixes = diagnosticsForServer.getQuickFixesFor(diagnostic);
+ fixes = diagnosticsForServer.getQuickFixesFor(diagnostic, file);
}
diagnosticSupport.createAnnotation(diagnostic, document, fixes, holder);
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/diagnostics/LSPDiagnosticsForServer.java b/src/main/java/com/redhat/devtools/lsp4ij/features/diagnostics/LSPDiagnosticsForServer.java
index 6cecb2c8a..d239854cb 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/diagnostics/LSPDiagnosticsForServer.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/diagnostics/LSPDiagnosticsForServer.java
@@ -15,6 +15,7 @@
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
import com.redhat.devtools.lsp4ij.LanguageServerItem;
import com.redhat.devtools.lsp4ij.LanguageServerWrapper;
import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
@@ -23,6 +24,7 @@
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.util.Ranges;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -138,10 +140,12 @@ public Set getDiagnostics() {
* Returns Intellij quickfixes for the given diagnostic if there available.
*
* @param diagnostic the diagnostic.
+ * @param file
* @return Intellij quickfixes for the given diagnostic if there available.
*/
- public List getQuickFixesFor(Diagnostic diagnostic) {
- boolean codeActionSupported = isCodeActionSupported(languageServer.getServerWrapper());
+ public List getQuickFixesFor(@NotNull Diagnostic diagnostic,
+ @NotNull PsiFile file) {
+ boolean codeActionSupported = isCodeActionSupported(languageServer.getServerWrapper(), file);
if (!codeActionSupported || diagnostics.isEmpty()) {
return Collections.emptyList();
}
@@ -149,13 +153,14 @@ public List getQuickFixesFor(Diagnostic diagnostic) {
return codeActions != null ? codeActions.getCodeActions() : Collections.emptyList();
}
- private static boolean isCodeActionSupported(LanguageServerWrapper languageServerWrapper) {
+ private static boolean isCodeActionSupported(@NotNull LanguageServerWrapper languageServerWrapper,
+ @NotNull PsiFile file) {
if (!languageServerWrapper.isActive() || languageServerWrapper.isStopping()) {
// This use-case comes from when a diagnostics is published and the language server is stopped
// We cannot use here languageServerWrapper.getServerCapabilities() otherwise it will restart the language server.
return false;
}
- return LanguageServerItem.isCodeActionSupported(languageServerWrapper.getServerCapabilities());
+ return languageServerWrapper.getClientFeatures().getCodeActionFeature().isCodeActionSupported(file);
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingAndRangeBothService.java b/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingAndRangeBothService.java
index 978a5e037..f0ae9a556 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingAndRangeBothService.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingAndRangeBothService.java
@@ -30,7 +30,7 @@ public class LSPFormattingAndRangeBothService extends AbstractLSPFormattingServi
@Override
protected boolean canSupportFormatting(LSPFormattingFeature formattingFeature, PsiFile file) {
- return formattingFeature.isDocumentRangeFormattingSupported(file);
+ return formattingFeature.isRangeFormattingSupported(file);
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingOnlyService.java b/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingOnlyService.java
index 4f3aacb41..6b1f204eb 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingOnlyService.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingOnlyService.java
@@ -31,8 +31,8 @@ public class LSPFormattingOnlyService extends AbstractLSPFormattingService {
@Override
protected boolean canSupportFormatting(LSPFormattingFeature formattingFeature, PsiFile file) {
- return formattingFeature.isDocumentFormattingSupported(file) &&
- !formattingFeature.isDocumentRangeFormattingSupported(file);
+ return formattingFeature.isFormattingSupported(file) &&
+ !formattingFeature.isRangeFormattingSupported(file);
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingSupport.java b/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingSupport.java
index 665b224f2..c29d7e1a9 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingSupport.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/formatting/LSPFormattingSupport.java
@@ -90,9 +90,9 @@ protected CompletableFuture> doLoad(LSPFormattingParams
@NotNull CancellationSupport cancellationSupport) {
boolean isRangeFormatting = params.textRange() != null;
Predicate filter = !isRangeFormatting ?
- f -> f.getFormattingFeature().isDocumentFormattingSupported(file) :
- f -> f.getFormattingFeature().isDocumentFormattingSupported(file) ||
- f.getFormattingFeature().isDocumentRangeFormattingSupported(file);
+ f -> f.getFormattingFeature().isFormattingSupported(file) :
+ f -> f.getFormattingFeature().isFormattingSupported(file) ||
+ f.getFormattingFeature().isRangeFormattingSupported(file);
return getLanguageServers(file,
f -> f.getFormattingFeature().isEnabled(file),
filter)
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/implementation/LSPGoToImplementationAction.java b/src/main/java/com/redhat/devtools/lsp4ij/features/implementation/LSPGoToImplementationAction.java
index 783f50b88..79983228f 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/implementation/LSPGoToImplementationAction.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/implementation/LSPGoToImplementationAction.java
@@ -16,11 +16,11 @@
import com.intellij.psi.PsiFile;
import com.redhat.devtools.lsp4ij.LSPFileSupport;
import com.redhat.devtools.lsp4ij.LSPIJUtils;
-import com.redhat.devtools.lsp4ij.LanguageServerItem;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
import com.redhat.devtools.lsp4ij.features.AbstractLSPGoToAction;
import com.redhat.devtools.lsp4ij.usages.LSPUsageType;
import org.eclipse.lsp4j.Location;
-import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,8 +62,8 @@ protected CompletableFuture> getLocations(PsiFile psiFile, Docume
}
@Override
- protected boolean canSupportFeature(ServerCapabilities serverCapabilities) {
- return LanguageServerItem.isImplementationSupported(serverCapabilities);
+ protected boolean canSupportFeature(@NotNull LSPClientFeatures clientFeatures, @NotNull PsiFile file) {
+ return clientFeatures.getImplementationFeature().isImplementationSupported(file);
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/inlayhint/LSPInlayHintsProvider.java b/src/main/java/com/redhat/devtools/lsp4ij/features/inlayhint/LSPInlayHintsProvider.java
index 456c9f5ec..e6a4a7391 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/inlayhint/LSPInlayHintsProvider.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/inlayhint/LSPInlayHintsProvider.java
@@ -178,7 +178,7 @@ private void executeCommand(@NotNull PsiFile psiFile,
@NotNull InlayHint inlayHint,
int index,
@Nullable MouseEvent event) {
- if (languageServer.isResolveInlayHintSupported()) {
+ if (languageServer.getClientFeatures().getInlayHintFeature().isResolveInlayHintSupported(psiFile)) {
languageServer.getTextDocumentService()
.resolveInlayHint(inlayHint)
.thenAcceptAsync(resolvedInlayHint -> {
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/inlayhint/LSPInlayHintsSupport.java b/src/main/java/com/redhat/devtools/lsp4ij/features/inlayhint/LSPInlayHintsSupport.java
index 3fdbf6e25..1a05c195b 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/inlayhint/LSPInlayHintsSupport.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/inlayhint/LSPInlayHintsSupport.java
@@ -67,7 +67,7 @@ protected CompletableFuture> doLoad(InlayHintParams params,
// Collect list of textDocument/inlayHint future for each language servers
List>> inlayHintPerServerFutures = languageServers
.stream()
- .map(languageServer -> getInlayHintsFor(params, languageServer, cancellationSupport))
+ .map(languageServer -> getInlayHintsFor(params, file, languageServer, cancellationSupport))
.toList();
// Merge list of textDocument/inlayHint future in one future which return the list of inlay hints
@@ -75,7 +75,10 @@ protected CompletableFuture> doLoad(InlayHintParams params,
});
}
- private static CompletableFuture> getInlayHintsFor(InlayHintParams params, LanguageServerItem languageServer, CancellationSupport cancellationSupport) {
+ private static CompletableFuture> getInlayHintsFor(@NotNull InlayHintParams params,
+ @NotNull PsiFile file,
+ @NotNull LanguageServerItem languageServer,
+ @NotNull CancellationSupport cancellationSupport) {
return cancellationSupport.execute(languageServer
.getTextDocumentService()
.inlayHint(params), languageServer, LSPRequestConstants.TEXT_DOCUMENT_INLAY_HINT)
@@ -89,7 +92,7 @@ private static CompletableFuture> getInlayHintsFor(InlayHint
.filter(Objects::nonNull)
.forEach(inlayHint -> {
CompletableFuture resolvedInlayHintFuture = null;
- if (inlayHint.getLabel() == null && languageServer.isResolveInlayHintSupported()) {
+ if (inlayHint.getLabel() == null && languageServer.getClientFeatures().getInlayHintFeature().isResolveInlayHintSupported(file)) {
// - the inlayHint has no label, and the language server supports inlayHint/resolve
// prepare the future which resolves the inlayHint.
resolvedInlayHintFuture = cancellationSupport.execute(languageServer
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/references/LSPGoToReferenceAction.java b/src/main/java/com/redhat/devtools/lsp4ij/features/references/LSPGoToReferenceAction.java
index 086afa359..ad8a69a64 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/references/LSPGoToReferenceAction.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/references/LSPGoToReferenceAction.java
@@ -16,11 +16,11 @@
import com.intellij.psi.PsiFile;
import com.redhat.devtools.lsp4ij.LSPFileSupport;
import com.redhat.devtools.lsp4ij.LSPIJUtils;
-import com.redhat.devtools.lsp4ij.LanguageServerItem;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
import com.redhat.devtools.lsp4ij.features.AbstractLSPGoToAction;
import com.redhat.devtools.lsp4ij.usages.LSPUsageType;
import org.eclipse.lsp4j.Location;
-import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,14 +56,14 @@ protected CompletableFuture> getLocations(PsiFile psiFile, Docume
// cancel the LSP requests textDocument/references
referenceSupport.cancel();
} catch (ExecutionException e) {
- LOGGER.error("Error while consuming LSP 'textDocument/reference' request", e);
+ LOGGER.error("Error while consuming LSP 'textDocument/references' request", e);
}
return referencesFuture;
}
@Override
- protected boolean canSupportFeature(ServerCapabilities serverCapabilities) {
- return LanguageServerItem.isReferencesSupported(serverCapabilities);
+ protected boolean canSupportFeature(@NotNull LSPClientFeatures clientFeatures, @NotNull PsiFile file) {
+ return clientFeatures.getReferencesFeature().isReferencesSupported(file);
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/rename/LSPRenameHandler.java b/src/main/java/com/redhat/devtools/lsp4ij/features/rename/LSPRenameHandler.java
index d06711b79..8824e02c0 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/rename/LSPRenameHandler.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/rename/LSPRenameHandler.java
@@ -181,7 +181,7 @@ public boolean isAvailableOnDataContext(@NotNull DataContext dataContext) {
// At this step we consider that language servers are started, we just wait for 200ms
// to avoid freezing the UI
if (LanguageServiceAccessor.getInstance(project)
- .hasAny(file.getVirtualFile(), ls -> LanguageServerItem.isRenameSupported(ls.getServerCapabilitiesSync()))) {
+ .hasAny(file.getVirtualFile(), ls -> ls.getClientFeatures().getRenameFeature().isRenameSupported(file))) {
// There is at least one language server providing rename support for the file.
try {
searchingRenameHandlers = true;
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/features/typeDefinition/LSPGoToTypeDefinitionAction.java b/src/main/java/com/redhat/devtools/lsp4ij/features/typeDefinition/LSPGoToTypeDefinitionAction.java
index fa8fe8463..933872b30 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/features/typeDefinition/LSPGoToTypeDefinitionAction.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/features/typeDefinition/LSPGoToTypeDefinitionAction.java
@@ -16,11 +16,11 @@
import com.intellij.psi.PsiFile;
import com.redhat.devtools.lsp4ij.LSPFileSupport;
import com.redhat.devtools.lsp4ij.LSPIJUtils;
-import com.redhat.devtools.lsp4ij.LanguageServerItem;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
import com.redhat.devtools.lsp4ij.features.AbstractLSPGoToAction;
import com.redhat.devtools.lsp4ij.usages.LSPUsageType;
import org.eclipse.lsp4j.Location;
-import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,8 +62,8 @@ protected CompletableFuture> getLocations(PsiFile psiFile, Docume
}
@Override
- protected boolean canSupportFeature(ServerCapabilities serverCapabilities) {
- return LanguageServerItem.isTypeDefinitionSupported(serverCapabilities);
+ protected boolean canSupportFeature(@NotNull LSPClientFeatures clientFeatures, @NotNull PsiFile file) {
+ return clientFeatures.getTypeDefinitionFeature().isTypeDefinitionSupported(file);
}
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/internal/ClientCapabilitiesFactory.java b/src/main/java/com/redhat/devtools/lsp4ij/internal/ClientCapabilitiesFactory.java
index b628d7deb..be9531b93 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/internal/ClientCapabilitiesFactory.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/internal/ClientCapabilitiesFactory.java
@@ -118,13 +118,13 @@ public static ClientCapabilities create(Object experimental) {
textDocumentClientCapabilities.setCodeAction(codeAction);
// Code Lens support
- textDocumentClientCapabilities.setCodeLens(new CodeLensCapabilities());
+ textDocumentClientCapabilities.setCodeLens(new CodeLensCapabilities(Boolean.TRUE));
// Inlay Hint support
- textDocumentClientCapabilities.setInlayHint(new InlayHintCapabilities());
+ textDocumentClientCapabilities.setInlayHint(new InlayHintCapabilities(Boolean.TRUE));
// textDocument/colorPresentation support
- textDocumentClientCapabilities.setColorProvider(new ColorProviderCapabilities());
+ textDocumentClientCapabilities.setColorProvider(new ColorProviderCapabilities(Boolean.TRUE));
// Completion support
final var completionItemCapabilities = new CompletionItemCapabilities(Boolean.TRUE);
@@ -140,10 +140,11 @@ public static ClientCapabilities create(Object experimental) {
completionItemCapabilities.setLabelDetailsSupport(Boolean.TRUE);
CompletionCapabilities completionCapabilities = new CompletionCapabilities(completionItemCapabilities);
completionCapabilities.setCompletionList(new CompletionListCapabilities(List.of("editRange")));
+ completionCapabilities.setDynamicRegistration(Boolean.TRUE);
textDocumentClientCapabilities.setCompletion(completionCapabilities);
// Signature help support
- SignatureHelpCapabilities signatureHelpCapabilities = new SignatureHelpCapabilities();
+ SignatureHelpCapabilities signatureHelpCapabilities = new SignatureHelpCapabilities(Boolean.TRUE);
SignatureInformationCapabilities signatureInformationCapabilities = new SignatureInformationCapabilities();
ParameterInformationCapabilities parameterInformationCapabilities = new ParameterInformationCapabilities();
parameterInformationCapabilities.setLabelOffsetSupport(Boolean.TRUE);
@@ -152,28 +153,28 @@ public static ClientCapabilities create(Object experimental) {
textDocumentClientCapabilities.setSignatureHelp(signatureHelpCapabilities);
// Declaration support
- final var declarationCapabilities = new DeclarationCapabilities();
+ final var declarationCapabilities = new DeclarationCapabilities(Boolean.TRUE);
declarationCapabilities.setLinkSupport(Boolean.TRUE);
textDocumentClientCapabilities.setDeclaration(declarationCapabilities);
// Definition support
- final var definitionCapabilities = new DefinitionCapabilities();
+ final var definitionCapabilities = new DefinitionCapabilities(Boolean.TRUE);
definitionCapabilities.setLinkSupport(Boolean.TRUE);
textDocumentClientCapabilities.setDefinition(definitionCapabilities);
// Type Definition support
- final var typeDefinitionCapabilities = new TypeDefinitionCapabilities();
+ final var typeDefinitionCapabilities = new TypeDefinitionCapabilities(Boolean.TRUE);
typeDefinitionCapabilities.setLinkSupport(Boolean.TRUE);
textDocumentClientCapabilities.setTypeDefinition(typeDefinitionCapabilities);
// DocumentHighlight support
- textDocumentClientCapabilities.setDocumentHighlight(new DocumentHighlightCapabilities());
+ textDocumentClientCapabilities.setDocumentHighlight(new DocumentHighlightCapabilities(Boolean.TRUE));
// DocumentLink support
- textDocumentClientCapabilities.setDocumentLink(new DocumentLinkCapabilities());
+ textDocumentClientCapabilities.setDocumentLink(new DocumentLinkCapabilities(Boolean.TRUE));
// textDocument/documentSymbol
- final var documentSymbol = new DocumentSymbolCapabilities();
+ final var documentSymbol = new DocumentSymbolCapabilities(Boolean.TRUE);
documentSymbol.setHierarchicalDocumentSymbolSupport(true);
documentSymbol.setSymbolKind(new SymbolKindCapabilities(Arrays.asList(SymbolKind.Array,
SymbolKind.Boolean, SymbolKind.Class, SymbolKind.Constant, SymbolKind.Constructor,
@@ -185,37 +186,36 @@ public static ClientCapabilities create(Object experimental) {
textDocumentClientCapabilities.setDocumentSymbol(documentSymbol);
// FoldingRange support
- textDocumentClientCapabilities.setFoldingRange(new FoldingRangeCapabilities());
-
- // Formatting support
- textDocumentClientCapabilities.setFormatting(new FormattingCapabilities(Boolean.TRUE));
- textDocumentClientCapabilities.setRangeFormatting(new RangeFormattingCapabilities(Boolean.TRUE));
+ var foldingRangeCapabilities = new FoldingRangeCapabilities();
+ foldingRangeCapabilities.setDynamicRegistration(Boolean.TRUE);
+ textDocumentClientCapabilities.setFoldingRange(foldingRangeCapabilities);
// Hover support
- final var hoverCapabilities = new HoverCapabilities();
+ final var hoverCapabilities = new HoverCapabilities(Boolean.TRUE);
hoverCapabilities.setContentFormat(List.of(MarkupKind.MARKDOWN, MarkupKind.PLAINTEXT));
textDocumentClientCapabilities.setHover(hoverCapabilities);
// References support
- textDocumentClientCapabilities.setReferences(new ReferencesCapabilities());
+ textDocumentClientCapabilities.setReferences(new ReferencesCapabilities(Boolean.TRUE));
// Implementation support
- var implementationCapabilities = new ImplementationCapabilities();
+ var implementationCapabilities = new ImplementationCapabilities(Boolean.TRUE);
implementationCapabilities.setLinkSupport(Boolean.TRUE);
textDocumentClientCapabilities.setImplementation(implementationCapabilities);
- // TODO: support onTypeFormatting
- // textDocumentClientCapabilities.setOnTypeFormatting(null); // TODO
- // TODO : support textDocument/rangeFormatting
- // textDocumentClientCapabilities.setRangeFormatting(new RangeFormattingCapabilities());
+ // textDocument/formatting
+ textDocumentClientCapabilities.setFormatting(new FormattingCapabilities(Boolean.TRUE));
+
+ // textDocument/rangeFormatting
+ textDocumentClientCapabilities.setRangeFormatting(new RangeFormattingCapabilities(Boolean.TRUE));
// textDocument/rename support
- final var renameCapabilities = new RenameCapabilities();
+ final var renameCapabilities = new RenameCapabilities(Boolean.TRUE);
renameCapabilities.setPrepareSupport(true);
textDocumentClientCapabilities.setRename(renameCapabilities);
// textDocument/semanticTokens
- var semanticTokensCapabilities = new SemanticTokensCapabilities();
+ var semanticTokensCapabilities = new SemanticTokensCapabilities(Boolean.TRUE);
semanticTokensCapabilities.setTokenTypes(List.of(
SemanticTokenTypes.Namespace,
SemanticTokenTypes.Type,
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CodeActionCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CodeActionCapabilityRegistry.java
new file mode 100644
index 000000000..bfb42a0c5
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CodeActionCapabilityRegistry.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.CodeActionOptions;
+import org.eclipse.lsp4j.CodeActionRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.eclipse.lsp4j.jsonrpc.messages.Either;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/codeAction'.
+ */
+public class CodeActionCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getCodeActionProvider());
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> RESOLVE_SERVER_CAPABILITIES_PREDICATE = sc -> {
+ Either codeActionProvider = sc.getCodeActionProvider();
+ if (codeActionProvider != null && codeActionProvider.isRight()) {
+ return hasCapability(codeActionProvider.getRight().getResolveProvider());
+ }
+ return false;
+ };
+
+ private static final @Nullable Predicate<@NotNull CodeActionRegistrationOptions> RESOLVE_REGISTRATION_OPTIONS_PREDICATE = o ->
+ hasCapability(o.getResolveProvider());
+
+
+ public CodeActionCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedCodeActionFormattingRegistrationOptions extends CodeActionRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable CodeActionRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedCodeActionFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support codeAction and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support codeAction and false otherwise.
+ */
+ public boolean isCodeActionSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+ /**
+ * Returns true if the language server can support resolve codeAction and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support resolve codeAction and false otherwise.
+ */
+ public boolean isResolveCodeActionSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, RESOLVE_SERVER_CAPABILITIES_PREDICATE, RESOLVE_REGISTRATION_OPTIONS_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CodeLensCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CodeLensCapabilityRegistry.java
new file mode 100644
index 000000000..02de0afe9
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CodeLensCapabilityRegistry.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.CodeLensRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/codeLens'.
+ */
+public class CodeLensCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ sc.getCodeLensProvider() != null;
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> RESOLVE_SERVER_CAPABILITIES_PREDICATE = sc ->
+ sc.getCodeLensProvider() != null && hasCapability(sc.getCodeLensProvider().getResolveProvider());
+
+ private static final @Nullable Predicate<@NotNull CodeLensRegistrationOptions> RESOLVE_REGISTRATION_OPTIONS_PREDICATE = o ->
+ hasCapability(o.getResolveProvider());
+
+ public CodeLensCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedCodeLensFormattingRegistrationOptions extends CodeLensRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable CodeLensRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedCodeLensFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support codeLens and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support codeLens and false otherwise.
+ */
+ public boolean isCodeLensSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+ /**
+ * Returns true if the language server can support resolve code lens and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support resolve code lens and false otherwise.
+ */
+ public boolean isResolveCodeLensSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, RESOLVE_SERVER_CAPABILITIES_PREDICATE, RESOLVE_REGISTRATION_OPTIONS_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CompletionCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CompletionCapabilityRegistry.java
new file mode 100644
index 000000000..85e5ba16b
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/CompletionCapabilityRegistry.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.CompletionRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/completion'.
+ */
+public class CompletionCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ sc.getCompletionProvider() != null;
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> RESOLVE_SERVER_CAPABILITIES_PREDICATE = sc ->
+ sc.getCompletionProvider() != null && hasCapability(sc.getCompletionProvider().getResolveProvider());
+
+ private static final @Nullable Predicate<@NotNull CompletionRegistrationOptions> RESOLVE_REGISTRATION_OPTIONS_PREDICATE = o ->
+ hasCapability(o.getResolveProvider());
+
+ public CompletionCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedCompletionFormattingRegistrationOptions extends CompletionRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable CompletionRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedCompletionFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support completion and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support completion and false otherwise.
+ */
+ public boolean isCompletionSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+ /**
+ * Returns true if the language server can support resolve completion and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support resolve completion and false otherwise.
+ */
+ public boolean isResolveCompletionSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, RESOLVE_SERVER_CAPABILITIES_PREDICATE, RESOLVE_REGISTRATION_OPTIONS_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DeclarationCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DeclarationCapabilityRegistry.java
new file mode 100644
index 000000000..1c30d21f7
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DeclarationCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.DeclarationRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/declaration'.
+ */
+public class DeclarationCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getDeclarationProvider());
+
+ public DeclarationCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedDeclarationRegistrationOptions extends DeclarationRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable DeclarationRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedDeclarationRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support declaration and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support declaration and false otherwise.
+ */
+ public boolean isDeclarationSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DefinitionCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DefinitionCapabilityRegistry.java
new file mode 100644
index 000000000..1c5558989
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DefinitionCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.DefinitionRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/definition'.
+ */
+public class DefinitionCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getDefinitionProvider());
+
+ public DefinitionCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedDefinitionRegistrationOptions extends DefinitionRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable DefinitionRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedDefinitionRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support definition and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support definition and false otherwise.
+ */
+ public boolean isDefinitionSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentColorCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentColorCapabilityRegistry.java
new file mode 100644
index 000000000..7e9153481
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentColorCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.ColorProviderOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/documentColor'.
+ */
+public class DocumentColorCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getColorProvider());
+
+ public DocumentColorCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedColorFormattingRegistrationOptions extends ColorProviderOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable ColorProviderOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedColorFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support documentColor and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support documentColor and false otherwise.
+ */
+ public boolean isDocumentColorSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentFormattingCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentFormattingCapabilityRegistry.java
new file mode 100644
index 000000000..591999f31
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentFormattingCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.DocumentFormattingRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/formatting'.
+ */
+public class DocumentFormattingCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getDocumentFormattingProvider());
+
+ public DocumentFormattingCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedDocumentFormattingRegistrationOptions extends DocumentFormattingRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable DocumentFormattingRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedDocumentFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support formatting and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support formatting and false otherwise.
+ */
+ public boolean isFormattingSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentHighlightCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentHighlightCapabilityRegistry.java
new file mode 100644
index 000000000..6236e5ca9
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentHighlightCapabilityRegistry.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.DocumentHighlightRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/documentHighlight'.
+ */
+public class DocumentHighlightCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ sc.getDocumentHighlightProvider() != null && hasCapability(sc.getDocumentHighlightProvider());
+
+ public DocumentHighlightCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedDocumentHighlightingFormattingRegistrationOptions extends DocumentHighlightRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+
+ }
+
+ @Override
+ protected @Nullable DocumentHighlightRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedDocumentHighlightingFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support documentDeclaration and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support documentDeclaration and false otherwise.
+ */
+ public boolean isDocumentHighlightSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentLinkCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentLinkCapabilityRegistry.java
new file mode 100644
index 000000000..cfb6e5745
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentLinkCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.DocumentLinkRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/documentLink'.
+ */
+public class DocumentLinkCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ sc.getDocumentLinkProvider() != null;
+
+ public DocumentLinkCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedLinkFormattingRegistrationOptions extends DocumentLinkRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable DocumentLinkRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedLinkFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support documentLink and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support documentLink and false otherwise.
+ */
+ public boolean isDocumentLinkSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentRangeFormattingCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentRangeFormattingCapabilityRegistry.java
new file mode 100644
index 000000000..41918a376
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentRangeFormattingCapabilityRegistry.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.DocumentRangeFormattingRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/rangeFormatting'.
+ */
+public class DocumentRangeFormattingCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getDocumentRangeFormattingProvider());
+
+ public DocumentRangeFormattingCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedDocumentRangeFormattingRegistrationOptions extends DocumentRangeFormattingRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+
+ @Override
+ protected @Nullable DocumentRangeFormattingRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedDocumentRangeFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support rangeFormatting and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support rangeFormatting and false otherwise.
+ */
+ public boolean isRangeFormattingSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentSymbolCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentSymbolCapabilityRegistry.java
new file mode 100644
index 000000000..9e05c14ea
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/DocumentSymbolCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.DocumentSymbolRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/documentSymbol'.
+ */
+public class DocumentSymbolCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getDocumentSymbolProvider());
+
+ public DocumentSymbolCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedSymbolFormattingRegistrationOptions extends DocumentSymbolRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable DocumentSymbolRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedSymbolFormattingRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support documentSymbol and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support documentSymbol and false otherwise.
+ */
+ public boolean isDocumentSymbolSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ExtendedDocumentSelector.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ExtendedDocumentSelector.java
new file mode 100644
index 000000000..8b798587f
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ExtendedDocumentSelector.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.redhat.devtools.lsp4ij.features.files.PathPatternMatcher;
+import com.redhat.devtools.lsp4ij.internal.StringUtils;
+import org.eclipse.lsp4j.DocumentFilter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Extended documentSelector.
+ */
+public class ExtendedDocumentSelector {
+
+ interface DocumentFilersProvider {
+ List getFilters();
+ }
+
+ @NotNull
+ private final List filters;
+
+ public class ExtendedDocumentFilter extends DocumentFilter {
+
+ private PathPatternMatcher patternMatcher;
+
+ public ExtendedDocumentFilter(DocumentFilter filter) {
+ super.setLanguage(filter.getLanguage());
+ super.setScheme(filter.getScheme());
+ super.setPattern(filter.getPattern());
+ }
+
+ @Nullable
+ public PathPatternMatcher getPathPattern() {
+ if (patternMatcher != null) {
+ return patternMatcher;
+ }
+ String pattern = super.getPattern();
+ if (StringUtils.isEmpty(pattern)) {
+ return null;
+ }
+ patternMatcher = new PathPatternMatcher(pattern);
+ return patternMatcher;
+ }
+ }
+
+ public ExtendedDocumentSelector(List documentSelector) {
+ this.filters = documentSelector != null ?
+ documentSelector
+ .stream()
+ .filter(f -> !(StringUtils.isEmpty(f.getLanguage()) && StringUtils.isEmpty(f.getPattern()) && StringUtils.isEmpty(f.getScheme())))
+ .map(f -> new ExtendedDocumentFilter(f))
+ .toList() :
+ Collections.emptyList();
+ }
+
+ public @NotNull List getFilters() {
+ return filters;
+ }
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/FoldingRangeCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/FoldingRangeCapabilityRegistry.java
new file mode 100644
index 000000000..8f905cfba
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/FoldingRangeCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.FoldingRangeProviderOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/foldingRange'.
+ */
+public class FoldingRangeCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getFoldingRangeProvider());
+
+ public FoldingRangeCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedFoldingRangeProviderOptions extends FoldingRangeProviderOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable FoldingRangeProviderOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedFoldingRangeProviderOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support foldingRange and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support foldingRange and false otherwise.
+ */
+ public boolean isFoldingRangeSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/HoverCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/HoverCapabilityRegistry.java
new file mode 100644
index 000000000..fb080a81d
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/HoverCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.HoverRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/hover'.
+ */
+public class HoverCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getHoverProvider());
+
+ public HoverCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedHoverRegistrationOptions extends HoverRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable HoverRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedHoverRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support hover and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support hover and false otherwise.
+ */
+ public boolean isHoverSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ImplementationCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ImplementationCapabilityRegistry.java
new file mode 100644
index 000000000..239aafc37
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ImplementationCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.ImplementationRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/implementation'.
+ */
+public class ImplementationCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getImplementationProvider());
+
+ public ImplementationCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedImplementationRegistrationOptions extends ImplementationRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable ImplementationRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedImplementationRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support implementation and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support implementation and false otherwise.
+ */
+ public boolean isImplementationSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/InlayHintCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/InlayHintCapabilityRegistry.java
new file mode 100644
index 000000000..a876e436a
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/InlayHintCapabilityRegistry.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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 inlayHint
+ ******************************************************************************/
+package com.redhat.devtools.lsp4ij.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.InlayHintRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/inlayHint'.
+ */
+public class InlayHintCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getInlayHintProvider());
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> RESOLVE_SERVER_CAPABILITIES_PREDICATE = sc -> {
+ var inlayHintProvider =sc.getInlayHintProvider();
+ if (inlayHintProvider != null && inlayHintProvider.isRight()) {
+ return hasCapability(inlayHintProvider.getRight().getResolveProvider());
+ }
+ return false;
+ };
+
+ private static final @Nullable Predicate<@NotNull InlayHintRegistrationOptions> RESOLVE_REGISTRATION_OPTIONS_PREDICATE = o ->
+ hasCapability(o.getResolveProvider());
+
+ public InlayHintCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedInlayHintRegistrationOptions extends InlayHintRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable InlayHintRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedInlayHintRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support inlayHint and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support inlayHint and false otherwise.
+ */
+ public boolean isInlayHintSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+ /**
+ * Returns true if the language server can support resolve inlayHint and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support resolve inlayHint and false otherwise.
+ */
+ public boolean isResolveInlayHintSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, RESOLVE_SERVER_CAPABILITIES_PREDICATE, RESOLVE_REGISTRATION_OPTIONS_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ReferencesCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ReferencesCapabilityRegistry.java
new file mode 100644
index 000000000..471f61978
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/ReferencesCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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 references
+ ******************************************************************************/
+package com.redhat.devtools.lsp4ij.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.ReferenceRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/references'.
+ */
+public class ReferencesCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getReferencesProvider());
+
+ public ReferencesCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedReferenceRegistrationOptions extends ReferenceRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable ReferenceRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedReferenceRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support references and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support references and false otherwise.
+ */
+ public boolean isReferencesSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/RenameCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/RenameCapabilityRegistry.java
new file mode 100644
index 000000000..f77991621
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/RenameCapabilityRegistry.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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 rename
+ ******************************************************************************/
+package com.redhat.devtools.lsp4ij.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.RenameOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.eclipse.lsp4j.jsonrpc.messages.Either;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/rename'.
+ */
+public class RenameCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getRenameProvider());
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> PREPARE_RENAME_SERVER_CAPABILITIES_PREDICATE = sc -> {
+ Either renameProvider =sc.getRenameProvider();
+ if (renameProvider != null && renameProvider.isRight()) {
+ return hasCapability(renameProvider.getRight().getPrepareProvider());
+ }
+ return false;
+ };
+
+ private static final @Nullable Predicate<@NotNull RenameOptions> PREPARE_RENAME_REGISTRATION_OPTIONS_PREDICATE = o ->
+ hasCapability(o.getPrepareProvider());
+
+ public RenameCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedRenameOptions extends RenameOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable RenameOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedRenameOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support rename and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support rename and false otherwise.
+ */
+ public boolean isRenameSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+ /**
+ * Returns true if the language server can support prepareRename and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support prepareRename and false otherwise.
+ */
+ public boolean isPrepareRenameSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, PREPARE_RENAME_SERVER_CAPABILITIES_PREDICATE, PREPARE_RENAME_REGISTRATION_OPTIONS_PREDICATE);
+ }
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/SignatureHelpCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/SignatureHelpCapabilityRegistry.java
new file mode 100644
index 000000000..8202596c1
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/SignatureHelpCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.SignatureHelpRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/signatureHelp'.
+ */
+public class SignatureHelpCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ sc.getSignatureHelpProvider() != null;
+
+ public SignatureHelpCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedSignatureHelpRegistrationOptions extends SignatureHelpRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable SignatureHelpRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedSignatureHelpRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support signatureHelp and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support signatureHelp and false otherwise.
+ */
+ public boolean isSignatureHelpSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/TextDocumentServerCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/TextDocumentServerCapabilityRegistry.java
new file mode 100644
index 000000000..1d3d59fee
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/TextDocumentServerCapabilityRegistry.java
@@ -0,0 +1,149 @@
+package com.redhat.devtools.lsp4ij.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.LSPIJUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import com.redhat.devtools.lsp4ij.features.files.PathPatternMatcher;
+import com.redhat.devtools.lsp4ij.internal.StringUtils;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.eclipse.lsp4j.TextDocumentRegistrationOptions;
+import org.eclipse.lsp4j.jsonrpc.messages.Either;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+public abstract class TextDocumentServerCapabilityRegistry {
+
+ private final @NotNull LSPClientFeatures clientFeatures;
+ private @Nullable ServerCapabilities serverCapabilities;
+
+ private final List dynamicCapabilities;
+
+ public TextDocumentServerCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ this.clientFeatures = clientFeatures;
+ this.dynamicCapabilities = new ArrayList<>();
+ }
+
+ public void setServerCapabilities(@Nullable ServerCapabilities serverCapabilities) {
+ this.serverCapabilities = serverCapabilities;
+ this.dynamicCapabilities.clear();
+ }
+
+ public @Nullable ServerCapabilities getServerCapabilities() {
+ return serverCapabilities;
+ }
+
+ @Nullable
+ public T registerCapability(JsonObject json) {
+ T t = create(json);
+ if (t != null) {
+ dynamicCapabilities.add(t);
+ }
+ return t;
+ }
+
+ @Nullable
+ protected abstract T create(JsonObject json);
+
+ public void unregisterCapability(Object options) {
+ dynamicCapabilities.remove(options);
+ }
+
+ protected boolean isSupported(@NotNull PsiFile file,
+ @NotNull Predicate<@NotNull ServerCapabilities> matchServerCapabilities) {
+ return isSupported(file, matchServerCapabilities, null);
+ }
+
+ protected boolean isSupported(@NotNull PsiFile file,
+ @NotNull Predicate<@NotNull ServerCapabilities> matchServerCapabilities,
+ @Nullable Predicate<@NotNull T> matchOption) {
+ var serverCapabilities = getServerCapabilities();
+ if (serverCapabilities != null && matchServerCapabilities.test(serverCapabilities)) {
+ return true;
+ }
+
+ if (dynamicCapabilities.isEmpty()) {
+ return false;
+ }
+
+ boolean languageIdGet = false;
+ String languageId = null;
+ URI fileUri = null;
+ String scheme = null;
+ for (var option : dynamicCapabilities) {
+ // Match documentSelector?
+ var filters = ((ExtendedDocumentSelector.DocumentFilersProvider) option).getFilters();
+ if (filters.isEmpty()) {
+ return matchOption != null ? matchOption.test(option) : true;
+ }
+ for (var filter : filters) {
+ boolean hasLanguage = !StringUtils.isEmpty(filter.getLanguage());
+ boolean hasScheme = !StringUtils.isEmpty(filter.getScheme());
+ boolean hasPattern = !StringUtils.isEmpty(filter.getPattern());
+
+ boolean matchDocumentSelector = false;
+ // Matches language?
+ if (hasLanguage) {
+ if (!languageIdGet) {
+ languageId = clientFeatures.getServerDefinition().getLanguageIdOrNull(file);
+ languageIdGet = true;
+ }
+ matchDocumentSelector = (languageId == null && !hasScheme && !hasPattern) // to be compatible with LSP4IJ < 0.7.0, when languageId is not defined in the mapping, we consider that it matches the documentSelector
+ || filter.getLanguage().equals(languageId);
+ }
+
+ if (!matchDocumentSelector) {
+ // Matches scheme?
+ if (hasScheme) {
+ if (fileUri == null) {
+ fileUri = LSPIJUtils.toUri(file); // TODO: move this file Uri into LSP client features to customize the file Uri
+ }
+ if (scheme == null) {
+ scheme = fileUri.getScheme();
+ }
+ matchDocumentSelector = filter.getScheme().equals(scheme);
+ }
+
+ if (!matchDocumentSelector) {
+
+ // Matches pattern?
+ if (hasPattern) {
+ PathPatternMatcher patternMatcher = filter.getPathPattern();
+ if (fileUri == null) {
+ fileUri = LSPIJUtils.toUri(file); // TODO: move this file Uri into LSP client features to customize the file Uri
+ }
+ matchDocumentSelector = patternMatcher.matches(fileUri);
+ }
+ }
+ }
+
+ if (matchDocumentSelector) {
+ if (matchOption == null) {
+ return true;
+ }
+ if (matchOption.test(option)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean hasCapability(final Either eitherCapability) {
+ if (eitherCapability == null) {
+ return false;
+ }
+ return eitherCapability.isRight() || hasCapability(eitherCapability.getLeft());
+ }
+
+ public static boolean hasCapability(Boolean capability) {
+ return capability != null && capability;
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/TypeDefinitionCapabilityRegistry.java b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/TypeDefinitionCapabilityRegistry.java
new file mode 100644
index 000000000..3f102e871
--- /dev/null
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/capabilities/TypeDefinitionCapabilityRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.server.capabilities;
+
+import com.google.gson.JsonObject;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.JSONUtils;
+import com.redhat.devtools.lsp4ij.client.features.LSPClientFeatures;
+import org.eclipse.lsp4j.TypeDefinitionRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Server capability registry for 'textDocument/typeDefinition'.
+ */
+public class TypeDefinitionCapabilityRegistry extends TextDocumentServerCapabilityRegistry {
+
+ private static final @NotNull Predicate<@NotNull ServerCapabilities> SERVER_CAPABILITIES_PREDICATE = sc ->
+ hasCapability(sc.getTypeDefinitionProvider());
+
+ public TypeDefinitionCapabilityRegistry(@NotNull LSPClientFeatures clientFeatures) {
+ super(clientFeatures);
+ }
+
+ class ExtendedTypeDefinitionRegistrationOptions extends TypeDefinitionRegistrationOptions implements ExtendedDocumentSelector.DocumentFilersProvider {
+ private transient ExtendedDocumentSelector documentSelector;
+
+ @Override
+ public List getFilters() {
+ if (documentSelector == null) {
+ documentSelector = new ExtendedDocumentSelector(super.getDocumentSelector());
+ }
+ return documentSelector.getFilters();
+ }
+ }
+
+ @Override
+ protected @Nullable TypeDefinitionRegistrationOptions create(JsonObject json) {
+ return JSONUtils.getLsp4jGson()
+ .fromJson(json,
+ ExtendedTypeDefinitionRegistrationOptions.class);
+ }
+
+ /**
+ * Returns true if the language server can support typeDefinition and false otherwise.
+ *
+ * @param file the Psi file.
+ * @return true if the language server can support typeDefinition and false otherwise.
+ */
+ public boolean isTypeDefinitionSupported(@NotNull PsiFile file) {
+ return super.isSupported(file, SERVER_CAPABILITIES_PREDICATE);
+ }
+
+}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/server/definition/LanguageServerDefinition.java b/src/main/java/com/redhat/devtools/lsp4ij/server/definition/LanguageServerDefinition.java
index 0e0a898a8..67657f3bd 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/server/definition/LanguageServerDefinition.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/server/definition/LanguageServerDefinition.java
@@ -18,8 +18,12 @@
import com.intellij.lang.Language;
import com.intellij.openapi.fileTypes.FileNameMatcher;
import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.redhat.devtools.lsp4ij.LSPIJUtils;
import com.redhat.devtools.lsp4ij.LanguageServerEnablementSupport;
import com.redhat.devtools.lsp4ij.LanguageServerFactory;
import com.redhat.devtools.lsp4ij.features.semanticTokens.DefaultSemanticTokensColorsProvider;
@@ -165,9 +169,7 @@ public void registerAssociation(List matchers, String languageI
this.languageIdFileNameMatcherMappings.add(Pair.create(matchers, languageId));
}
- public @Nullable String getLanguageId(Language language) {
- return languageIdLanguageMappings.get(language);
- }
+
public Map getLanguageMappings() {
return languageIdLanguageMappings;
@@ -181,21 +183,6 @@ public List, String>> getFilenameMatcherMappings() {
return languageIdFileNameMatcherMappings;
}
- public @Nullable String getLanguageId(FileType fileType) {
- return languageIdFileTypeMappings.get(fileType);
- }
-
- public @Nullable String getLanguageId(String filename) {
- for (var mapping : languageIdFileNameMatcherMappings) {
- for (var matcher : mapping.getFirst()) {
- if (matcher.acceptsCharSequence(filename)) {
- return mapping.getSecond();
- }
- }
- }
- return null;
- }
-
public Launcher.Builder createLauncherBuilder() {
return new Launcher.Builder<>();
}
@@ -217,4 +204,147 @@ public SemanticTokensColorsProvider getSemanticTokensColorsProvider() {
public void setSemanticTokensColorsProvider(@NotNull SemanticTokensColorsProvider semanticTokensColorsProvider) {
this.semanticTokensColorsProvider = semanticTokensColorsProvider;
}
+
+ /**
+ * Returns the LSP language id defined in mapping otherwise null.
+ *
+ * @param file the PsiFile file.
+ * @return the LSP language id or null.
+ */
+ @Nullable
+ public String getLanguageIdOrNull(@NotNull PsiFile file) {
+ return getLanguageId(file.getLanguage(), file.getFileType(), file.getName(), true);
+ }
+
+ /**
+ * Returns the LSP language id defined in mapping otherwise the {@link Language#getID()} otherwise the {@link FileType#getName()} otherwise 'unknown'.
+ *
+ * @param file the PsiFile file.
+ * @return the LSP language id.
+ */
+ @NotNull
+ public String getLanguageId(@NotNull PsiFile file) {
+ return getLanguageId(file.getLanguage(), file.getFileType(), file.getName());
+ }
+
+ /**
+ * Returns the LSP language id defined in mapping otherwise the {@link Language#getID()} otherwise the {@link FileType#getName()} otherwise 'unknown'.
+ *
+ * @param file the virtual file.
+ * @param project the project.
+ * @return the LSP language id.
+ */
+ @NotNull
+ public String getLanguageId(@Nullable VirtualFile file,
+ @NotNull Project project) {
+ if (file == null) {
+ return FileTypes.UNKNOWN.getName().toLowerCase();
+ }
+ Language language = LSPIJUtils.getFileLanguage(file, project);
+ return getLanguageId(language, file.getFileType(), file.getName());
+ }
+
+ /**
+ * Returns the LSP language id defined in mapping otherwise the {@link Language#getID()} otherwise the {@link FileType#getName()} otherwise 'unknown'.
+ *
+ * @param language the language.
+ * @param fileType the file type.
+ * @param fileName the file name.
+ * @return the LSP language id.
+ */
+ @NotNull
+ public String getLanguageId(@Nullable Language language,
+ @Nullable FileType fileType,
+ @NotNull String fileName) {
+ return getLanguageId(language, fileType, fileName, false);
+ }
+ /**
+ * Returns the LSP language id defined in mapping otherwise the {@link Language#getID()} otherwise the {@link FileType#getName()} otherwise 'unknown'.
+ *
+ * @param language the language.
+ * @param fileType the file type.
+ * @param fileName the file name.
+ * @param nullIfNotFound returns null if not found.
+ * @return the LSP language id.
+ */
+ @Nullable
+ private String getLanguageId(@Nullable Language language,
+ @Nullable FileType fileType,
+ @NotNull String fileName,
+ boolean nullIfNotFound) {
+ // 1. Try to get the LSP languageId by using language mapping
+ String languageId = getLanguageId(language);
+ if (languageId != null) {
+ return languageId;
+ }
+
+ // 2. Try to get the LSP languageId by using the fileType mapping
+ languageId = getLanguageId(fileType);
+ if (languageId != null) {
+ return languageId;
+ }
+
+ // 3. Try to get the LSP languageId by using the file name pattern mapping
+ languageId = getLanguageId(fileName);
+ if (languageId != null) {
+ return languageId;
+ }
+
+ // At this step there is no mapping
+ if (nullIfNotFound) {
+ return null;
+ }
+
+ // We return the language Id if it exists or file type name
+ // with 'lower case' to try to map the recommended languageId specified at
+ // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem
+ if (language != null) {
+ // The language exists, use its ID with lower case
+ return language.getID().toLowerCase();
+ }
+ // Returns the existing file type or 'unknown' with lower case
+ return fileName.toLowerCase();
+ }
+
+ /**
+ * @return The language ID that this wrapper is dealing with if defined in the
+ * language mapping for the language server
+ */
+ @Nullable
+ public String getLanguageId(@Nullable Language language) {
+ while (language != null) {
+ String languageId = languageIdLanguageMappings.get(language);
+ if (languageId != null) {
+ return languageId;
+ }
+ language = language.getBaseLanguage();
+ }
+ return null;
+ }
+
+ /**
+ * @return The language ID that this wrapper is dealing with if defined in the
+ * file type mapping for the language server
+ */
+ @Nullable
+ public String getLanguageId(@Nullable FileType fileType) {
+ if (fileType == null) {
+ return null;
+ }
+ return languageIdLanguageMappings.get(fileType);
+ }
+ /**
+ * @return The language ID that this wrapper is dealing with if defined in the
+ * file type mapping for the language server
+ */
+ public @Nullable String getLanguageId(String filename) {
+ for (var mapping : languageIdFileNameMatcherMappings) {
+ for (var matcher : mapping.getFirst()) {
+ if (matcher.acceptsCharSequence(filename)) {
+ return mapping.getSecond();
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPUsageSupport.java b/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPUsageSupport.java
index 5b9221d51..523d52112 100644
--- a/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPUsageSupport.java
+++ b/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPUsageSupport.java
@@ -77,8 +77,9 @@ protected CompletableFuture> doLoad(LSPUsageSupportPara
List>> allFutures = new ArrayList<>();
for (var ls : languageServers) {
+ var clientFeature = ls.getClientFeatures();
// Collect declarations
- if (ls.isDeclarationSupported()) {
+ if (clientFeature.getDeclarationFeature().isDeclarationSupported(file)) {
allFutures.add(
cancellationSupport.execute(ls
.getTextDocumentService()
@@ -88,7 +89,7 @@ protected CompletableFuture> doLoad(LSPUsageSupportPara
}
// Collect definitions
- if (ls.isDefinitionSupported()) {
+ if (clientFeature.getDefinitionFeature().isDefinitionSupported(file)) {
allFutures.add(
cancellationSupport.execute(ls
.getTextDocumentService()
@@ -98,7 +99,7 @@ protected CompletableFuture> doLoad(LSPUsageSupportPara
}
// Collect type definitions
- if (ls.isTypeDefinitionSupported()) {
+ if (clientFeature.getTypeDefinitionFeature().isTypeDefinitionSupported(file)) {
allFutures.add(
cancellationSupport.execute(ls
.getTextDocumentService()
@@ -108,7 +109,7 @@ protected CompletableFuture> doLoad(LSPUsageSupportPara
}
// Collect references
- if (ls.isReferencesSupported()) {
+ if (clientFeature.getReferencesFeature().isReferencesSupported(file)) {
allFutures.add(
cancellationSupport.execute(ls
.getTextDocumentService()
@@ -118,7 +119,7 @@ protected CompletableFuture> doLoad(LSPUsageSupportPara
}
// Collect implementation
- if (ls.isImplementationSupported()) {
+ if (clientFeature.getImplementationFeature().isImplementationSupported(file)) {
allFutures.add(
cancellationSupport.execute(ls
.getTextDocumentService()