Skip to content

Commit

Permalink
New API: Port code lenses
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedneilhussain committed Feb 2, 2023
1 parent be72902 commit 604da23
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
*******************************************************************************/
package org.eclipse.lsp4e.test.operations.codelens;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.core.commands.ExecutionEvent;
Expand All @@ -25,9 +24,10 @@
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.lsp4e.LanguageServerWrapper;
import org.eclipse.lsp4e.LanguageServersRegistry;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.command.LSPCommandHandler;
import org.eclipse.lsp4e.operations.codelens.CodeLensProvider;
import org.eclipse.lsp4e.operations.codelens.LSPCodeMining;
Expand All @@ -39,7 +39,6 @@
import org.eclipse.lsp4j.ExecuteCommandParams;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.widgets.Display;
Expand Down Expand Up @@ -71,7 +70,7 @@ public void setUp() throws CoreException {
}

@Test
public void testLSPCodeMiningActionClientSideHandling() throws BadLocationException, CoreException {
public void testLSPCodeMiningActionClientSideHandling() throws Exception {
String commandID = "test.command";
final CodeLens lens = createCodeLens(commandID);

Expand All @@ -94,10 +93,10 @@ public Object execute(ExecutionEvent event, Command command, IPath context) thro
IFile file = TestUtils.createUniqueTestFile(project, "lspt", "test content");
IDocument document = TestUtils.openTextViewer(file).getDocument();

LanguageServer languageServer = MockLanguageServer.INSTANCE;
CodeLensProvider provider = new CodeLensProvider();
LanguageServerWrapper wrapper = LanguageServiceAccessor.getLSWrapperForConnection(project, LanguageServersRegistry.getInstance().getDefinition(MOCK_SERVER_ID));

LSPCodeMining sut = new LSPCodeMining(lens, document, languageServer, LanguageServersRegistry.getInstance().getDefinition(MOCK_SERVER_ID), provider);
LSPCodeMining sut = new LSPCodeMining(lens, document, wrapper, provider);
MouseEvent mouseEvent = createMouseEvent();
sut.getAction().accept(mouseEvent);

Expand All @@ -107,8 +106,7 @@ public Object execute(ExecutionEvent event, Command command, IPath context) thro

@Test
public void testLSPCodeMiningActionServerSideHandling()
throws InterruptedException, java.util.concurrent.ExecutionException, TimeoutException,
BadLocationException, CoreException {
throws Exception {
final CodeLens lens = createCodeLens(MockLanguageServer.SUPPORTED_COMMAND_ID);
Command command = lens.getCommand();
JsonObject jsonObject = new JsonObject();
Expand All @@ -122,8 +120,9 @@ public void testLSPCodeMiningActionServerSideHandling()
MockLanguageServer languageServer = MockLanguageServer.INSTANCE;
CodeLensProvider provider = new CodeLensProvider();

LSPCodeMining sut = new LSPCodeMining(lens, document, languageServer, LanguageServersRegistry.getInstance().getDefinition(MOCK_SERVER_ID), provider);
MouseEvent mouseEvent = createMouseEvent();
LanguageServerWrapper wrapper = LanguageServiceAccessor.getLSWrapperForConnection(project, LanguageServersRegistry.getInstance().getDefinition(MOCK_SERVER_ID));

LSPCodeMining sut = new LSPCodeMining(lens, document, wrapper, provider); MouseEvent mouseEvent = createMouseEvent();
sut.getAction().accept(mouseEvent);

// We expect that the language server will be called to execute the command
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
package org.eclipse.lsp4e.operations.codelens;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
Expand All @@ -24,41 +23,37 @@
import org.eclipse.jface.text.codemining.ICodeMining;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServerPlugin;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.LanguageServerWrapper;
import org.eclipse.lsp4e.LanguageServers;
import org.eclipse.lsp4e.LanguageServers.LanguageServerDocumentExecutor;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.CodeLensParams;
import org.eclipse.lsp4j.services.LanguageServer;

public class CodeLensProvider extends AbstractCodeMiningProvider {

private CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(@NonNull IDocument document) {
URI docURI = LSPEclipseUtils.toUri(document);
if (docURI != null) {
final var param = new CodeLensParams(LSPEclipseUtils.toTextDocumentIdentifier(docURI));
final var codeLensResults = Collections.synchronizedList(new ArrayList<LSPCodeMining>());
return LanguageServiceAccessor
.getLanguageServers(document, capabilities -> capabilities.getCodeLensProvider() != null)
.thenComposeAsync(languageServers -> CompletableFuture.allOf(languageServers.stream()
.map(languageServer -> languageServer.getTextDocumentService().codeLens(param)
.thenAcceptAsync(codeLenses -> {
// textDocument/codeLens may return null
if (codeLenses != null) {
codeLenses.stream().filter(Objects::nonNull)
.map(codeLens -> toCodeMining(document, languageServer, codeLens))
.filter(Objects::nonNull).forEach(codeLensResults::add);
}
}))
.toArray(CompletableFuture[]::new)))
.thenApplyAsync(theVoid -> codeLensResults);
LanguageServerDocumentExecutor executor = LanguageServers.forDocument(document)
.withFilter(sc -> sc.getCodeLensProvider() != null);
return executor.collectAll((w, ls) -> ls.getTextDocumentService().codeLens(param)
.thenApply(codeLenses -> LanguageServers.streamSafely(codeLenses)
.map(codeLens -> toCodeMining(document, w, codeLens))
.filter(Objects::nonNull)))
.thenApply(result -> result.stream().flatMap(s -> s).collect(Collectors.toList()));
}
else {
return null;
}
}

private LSPCodeMining toCodeMining(IDocument document, LanguageServer languageServer, CodeLens codeLens) {
private LSPCodeMining toCodeMining(IDocument document, LanguageServerWrapper languageServerWrapper, CodeLens codeLens) {
if (codeLens == null) {
return null;
}
try {
return new LSPCodeMining(codeLens, document, languageServer, LanguageServiceAccessor.resolveServerDefinition(languageServer).orElse(null), CodeLensProvider.this);
return new LSPCodeMining(codeLens, document, languageServerWrapper, CodeLensProvider.this);
} catch (BadLocationException e) {
LanguageServerPlugin.logError(e);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,27 @@
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.codemining.LineHeaderCodeMining;
import org.eclipse.lsp4e.LanguageServerWrapper;
import org.eclipse.lsp4e.LanguageServersRegistry.LanguageServerDefinition;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.command.CommandExecutor;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.swt.events.MouseEvent;

public class LSPCodeMining extends LineHeaderCodeMining {
private CodeLens codeLens;
private final LanguageServer languageServer;

// TODO: Store a SingleServerDocumentExecutor instead when that codestream is merged
private final LanguageServerWrapper languageServerWrapper;
private final LanguageServerDefinition languageServerDefinition;
private final @Nullable IDocument document;

public LSPCodeMining(CodeLens codeLens, IDocument document, LanguageServer languageServer, LanguageServerDefinition languageServerDefinition,
public LSPCodeMining(CodeLens codeLens, IDocument document, LanguageServerWrapper languageServerWrapper,
CodeLensProvider provider) throws BadLocationException {
super(codeLens.getRange().getStart().getLine(), document, provider, null);
this.codeLens = codeLens;
this.languageServer = languageServer;
this.languageServerDefinition = languageServerDefinition;
this.languageServerWrapper = languageServerWrapper;
this.languageServerDefinition = languageServerWrapper.serverDefinition;
this.document = document;
setLabel(getCodeLensString(codeLens));
}
Expand All @@ -52,14 +53,11 @@ public LSPCodeMining(CodeLens codeLens, IDocument document, LanguageServer langu

@Override
protected CompletableFuture<Void> doResolve(ITextViewer viewer, IProgressMonitor monitor) {
if (!LanguageServiceAccessor.checkCapability(languageServer,
capabilities -> {
Boolean resolveProvider = capabilities.getCodeLensProvider().getResolveProvider();
return resolveProvider != null && resolveProvider;
})) {
if (Boolean.TRUE != this.languageServerWrapper.getServerCapabilities().getCodeLensProvider().getResolveProvider()) {
return CompletableFuture.completedFuture(null);
}
return languageServer.getTextDocumentService().resolveCodeLens(this.codeLens)

return this.languageServerWrapper.execute(languageServer -> languageServer.getTextDocumentService().resolveCodeLens(this.codeLens))
.thenAcceptAsync(resolvedCodeLens -> {
codeLens = resolvedCodeLens;
if (resolvedCodeLens != null) {
Expand Down

0 comments on commit 604da23

Please sign in to comment.