diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml index 0694f9d69..29ced074b 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml @@ -95,6 +95,10 @@ class="org.springframework.tooling.ls.eclipse.commons.commands.JavaWorkspaceCommandHanlder" commandId="java.execute.workspaceCommand"> + + @@ -121,6 +125,22 @@ optional="false"> + + + + + + diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/commands/InvokeContentAssistCommandHandler.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/commands/InvokeContentAssistCommandHandler.java new file mode 100644 index 000000000..e5c588720 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/commands/InvokeContentAssistCommandHandler.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2023 VMware, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VMware, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.tooling.ls.eclipse.commons.commands; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.NotEnabledException; +import org.eclipse.core.commands.NotHandledException; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.ICoreRunnable; +import org.eclipse.core.runtime.Status; +import org.eclipse.ui.IWorkbenchCommandConstants; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.progress.UIJob; + +public class InvokeContentAssistCommandHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + UIJob.create("Invoke Content Assist", (ICoreRunnable) m -> { + try { + IHandlerService service = HandlerUtil.getActiveWorkbenchWindow(event).getService(IHandlerService.class); + service.executeCommand(IWorkbenchCommandConstants.EDIT_CONTENT_ASSIST, null); + } catch (ExecutionException | NotDefinedException | NotEnabledException | NotHandledException e) { + throw new CoreException(Status.error("", e)); + } + }).schedule(); + return null; + } + +} diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java index 1881cf1d0..cbcb9b02c 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java @@ -26,6 +26,7 @@ public interface ICompletionProposal { CompletionItemKind getKind(); DocumentEdits getTextEdit(); default Optional getAdditionalEdit() { return Optional.empty(); } + default boolean isTriggeringNextCompletionRequest() { return false; } String getDetail(); Renderable getDocumentation(); diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java index 2dbe095e9..22f0ef50a 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2022 VMware Inc. + * Copyright (c) 2016, 2023 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -21,6 +21,7 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; +import org.eclipse.lsp4j.Command; import org.eclipse.lsp4j.CompletionItem; import org.eclipse.lsp4j.CompletionList; import org.eclipse.lsp4j.InsertTextFormat; @@ -228,6 +229,10 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine { resolveItem(doc, completion, item); } } + + if (completion.isTriggeringNextCompletionRequest()) { + item.setCommand(new Command("Completion Proposal Request", "editor.action.triggerSuggest")); + } return item; } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/FindByCompletionProposal.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/FindByCompletionProposal.java index 880b175a6..0b4316652 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/FindByCompletionProposal.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/FindByCompletionProposal.java @@ -26,9 +26,10 @@ public class FindByCompletionProposal implements ICompletionProposal { private Renderable doc; private Optional additionalEdits; private String filter; + private boolean triggerNextCompletion; public FindByCompletionProposal(String label, CompletionItemKind kind, DocumentEdits edits, String details, - Renderable doc, Optional additionalEdits, String filter) { + Renderable doc, Optional additionalEdits, String filter, boolean triggerNextCompletion) { super(); this.label = label; this.kind = kind; @@ -37,9 +38,10 @@ public class FindByCompletionProposal implements ICompletionProposal { this.doc = doc; this.additionalEdits = additionalEdits; this.filter = filter; + this.triggerNextCompletion = triggerNextCompletion; } - public static ICompletionProposal createProposal(int offset, CompletionItemKind completionItemKind, String prefix, String label, String completion) { + public static ICompletionProposal createProposal(int offset, CompletionItemKind completionItemKind, String prefix, String label, String completion, boolean triggerNextCompletion) { DocumentEdits edits = new DocumentEdits(null, false); String filter = label; if (prefix != null && label.startsWith(prefix)) { @@ -54,7 +56,7 @@ public class FindByCompletionProposal implements ICompletionProposal { } DocumentEdits additionalEdits = new DocumentEdits(null, false); - return new FindByCompletionProposal(label, completionItemKind, edits, null, null, Optional.of(additionalEdits), filter); + return new FindByCompletionProposal(label, completionItemKind, edits, null, null, Optional.of(additionalEdits), filter, triggerNextCompletion); } @Override @@ -92,4 +94,9 @@ public class FindByCompletionProposal implements ICompletionProposal { return filter; } + @Override + public boolean isTriggeringNextCompletionRequest() { + return triggerNextCompletion; + } + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/DataRepositoryQueryStartCompletionProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/DataRepositoryQueryStartCompletionProvider.java index b2aa17f46..8edfab548 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/DataRepositoryQueryStartCompletionProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/DataRepositoryQueryStartCompletionProvider.java @@ -32,7 +32,7 @@ public class DataRepositoryQueryStartCompletionProvider implements DataRepositor for(QueryMethodSubject queryMethodSubject : QueryMethodSubject.QUERY_METHOD_SUBJECTS){ String toInsert = queryMethodSubject.key() + "By"; if(prefix == null || toInsert.startsWith(localPrefix)||isOffsetAfterWhitespace(doc, offset)) { - completions.add(FindByCompletionProposal.createProposal(offset, CompletionItemKind.Text, prefix, toInsert, toInsert)); + completions.add(FindByCompletionProposal.createProposal(offset, CompletionItemKind.Text, prefix, toInsert, toInsert, true)); } } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/DataRepositoryStandardCompletionProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/DataRepositoryStandardCompletionProvider.java index 81e2a7c4c..a3e6b45e3 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/DataRepositoryStandardCompletionProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/DataRepositoryStandardCompletionProvider.java @@ -56,6 +56,6 @@ public class DataRepositoryStandardCompletionProvider implements DataRepositoryC completion.append(StringUtils.uncapitalize(domainProperty.getName())); completion.append(");"); - return FindByCompletionProposal.createProposal(offset, CompletionItemKind.Method, prefix, label.toString(), completion.toString()); + return FindByCompletionProposal.createProposal(offset, CompletionItemKind.Method, prefix, label.toString(), completion.toString(), false); } } \ No newline at end of file diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/prefixsensitive/DataRepositoryPrefixSensitiveCompletionProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/prefixsensitive/DataRepositoryPrefixSensitiveCompletionProvider.java index 1f0499b3d..20ab699f1 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/prefixsensitive/DataRepositoryPrefixSensitiveCompletionProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/providers/prefixsensitive/DataRepositoryPrefixSensitiveCompletionProvider.java @@ -94,7 +94,7 @@ public class DataRepositoryPrefixSensitiveCompletionProvider implements DataRepo DocumentEdits edits = new DocumentEdits(null, false); edits.replace(offset - lastWord.length(), offset, toReplace); DocumentEdits additionalEdits = new DocumentEdits(null, false); - ICompletionProposal proposal = new FindByCompletionProposal(toReplace, CompletionItemKind.Text, edits, "property " + toReplace, null, Optional.of(additionalEdits), lastWord); + ICompletionProposal proposal = new FindByCompletionProposal(toReplace, CompletionItemKind.Text, edits, "property " + toReplace, null, Optional.of(additionalEdits), lastWord, true); completions.add(proposal); } } @@ -117,7 +117,7 @@ public class DataRepositoryPrefixSensitiveCompletionProvider implements DataRepo int replaceStart = calculateReplaceOffset(offset, localPrefix, fullPrefix, returnType); edits.replace(replaceStart, offset, newText.toString()); DocumentEdits additionalEdits = new DocumentEdits(null, false); - ICompletionProposal proposal = new FindByCompletionProposal(methodName, CompletionItemKind.Method, edits, null, null, Optional.of(additionalEdits), signature); + ICompletionProposal proposal = new FindByCompletionProposal(methodName, CompletionItemKind.Method, edits, null, null, Optional.of(additionalEdits), signature, false); completions.add(proposal); }