diff --git a/qute.ls/com.redhat.qute.ls/pom.xml b/qute.ls/com.redhat.qute.ls/pom.xml index ec9e074ca..286a7345a 100644 --- a/qute.ls/com.redhat.qute.ls/pom.xml +++ b/qute.ls/com.redhat.qute.ls/pom.xml @@ -38,7 +38,7 @@ 11 yyyyMMdd-HHmm ${maven.build.timestamp} - 0.24.0 + 1.0.0 3.30.1 5.6.1 2.18.2 diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/AbstractTextDocumentService.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/AbstractTextDocumentService.java index 4c4543ad8..6eee5b3e6 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/AbstractTextDocumentService.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/AbstractTextDocumentService.java @@ -37,6 +37,9 @@ import org.eclipse.lsp4j.HoverParams; import org.eclipse.lsp4j.InlayHint; import org.eclipse.lsp4j.InlayHintParams; +import org.eclipse.lsp4j.InlineCompletionItem; +import org.eclipse.lsp4j.InlineCompletionList; +import org.eclipse.lsp4j.InlineCompletionParams; import org.eclipse.lsp4j.LinkedEditingRangeParams; import org.eclipse.lsp4j.LinkedEditingRanges; import org.eclipse.lsp4j.Location; @@ -205,6 +208,12 @@ public CompletableFuture semanticTokensFull(SemanticTokensParams return CompletableFuture.completedFuture(null); } + @Override + public CompletableFuture, InlineCompletionList>> inlineCompletion( + InlineCompletionParams params) { + return CompletableFuture.completedFuture(null); + } + public boolean isHierarchicalDocumentSymbolSupport() { return hierarchicalDocumentSymbolSupport; } diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteTextDocumentService.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteTextDocumentService.java index f3ed57761..284e10c35 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteTextDocumentService.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/QuteTextDocumentService.java @@ -43,6 +43,9 @@ import org.eclipse.lsp4j.HoverParams; import org.eclipse.lsp4j.InlayHint; import org.eclipse.lsp4j.InlayHintParams; +import org.eclipse.lsp4j.InlineCompletionItem; +import org.eclipse.lsp4j.InlineCompletionList; +import org.eclipse.lsp4j.InlineCompletionParams; import org.eclipse.lsp4j.LinkedEditingRangeParams; import org.eclipse.lsp4j.LinkedEditingRanges; import org.eclipse.lsp4j.Location; @@ -305,6 +308,16 @@ public CompletableFuture semanticTokensFull(SemanticTokensParams return CompletableFuture.completedFuture(null); } + @Override + public CompletableFuture, InlineCompletionList>> inlineCompletion( + InlineCompletionParams params) { + AbstractTextDocumentService service = getTextDocumentService(params.getTextDocument()); + if (service != null) { + return service.inlineCompletion(params); + } + return CompletableFuture.completedFuture(null); + } + public AbstractTextDocumentService getTextDocumentService(TextDocumentIdentifier document) { return getTextDocumentService(document.getUri()); } diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/CodeActionFactory.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/CodeActionFactory.java index fb6d776f5..9ea2bda7f 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/CodeActionFactory.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/ls/commons/CodeActionFactory.java @@ -27,6 +27,7 @@ import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.ResourceOperation; +import org.eclipse.lsp4j.SnippetTextEdit; import org.eclipse.lsp4j.TextDocumentEdit; import org.eclipse.lsp4j.TextDocumentItem; import org.eclipse.lsp4j.TextEdit; @@ -97,7 +98,11 @@ public static TextEdit insertEdit(String insertText, Position position) { public static TextDocumentEdit insertEdits(TextDocumentItem document, List edits) { VersionedTextDocumentIdentifier versionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier( document.getUri(), document.getVersion()); - return new TextDocumentEdit(versionedTextDocumentIdentifier, edits); + List> editList = new ArrayList<>(); + for (TextEdit edit : edits) { + editList.add(Either.forLeft(edit)); + } + return new TextDocumentEdit(versionedTextDocumentIdentifier, editList); } public static CodeAction replace(String title, Range range, String replaceText, TextDocumentItem document, @@ -115,7 +120,11 @@ public static CodeAction replace(String title, List replace, TextDocum VersionedTextDocumentIdentifier versionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier( document.getUri(), document.getVersion()); - TextDocumentEdit textDocumentEdit = new TextDocumentEdit(versionedTextDocumentIdentifier, replace); + List> editList = new ArrayList<>(); + for (TextEdit edit : replace) { + editList.add(Either.forLeft(edit)); + } + TextDocumentEdit textDocumentEdit = new TextDocumentEdit(versionedTextDocumentIdentifier, editList); WorkspaceEdit workspaceEdit = new WorkspaceEdit(Collections.singletonList(Either.forLeft(textDocumentEdit))); insertContentAction.setEdit(workspaceEdit); return insertContentAction; @@ -129,10 +138,10 @@ public static CodeAction replaceAt(String title, String replaceText, TextDocumen VersionedTextDocumentIdentifier versionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier( document.getUri(), document.getVersion()); - List edits = new ArrayList<>(); + List> edits = new ArrayList<>(); for (Range range : ranges) { TextEdit edit = new TextEdit(range, replaceText); - edits.add(edit); + edits.add(Either.forLeft(edit)); } TextDocumentEdit textDocumentEdit = new TextDocumentEdit(versionedTextDocumentIdentifier, edits); WorkspaceEdit workspaceEdit = new WorkspaceEdit(Collections.singletonList(Either.forLeft(textDocumentEdit))); @@ -159,7 +168,7 @@ public static CodeAction createFile(String title, String docURI, String content, // 2. update the created file with the given content VersionedTextDocumentIdentifier identifier = new VersionedTextDocumentIdentifier(docURI, 0); TextEdit te = new TextEdit(new Range(new Position(0, 0), new Position(0, 0)), content); - actionsToTake.add(Either.forLeft(new TextDocumentEdit(identifier, Collections.singletonList(te)))); + actionsToTake.add(Either.forLeft(new TextDocumentEdit(identifier, Collections.singletonList(Either.forLeft(te))))); WorkspaceEdit createAndAddContentEdit = new WorkspaceEdit(actionsToTake); diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ClientCapabilitiesWrapper.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ClientCapabilitiesWrapper.java index fd8902e58..446bffabf 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ClientCapabilitiesWrapper.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ClientCapabilitiesWrapper.java @@ -101,6 +101,10 @@ public boolean isInlayHintDynamicRegistered() { return v3Supported && isDynamicRegistrationSupported(getTextDocument().getInlayHint()); } + public boolean isInlineCompletionDynamicRegistered() { + return v3Supported && isDynamicRegistrationSupported(getTextDocument().getInlineCompletion()); + } + public boolean isRenameDynamicRegistered() { return v3Supported && isDynamicRegistrationSupported(getTextDocument().getRename()); } diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/QuteCapabilityManager.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/QuteCapabilityManager.java index 8bb770a0a..479bd9cb0 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/QuteCapabilityManager.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/QuteCapabilityManager.java @@ -23,6 +23,7 @@ import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.DOCUMENT_SYMBOL_ID; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.HOVER_ID; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.INLAY_HINT_ID; +import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.INLINE_COMPLETION_ID; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.LINKED_EDITING_RANGE_ID; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.REFERENCES_ID; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.RENAME_ID; @@ -36,6 +37,7 @@ import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.TEXT_DOCUMENT_HIGHLIGHT; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.TEXT_DOCUMENT_HOVER; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.TEXT_DOCUMENT_INLAY_HINT; +import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.TEXT_DOCUMENT_INLINE_COMPLETION; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.TEXT_DOCUMENT_LINKED_EDITING_RANGE; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.TEXT_DOCUMENT_REFERENCES; import static com.redhat.qute.settings.capabilities.ServerCapabilitiesConstants.TEXT_DOCUMENT_RENAME; @@ -65,6 +67,7 @@ import org.eclipse.lsp4j.FileSystemWatcher; import org.eclipse.lsp4j.HoverRegistrationOptions; import org.eclipse.lsp4j.InlayHintRegistrationOptions; +import org.eclipse.lsp4j.InlineCompletionRegistrationOptions; import org.eclipse.lsp4j.LinkedEditingRangeRegistrationOptions; import org.eclipse.lsp4j.ReferenceRegistrationOptions; import org.eclipse.lsp4j.Registration; @@ -155,6 +158,11 @@ public void initializeCapabilities() { registerCapability(INLAY_HINT_ID, TEXT_DOCUMENT_INLAY_HINT, new InlayHintRegistrationOptions(), QuteLanguageIds.QUTE_ALL); } + if (this.getClientCapabilities().isInlineCompletionDynamicRegistered()) { + // Inline Completion is only available for Qute templates + registerCapability(INLINE_COMPLETION_ID, TEXT_DOCUMENT_INLINE_COMPLETION, new InlineCompletionRegistrationOptions(), + QuteLanguageIds.QUTE_ALL); + } if (this.getClientCapabilities().isSemanticTokensDynamicRegistered()) { // Semantic tokens is only available for Qute templates registerCapability(SEMANTIC_TOKENS_ID, TEXT_DOCUMENT_SEMANTIC_TOKENS, DEFAULT_SEMANTIC_TOKENS_OPTIONS, diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ServerCapabilitiesConstants.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ServerCapabilitiesConstants.java index b39c7934e..509a03def 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ServerCapabilitiesConstants.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ServerCapabilitiesConstants.java @@ -47,6 +47,7 @@ private ServerCapabilitiesConstants() { public static final String TEXT_DOCUMENT_REFERENCES = "textDocument/references"; public static final String TEXT_DOCUMENT_RENAME = "textDocument/rename"; public static final String TEXT_DOCUMENT_INLAY_HINT = "textDocument/inlayHint"; + public static final String TEXT_DOCUMENT_INLINE_COMPLETION = "textDocument/inlineCompletion"; public static final String TEXT_DOCUMENT_SEMANTIC_TOKENS = "textDocument/semanticTokens"; /* workspace/... */ public static final String WORKSPACE_EXECUTE_COMMAND = "workspace/executeCommand"; @@ -69,6 +70,7 @@ private ServerCapabilitiesConstants() { public static final String WORKSPACE_EXECUTE_COMMAND_ID = UUID.randomUUID().toString(); public static final String WORKSPACE_WATCHED_FILES_ID = UUID.randomUUID().toString(); public static final String INLAY_HINT_ID = UUID.randomUUID().toString(); + public static final String INLINE_COMPLETION_ID = UUID.randomUUID().toString(); public static final String SEMANTIC_TOKENS_ID = UUID.randomUUID().toString(); /* Default Options */ public static final CodeLensOptions DEFAULT_CODELENS_OPTIONS = new CodeLensOptions(); diff --git a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ServerCapabilitiesInitializer.java b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ServerCapabilitiesInitializer.java index 0c54b1570..760ef1019 100644 --- a/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ServerCapabilitiesInitializer.java +++ b/qute.ls/com.redhat.qute.ls/src/main/java/com/redhat/qute/settings/capabilities/ServerCapabilitiesInitializer.java @@ -60,6 +60,7 @@ public static ServerCapabilities getNonDynamicServerCapabilities(ClientCapabilit serverCapabilities.setReferencesProvider(!clientCapabilities.isReferencesDynamicRegistrationSupported()); serverCapabilities.setLinkedEditingRangeProvider(!clientCapabilities.isLinkedEditingRangeDynamicRegistered()); serverCapabilities.setInlayHintProvider(!clientCapabilities.isInlayHintDynamicRegistered()); + serverCapabilities.setInlineCompletionProvider(!clientCapabilities.isInlineCompletionDynamicRegistered()); serverCapabilities.setRenameProvider(!clientCapabilities.isRenameDynamicRegistered()); if (!clientCapabilities.isSemanticTokensDynamicRegistered()) { serverCapabilities.setSemanticTokensProvider(DEFAULT_SEMANTIC_TOKENS_OPTIONS); diff --git a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/QuteAssert.java b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/QuteAssert.java index 822d38dbf..fdbf9b7d7 100644 --- a/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/QuteAssert.java +++ b/qute.ls/com.redhat.qute.ls/src/test/java/com/redhat/qute/QuteAssert.java @@ -67,6 +67,7 @@ import org.eclipse.lsp4j.ReferenceContext; import org.eclipse.lsp4j.ResourceOperation; import org.eclipse.lsp4j.SemanticTokens; +import org.eclipse.lsp4j.SnippetTextEdit; import org.eclipse.lsp4j.SymbolKind; import org.eclipse.lsp4j.TextDocumentEdit; import org.eclipse.lsp4j.TextDocumentIdentifier; @@ -564,8 +565,10 @@ public static void assertDiagnostics(List actual, Diagnostic... expe public static void assertDiagnostics(List actual, List expected, boolean filter) { List received = actual; final boolean filterMessage; - if (expected != null && !expected.isEmpty() && !StringUtils.isEmpty(expected.get(0).getMessage())) { - filterMessage = true; + if (expected != null && !expected.isEmpty()) { + Either message = expected.get(0).getMessage(); + boolean hasMessage = message != null && message.isLeft() && !StringUtils.isEmpty(message.getLeft()); + filterMessage = hasMessage; } else { filterMessage = false; } @@ -1017,7 +1020,7 @@ public static void assertCodeActions(List actual, CodeAction... expe if (ca.getDiagnostics() != null) { ca.getDiagnostics().forEach(d -> { d.setSeverity(null); - d.setMessage(""); + d.setMessage(Either.forLeft("")); d.setSource(null); }); } @@ -1071,7 +1074,11 @@ public static Command c(String title, String commandId, String section, String s public static TextDocumentEdit tde(String uri, int version, TextEdit... te) { VersionedTextDocumentIdentifier versionedTextDocumentIdentifier = new VersionedTextDocumentIdentifier(uri, version); - return new TextDocumentEdit(versionedTextDocumentIdentifier, Arrays.asList(te)); + List> edits = new ArrayList<>(); + for (TextEdit edit : te) { + edits.add(Either.forLeft(edit)); + } + return new TextDocumentEdit(versionedTextDocumentIdentifier, edits); } public static CodeAction ca(Diagnostic d, Either... ops) { @@ -1099,7 +1106,7 @@ public static Either createFile(String uri, public static Either teOp(String uri, int startLine, int startChar, int endLine, int endChar, String newText) { return Either.forLeft(new TextDocumentEdit(new VersionedTextDocumentIdentifier(uri, 0), - Collections.singletonList(te(startLine, startChar, endLine, endChar, newText)))); + Collections.singletonList(Either.forLeft(te(startLine, startChar, endLine, endChar, newText))))); } // ------------------- Reference assert