Implement support for Eclipse-based classpath service

Note: this requires changes to LSP4e to support
to provide the means to execute commands, by dispatching
command execution to the server that registered it.
This commit is contained in:
Kris De Volder
2018-04-17 13:22:50 -07:00
parent d29254f167
commit 590482c418
5 changed files with 139 additions and 18 deletions

View File

@@ -0,0 +1,59 @@
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=true
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_functional_interfaces=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.insert_inferred_type_arguments=false
sp_cleanup.make_local_variable_final=true
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=false
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.organize_imports=false
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_redundant_type_arguments=false
sp_cleanup.remove_trailing_whitespaces=true
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=false
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
sp_cleanup.use_anonymous_class_creation=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_lambda=true
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true

View File

@@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.8.0",
org.eclipse.jface.text,
com.google.guava,
org.eclipse.debug.ui,
org.eclipse.ui.console
org.eclipse.ui.console,
org.springframework.tooling.jdt.ls.commons
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Export-Package: org.springframework.tooling.ls.eclipse.commons,

View File

@@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.ls.eclipse.commons;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4j.ExecuteCommandOptions;
import org.eclipse.lsp4j.ExecuteCommandParams;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.services.LanguageServer;
import org.springframework.tooling.jdt.ls.commons.classpath.ClientCommandExecutor;
@SuppressWarnings("restriction")
public class LSP4ECommandExecutor implements ClientCommandExecutor {
@Override
public Object executeClientCommand(String id, Object... params) throws Exception {
List<LanguageServer> commandHandlers = LanguageServiceAccessor.getLanguageServers(handlesCommand(id));
if (commandHandlers!=null) {
if (commandHandlers.size()==1) {
LanguageServer handler = commandHandlers.get(0);
return handler
.getWorkspaceService()
.executeCommand(new ExecuteCommandParams(id, Arrays.asList(params)))
.get(2, TimeUnit.SECONDS);
} else if (commandHandlers.size() > 1) {
throw new IllegalStateException("Multiple language servers have registered to handle command '"+id+"'");
}
}
throw new UnsupportedOperationException("No language server has registered to handle command '"+id+"'");
}
private Predicate<ServerCapabilities> handlesCommand(String id) {
return (serverCaps) -> {
ExecuteCommandOptions executeCommandProvider = serverCaps.getExecuteCommandProvider();
if (executeCommandProvider!=null) {
return executeCommandProvider.getCommands().contains(id);
}
return false;
};
}
}

View File

@@ -40,18 +40,26 @@ import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.springframework.tooling.jdt.ls.commons.classpath.ReusableClasspathListenerHandler;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.Futures;
@SuppressWarnings("restriction")
public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4LanguageClient {
private static ReusableClasspathListenerHandler classpathService = new ReusableClasspathListenerHandler(new LSP4ECommandExecutor());
public STS4LanguageClientImpl() {
System.out.println("Instantiatin STS4LanguageClientImpl");
}
private static final String ANNOTION_TYPE_ID = "org.springframework.tooling.bootinfo";
class UpdateHighlights extends UIJob {
private String target;
UpdateHighlights(String target) {
@@ -60,7 +68,7 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
setSystem(true);
schedule();
}
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
IWorkbenchWindow ww = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
@@ -93,23 +101,23 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
return Status.OK_STATUS;
}
};
/**
* Latest highlight request params. It is sufficient to only remember the last request per uri, because
* each new request is expected to replace the previous highlights.
*/
private Map<String, List<Range>> currentHighlights = new HashMap<>();
/**
* Current markers... indexed per document uri, needed sp we to be removed upon next update.
*/
private Map<String, Annotation[]> currentAnnotations = new HashMap<>();
private Map<String, Annotation[]> currentAnnotations = new HashMap<>();
private synchronized void updateAnnotations(String target, IDocument doc, IAnnotationModelExtension annotationModel) {
if (target!=null) {
Collection<LSPDocumentInfo> infos = LanguageServiceAccessor.getLSPDocumentInfosFor(doc, (x) -> true);
for (LSPDocumentInfo docInfo : infos) {
URI uri = docInfo.getFileUri();
URI uri = docInfo.getFileUri();
if (uri!=null && uri.toString().equals(target)) {
Annotation[] toRemove = currentAnnotations.get(target);
if (toRemove==null) {
@@ -140,7 +148,7 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
}
return annotations.build();
}
@Override
public synchronized void highlight(HighlightParams highlights) {
String target = highlights.getDoc().getUri();
@@ -155,7 +163,7 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
String status = progressEvent.getStatusMsg() != null ? progressEvent.getStatusMsg() : "";
showStatusMessage(status);
}
private void showStatusMessage(final String status) {
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
@Override
@@ -179,14 +187,12 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
@Override
public CompletableFuture<Object> addClasspathListener(ClasspathListenerParams params) {
// TODO Auto-generated method stub
return null;
return CompletableFuture.completedFuture(classpathService.addClasspathListener(params.getCallbackCommandId()));
}
@Override
public CompletableFuture<Object> removeClasspathListener(ClasspathListenerParams classpathListenerParams) {
// TODO Auto-generated method stub
return null;
public CompletableFuture<Object> removeClasspathListener(ClasspathListenerParams params) {
return CompletableFuture.completedFuture(classpathService.removeClasspathListener(params.getCallbackCommandId()));
}
}

View File

@@ -1,5 +1,5 @@
package org.springframework.tooling.jdt.ls.commons.classpath;
public interface ClientCommandExecutor {
Object executeClientCommand(String id, Object... params);
Object executeClientCommand(String id, Object... params) throws Exception;
}