Merge branch 'master' of github.com:spring-projects/sts4

This commit is contained in:
Kris De Volder
2017-11-22 13:03:37 -08:00
26 changed files with 383 additions and 339 deletions

View File

@@ -1,7 +1,15 @@
instructions.configure=\
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.eclipse.org/releases/oxygen,name:Oxygen);\
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.eclipse.org/releases/oxygen,name:Oxygen);
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.eclipse.org/releases/oxygen,name:Oxygen);\
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.7,name:Spring Tool Suite 4);\
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.7,name:Spring Tool Suite 4);\
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations,name:Spring Tools 4 Language Servers for Eclipse);\
org.eclipse.equinox.p2.touchpoint.eclipse.addRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations,name:Spring Tools 4 Language Servers for Eclipse);
instructions.unconfigure=\
org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.eclipse.org/releases/oxygen);\
org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.eclipse.org/releases/oxygen);
org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.eclipse.org/releases/oxygen);\
org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.7);\
org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4/update/e4.7);\
org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:0,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations);\
org.eclipse.equinox.p2.touchpoint.eclipse.removeRepository(type:1,location:http${#58}//download.springsource.com/release/TOOLS/sts4-language-server-integrations);

View File

@@ -11,7 +11,6 @@
package org.springframework.tooling.boot.java.ls;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
@@ -21,18 +20,13 @@ import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
import org.osgi.framework.Bundle;
import org.springframework.tooling.ls.eclipse.commons.LanguageServerProcessReaper;
import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessStreamConnector;
/**
* @author Martin Lippert
*/
@SuppressWarnings("restriction")
public class SpringBootJavaLanguageServer extends ProcessStreamConnectionProvider {
private static LanguageServerProcessReaper processReaper = new LanguageServerProcessReaper();
public class SpringBootJavaLanguageServer extends STS4LanguageServerProcessStreamConnector {
public SpringBootJavaLanguageServer() {
List<String> commands = new ArrayList<>();
@@ -43,7 +37,7 @@ public class SpringBootJavaLanguageServer extends ProcessStreamConnectionProvide
commands.add("-Dlsp.lazy.completions.disable=true");
commands.add("-Dlsp.completions.indentation.enable=true");
commands.add("-Xmx100m");
commands.add("-Xmx200m");
commands.add("-cp");
commands.add(getToolsJAR() + ":" + getLanguageServerJARLocation());
commands.add("org.springframework.boot.loader.JarLauncher");
@@ -54,29 +48,6 @@ public class SpringBootJavaLanguageServer extends ProcessStreamConnectionProvide
setWorkingDirectory(workingDir);
}
@Override
public void start() throws IOException {
super.start();
processReaper.addProcess(LanguageServerProcessReaper.getProcess(this));
}
@Override
public void stop() {
super.stop();
processReaper.removeProcess(LanguageServerProcessReaper.getProcess(this));
}
protected String getJDKLocation() {
File jre = new File(System.getProperty("java.home"));
File javaExecutable = StandardVMType.findJavaExecutable(jre);
return javaExecutable.getAbsolutePath();
}
protected String getToolsJAR() {
File jre = new File(System.getProperty("java.home"));
return new File(jre.getParent(), "lib" + Path.SEPARATOR + "tools.jar").getAbsolutePath();
}
protected String getLanguageServerJARLocation() {
String fromSysprop = System.getProperty("boot-java-ls-jar", null);
if (fromSysprop!=null) {
@@ -102,11 +73,6 @@ public class SpringBootJavaLanguageServer extends ProcessStreamConnectionProvide
return dataFile.getAbsolutePath();
}
protected String getWorkingDirLocation() {
// TODO: identify a reasonable working directory for the language server process
return System.getProperty("user.dir");
}
protected void copyLanguageServerJAR(String languageServerJarName, String languageServerLocalCopy) throws Exception {
Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID);
InputStream stream = FileLocator.openStream( bundle, new Path("servers/" + languageServerJarName), false );

View File

@@ -15,7 +15,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0",
org.eclipse.tm4e.ui;bundle-version="0.1.0",
org.eclipse.lsp4j,
org.eclipse.ui.workbench,
org.eclipse.jface
org.eclipse.jface,
org.springframework.tooling.ls.eclipse.commons;bundle-version="4.0.0"
Import-Package: com.google.gson;version="2.7.0",
org.eclipse.jface.preference,
org.eclipse.lsp4j.jsonrpc.messages;version="0.1.0.v20170117-0759",

View File

@@ -85,6 +85,7 @@
<server
class="org.springframework.tooling.bosh.ls.BoshLanguageServer"
id="org.eclipse.languageserver.languages.bosh"
clientImpl="org.springframework.tooling.ls.eclipse.commons.STS4LanguageClientImpl"
label="BOSH Language Server">
</server>
<contentTypeMapping

View File

@@ -20,24 +20,13 @@ import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Bundle;
import com.google.gson.JsonObject;
import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessStreamConnector;
/**
* @author Martin Lippert
*/
@SuppressWarnings("restriction")
public class BoshLanguageServer extends ProcessStreamConnectionProvider {
public class BoshLanguageServer extends STS4LanguageServerProcessStreamConnector {
public BoshLanguageServer() {
List<String> commands = new ArrayList<>();
@@ -58,44 +47,6 @@ public class BoshLanguageServer extends ProcessStreamConnectionProvider {
setWorkingDirectory(workingDir);
}
public void handleMessage(Message message, LanguageServer languageServer, String rootPath) {
if (message instanceof NotificationMessage) {
NotificationMessage notificationMessage = (NotificationMessage) message;
if ("sts/progress".equals(notificationMessage.getMethod())) {
JsonObject params = (JsonObject) notificationMessage.getParams();
String status = params.has("statusMsg") ? params.get("statusMsg").getAsString() : "";
showStatusMessage(status);
}
}
}
private void showStatusMessage(final String status) {
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
IStatusLineManager statusLineManager = getStatusLineManager();
if (statusLineManager != null) {
statusLineManager.setMessage(status);
}
}
});
}
private IStatusLineManager getStatusLineManager() {
try {
return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getEditorSite().getActionBars().getStatusLineManager();
}
catch (NullPointerException e) {
return null;
}
}
protected String getJDKLocation() {
IVMInstall jdk = JavaRuntime.getDefaultVMInstall();
File javaExecutable = StandardVMType.findJavaExecutable(jdk.getInstallLocation());
return javaExecutable.getAbsolutePath();
}
protected String getLanguageServerJARLocation() {
String languageServer = "bosh-language-server-" + Constants.LANGUAGE_SERVER_VERSION + "-SNAPSHOT.jar";
@@ -113,11 +64,6 @@ public class BoshLanguageServer extends ProcessStreamConnectionProvider {
return dataFile.getAbsolutePath();
}
protected String getWorkingDirLocation() {
// TODO: identify a reasonable working directory for the language server process
return System.getProperty("user.dir");
}
protected void copyLanguageServerJAR(String languageServerJarName) throws Exception {
Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID);
InputStream stream = FileLocator.openStream( bundle, new Path("servers/" + languageServerJarName), false );

View File

@@ -7,6 +7,7 @@
<server
class="org.springframework.tooling.cloudfoundry.manifest.ls.CloudFoundryManifestLanguageServer"
id="org.eclipse.languageserver.languages.cloudfoundrymanifest"
clientImpl="org.springframework.tooling.ls.eclipse.commons.STS4LanguageClientImpl"
label="Cloud Foundry Manifest Language Server">
</server>
<contentTypeMapping

View File

@@ -11,7 +11,6 @@
package org.springframework.tooling.cloudfoundry.manifest.ls;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
@@ -23,23 +22,18 @@ import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
import org.eclipse.lsp4j.DidChangeConfigurationParams;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage;
import org.eclipse.lsp4j.services.LanguageServer;
import org.osgi.framework.Bundle;
import org.springframework.tooling.ls.eclipse.commons.LanguageServerProcessReaper;
import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessStreamConnector;
/**
* @author Martin Lippert
*/
@SuppressWarnings("restriction")
public class CloudFoundryManifestLanguageServer extends ProcessStreamConnectionProvider {
private static LanguageServerProcessReaper processReaper = new LanguageServerProcessReaper();
public class CloudFoundryManifestLanguageServer extends STS4LanguageServerProcessStreamConnector {
private LanguageServer languageServer;
private URI rootPath;
@@ -93,7 +87,6 @@ public class CloudFoundryManifestLanguageServer extends ProcessStreamConnectionP
public void stop() {
removeLanguageServer(this);
super.stop();
processReaper.removeProcess(LanguageServerProcessReaper.getProcess(this));
}
@Override
@@ -101,28 +94,6 @@ public class CloudFoundryManifestLanguageServer extends ProcessStreamConnectionP
return cfTargetOptionSettings;
}
protected String getJDKLocation() {
try {
File javaHome= new File(System.getProperty("java.home")).getCanonicalFile(); //$NON-NLS-1$
if (javaHome.exists()) {
File javaExecutable = StandardVMType.findJavaExecutable(javaHome);
if (javaExecutable != null && javaExecutable.exists()) {
return javaExecutable.getAbsolutePath();
}
}
} catch (IOException e) {
return null;
}
return null;
}
@Override
public void start() throws IOException {
super.start();
processReaper.addProcess(LanguageServerProcessReaper.getProcess(this));
}
protected String getLanguageServerJARLocation() {
String languageServer = "manifest-yaml-language-server-" + Constants.LANGUAGE_SERVER_VERSION;
@@ -144,11 +115,6 @@ public class CloudFoundryManifestLanguageServer extends ProcessStreamConnectionP
return dataFile.getAbsolutePath();
}
protected String getWorkingDirLocation() {
// TODO: identify a reasonable working directory for the language server process
return System.getProperty("user.dir");
}
protected void copyLanguageServerJAR(String languageServerJarName, String languageServerLocalCopy) throws Exception {
Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID);
InputStream stream = FileLocator.openStream( bundle, new Path("servers/" + languageServerJarName), false );

View File

@@ -15,7 +15,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0",
org.eclipse.tm4e.ui;bundle-version="0.1.0",
org.eclipse.lsp4j,
org.eclipse.ui.workbench,
org.eclipse.jface
org.eclipse.jface,
org.springframework.tooling.ls.eclipse.commons;bundle-version="4.0.0"
Import-Package: com.google.gson;version="2.7.0",
org.eclipse.jface.preference,
org.eclipse.lsp4j.jsonrpc.messages;version="0.1.0.v20170117-0759",

View File

@@ -85,6 +85,7 @@
<server
class="org.springframework.tooling.concourse.ls.ConcourseLanguageServer"
id="org.eclipse.languageserver.languages.concourse"
clientImpl="org.springframework.tooling.ls.eclipse.commons.STS4LanguageClientImpl"
label="Concourse Language Server">
</server>
<contentTypeMapping

View File

@@ -20,24 +20,13 @@ import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Bundle;
import com.google.gson.JsonObject;
import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessStreamConnector;
/**
* @author Martin Lippert
*/
@SuppressWarnings("restriction")
public class ConcourseLanguageServer extends ProcessStreamConnectionProvider {
public class ConcourseLanguageServer extends STS4LanguageServerProcessStreamConnector {
public ConcourseLanguageServer() {
List<String> commands = new ArrayList<>();
@@ -58,44 +47,6 @@ public class ConcourseLanguageServer extends ProcessStreamConnectionProvider {
setWorkingDirectory(workingDir);
}
public void handleMessage(Message message, LanguageServer languageServer, String rootPath) {
if (message instanceof NotificationMessage) {
NotificationMessage notificationMessage = (NotificationMessage) message;
if ("sts/progress".equals(notificationMessage.getMethod())) {
JsonObject params = (JsonObject) notificationMessage.getParams();
String status = params.has("statusMsg") ? params.get("statusMsg").getAsString() : "";
showStatusMessage(status);
}
}
}
private void showStatusMessage(final String status) {
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
IStatusLineManager statusLineManager = getStatusLineManager();
if (statusLineManager != null) {
statusLineManager.setMessage(status);
}
}
});
}
private IStatusLineManager getStatusLineManager() {
try {
return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getEditorSite().getActionBars().getStatusLineManager();
}
catch (NullPointerException e) {
return null;
}
}
protected String getJDKLocation() {
IVMInstall jdk = JavaRuntime.getDefaultVMInstall();
File javaExecutable = StandardVMType.findJavaExecutable(jdk.getInstallLocation());
return javaExecutable.getAbsolutePath();
}
protected String getLanguageServerJARLocation() {
String languageServer = "concourse-language-server-" + Constants.LANGUAGE_SERVER_VERSION + "-SNAPSHOT.jar";
@@ -113,11 +64,6 @@ public class ConcourseLanguageServer extends ProcessStreamConnectionProvider {
return dataFile.getAbsolutePath();
}
protected String getWorkingDirLocation() {
// TODO: identify a reasonable working directory for the language server process
return System.getProperty("user.dir");
}
protected void copyLanguageServerJAR(String languageServerJarName) throws Exception {
Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID);
InputStream stream = FileLocator.openStream( bundle, new Path("servers/" + languageServerJarName), false );

View File

@@ -4,7 +4,8 @@ Bundle-Name: Eclipse Language Server Commons
Bundle-SymbolicName: org.springframework.tooling.ls.eclipse.commons;singleton:=true
Bundle-Version: 4.0.0.qualifier
Bundle-Vendor: Pivotal, Inc.
Require-Bundle: org.eclipse.ui,
Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0",
org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.lsp4e;bundle-version="0.3.0",
org.eclipse.lsp4j.jsonrpc,

View File

@@ -0,0 +1,89 @@
/*******************************************************************************
* Copyright (c) 2016-2017 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;
public class ProgressParams {
/**
* An id representing the enitity for which progress messages are to be shown.
*/
private String id;
/**
* Updates the current statusMsg associated with a given the id. If null, then the message
* is cleared.
*/
private String statusMsg;
public ProgressParams() {
}
public ProgressParams(String id, String statusMsg) {
super();
this.id = id;
this.statusMsg = statusMsg;
}
@Override
public String toString() {
return "ProgressParams [id=" + id + ", statusMsg=" + statusMsg + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((statusMsg == null) ? 0 : statusMsg.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ProgressParams other = (ProgressParams) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (statusMsg == null) {
if (other.statusMsg != null)
return false;
} else if (!statusMsg.equals(other.statusMsg))
return false;
return true;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getStatusMsg() {
return statusMsg;
}
public void setStatusMsg(String statusMsg) {
this.statusMsg = statusMsg;
}
}

View File

@@ -23,9 +23,9 @@ public interface STS4LanguageClient extends LanguageClient {
@JsonNotification("sts/highlight")
void highlight(HighlightParams highlights);
// TODO: @JsonNotification("sts/progress")
// void progress(ProgressParams progressEvent);
//
@JsonNotification("sts/progress")
void progress(ProgressParams progressEvent);
// TODO: @JsonRequest("sts/moveCursor")
// CompletableFuture<Object> moveCursor(CursorMovement cursorMovement);

View File

@@ -20,6 +20,7 @@ import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
@@ -147,4 +148,31 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
}
}
@Override
public void progress(ProgressParams progressEvent) {
String status = progressEvent.getStatusMsg() != null ? progressEvent.getStatusMsg() : "";
showStatusMessage(status);
}
private void showStatusMessage(final String status) {
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
IStatusLineManager statusLineManager = getStatusLineManager();
if (statusLineManager != null) {
statusLineManager.setMessage(status);
}
}
});
}
private IStatusLineManager getStatusLineManager() {
try {
return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getEditorSite().getActionBars().getStatusLineManager();
}
catch (NullPointerException e) {
return null;
}
}
}

View File

@@ -0,0 +1,62 @@
/*******************************************************************************
* Copyright (c) 2017 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.io.File;
import java.io.IOException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
@SuppressWarnings("restriction")
public class STS4LanguageServerProcessStreamConnector extends ProcessStreamConnectionProvider {
private static LanguageServerProcessReaper processReaper = new LanguageServerProcessReaper();
@Override
public void start() throws IOException {
super.start();
processReaper.addProcess(LanguageServerProcessReaper.getProcess(this));
}
@Override
public void stop() {
super.stop();
processReaper.removeProcess(LanguageServerProcessReaper.getProcess(this));
}
protected String getJDKLocation() {
try {
File javaHome= new File(System.getProperty("java.home")).getCanonicalFile(); //$NON-NLS-1$
if (javaHome.exists()) {
File javaExecutable = StandardVMType.findJavaExecutable(javaHome);
if (javaExecutable != null && javaExecutable.exists()) {
return javaExecutable.getAbsolutePath();
}
}
} catch (IOException e) {
return null;
}
return null;
}
protected String getToolsJAR() {
File jre = new File(System.getProperty("java.home"));
return new File(jre.getParent(), "lib" + Path.SEPARATOR + "tools.jar").getAbsolutePath();
}
protected String getWorkingDirLocation() {
return System.getProperty("user.dir");
}
}

View File

@@ -27,8 +27,10 @@ import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.outline.SymbolsLabelProvider;
import org.eclipse.lsp4j.Location;
@@ -36,6 +38,7 @@ import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
@@ -83,34 +86,67 @@ public class GotoSymbolDialog extends PopupDialog {
}
}
private class GotoSymbolsLabelProvider extends SymbolsLabelProvider {
@Override
protected int getMaxSeverity(IResource resource, SymbolInformation symbolInformation)
throws CoreException, BadLocationException {
int maxSeverity = -1;
for (IMarker marker : resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO)) {
int offset = marker.getAttribute(IMarker.CHAR_START, -1);
if (offset != -1) {
maxSeverity = Math.max(maxSeverity, marker.getAttribute(IMarker.SEVERITY, -1));
private class GotoSymbolsLabelProvider extends StyledCellLabelProvider {
private Stylers stylers;
private SymbolsLabelProvider symbolsLabelProvider;
public GotoSymbolsLabelProvider(Font base) {
stylers = new Stylers(base);
boolean showSymbolsLabelProviderLocation = false; /* dont show full location. we show relative location in our own implementation below */
boolean showKindInformation = false;
symbolsLabelProvider = new SymbolsLabelProvider(showSymbolsLabelProviderLocation , showKindInformation) {
@Override
protected int getMaxSeverity(IResource resource, SymbolInformation symbolInformation)
throws CoreException, BadLocationException {
int maxSeverity = -1;
for (IMarker marker : resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO)) {
int offset = marker.getAttribute(IMarker.CHAR_START, -1);
if (offset != -1) {
maxSeverity = Math.max(maxSeverity, marker.getAttribute(IMarker.SEVERITY, -1));
}
}
return maxSeverity;
}
}
return maxSeverity;
};
}
@Override
public void update(ViewerCell cell) {
super.update(cell);
Object element = cell.getElement();
cell.setImage(symbolsLabelProvider.getImage(element));
StyledString styledString = getStyledText(element);
cell.setText(styledString.getString());
cell.setStyleRanges(styledString.getStyleRanges());
}
@Override
public StyledString getStyledText(Object element) {
StyledString s = super.getStyledText(element);
private StyledString getStyledText(Object element) {
StyledString s = symbolsLabelProvider.getStyledText(element);
if (element instanceof SymbolInformation) {
Optional<String> workspacePath = GotoSymbolDialog.this
.getWorkspaceLocation((SymbolInformation) element);
if (workspacePath.isPresent()) {
s.append(" -- [", Stylers.NULL);
s.append(workspacePath.get(), Stylers.NULL);
s.append("]", Stylers.NULL);
String locationText = getSymbolLocationText((SymbolInformation) element);
if (locationText != null) {
s = s.append(locationText, stylers.italicColoured(SWT.COLOR_DARK_GRAY));
}
}
return s;
}
}
@Override
public void dispose() {
stylers.dispose();
symbolsLabelProvider.dispose();
super.dispose();
}
protected String getSymbolLocationText(SymbolInformation symbol) {
Optional<String> location = GotoSymbolDialog.this
.getSymbolLocation(symbol);
if (location.isPresent()) {
return " -- [" + location.get() + "]";
}
return null;
}
}
private static final Point DEFAULT_SIZE = new Point(280, 300);
@@ -219,7 +255,7 @@ public class GotoSymbolDialog extends PopupDialog {
list.addDoubleClickListener(e -> performOk(list));
}
private Optional<String> getWorkspaceLocation(SymbolInformation symbolInformation) {
private Optional<String> getSymbolLocation(SymbolInformation symbolInformation) {
String val = null;
if (!model.fromFileProvider(symbolInformation)) {
@@ -281,7 +317,7 @@ public class GotoSymbolDialog extends PopupDialog {
TreeViewer viewer = new TreeViewer(dialogArea, SWT.SINGLE);
GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getControl());
viewer.setContentProvider(new SymbolsContentProvider());
viewer.setLabelProvider(new GotoSymbolsLabelProvider());
viewer.setLabelProvider(new GotoSymbolsLabelProvider(viewer.getTree().getFont()));
viewer.setUseHashlookup(true);
disposables.add(model.getSymbols().onChange(UIValueListener.from((e, v) -> {
viewer.refresh();

View File

@@ -15,7 +15,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0",
org.eclipse.tm4e.ui;bundle-version="0.1.0",
org.eclipse.lsp4j,
org.eclipse.ui.workbench,
org.eclipse.jface
org.eclipse.jface,
org.springframework.tooling.ls.eclipse.commons;bundle-version="4.0.0"
Import-Package: com.google.gson;version="2.7.0",
org.eclipse.jface.preference,
org.eclipse.lsp4j.jsonrpc.messages;version="0.1.0.v20170117-0759",

View File

@@ -81,6 +81,7 @@
<server
class="org.springframework.tooling.properties.ls.SpringBootPropertiesLanguageServer"
id="org.eclipse.languageserver.languages.springbootproperties"
clientImpl="org.springframework.tooling.ls.eclipse.commons.STS4LanguageClientImpl"
label="Spring Boot Properties Language Server">
</server>
<contentTypeMapping

View File

@@ -12,7 +12,6 @@ package org.springframework.tooling.properties.ls;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
@@ -21,24 +20,13 @@ import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Bundle;
import com.google.gson.JsonObject;
import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessStreamConnector;
/**
* @author Martin Lippert
*/
@SuppressWarnings("restriction")
public class SpringBootPropertiesLanguageServer extends ProcessStreamConnectionProvider {
public class SpringBootPropertiesLanguageServer extends STS4LanguageServerProcessStreamConnector {
public SpringBootPropertiesLanguageServer() {
List<String> commands = new ArrayList<>();
@@ -59,45 +47,6 @@ public class SpringBootPropertiesLanguageServer extends ProcessStreamConnectionP
setWorkingDirectory(workingDir);
}
@Override
public void handleMessage(Message message, LanguageServer languageServer, URI rootPath) {
if (message instanceof NotificationMessage) {
NotificationMessage notificationMessage = (NotificationMessage) message;
if ("sts/progress".equals(notificationMessage.getMethod())) {
JsonObject params = (JsonObject) notificationMessage.getParams();
String status = params.has("statusMsg") ? params.get("statusMsg").getAsString() : "";
showStatusMessage(status);
}
}
}
private void showStatusMessage(final String status) {
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
IStatusLineManager statusLineManager = getStatusLineManager();
if (statusLineManager != null) {
statusLineManager.setMessage(status);
}
}
});
}
private IStatusLineManager getStatusLineManager() {
try {
return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getEditorSite().getActionBars().getStatusLineManager();
}
catch (NullPointerException e) {
return null;
}
}
protected String getJDKLocation() {
IVMInstall jdk = JavaRuntime.getDefaultVMInstall();
File javaExecutable = StandardVMType.findJavaExecutable(jdk.getInstallLocation());
return javaExecutable.getAbsolutePath();
}
protected String getLanguageServerJARLocation() {
String languageServer = "boot-properties-language-server-" + Constants.LANGUAGE_SERVER_VERSION + "-SNAPSHOT.jar";
@@ -115,11 +64,6 @@ public class SpringBootPropertiesLanguageServer extends ProcessStreamConnectionP
return dataFile.getAbsolutePath();
}
protected String getWorkingDirLocation() {
// TODO: identify a reasonable working directory for the language server process
return System.getProperty("user.dir");
}
protected void copyLanguageServerJAR(String languageServerJarName) throws Exception {
Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID);
InputStream stream = FileLocator.openStream( bundle, new Path("servers/" + languageServerJarName), false );

View File

@@ -15,7 +15,6 @@ import java.nio.file.Path;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -31,7 +30,6 @@ import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -87,18 +85,32 @@ public final class CompilationUnitCache {
*/
public <T> T withCompilationUnit(TextDocument document, Function<CompilationUnit, T> requestor) {
URI uri = URI.create(document.getUri());
readLock.lock();
try {
CompilationUnit cu = uriToCu.get(uri, () -> parse(document));
if (cu!=null) {
synchronized (cu.getAST()) {
return requestor.apply(cu);
IJavaProject project = projectFinder.find(document.getId()).orElse(null);
if (project != null) {
readLock.lock();
try {
CompilationUnit cu = uriToCu.get(uri, () -> {
CompilationUnit cUnit = parse(document, project);
projectToDocs.get(project, () -> new HashSet<>()).add(URI.create(document.getUri()));
return cUnit;
});
if (cu!=null) {
projectToDocs.get(project, () -> new HashSet<>()).add(URI.create(document.getUri()));
synchronized (cu.getAST()) {
return requestor.apply(cu);
}
}
} catch (Exception e) {
Log.log(e);
} finally {
readLock.unlock();
}
} else {
try {
return requestor.apply(parse(document, null));
} catch (Exception e) {
Log.log(e);
}
} catch (Exception e) {
Log.log(e);
} finally {
readLock.unlock();
}
return requestor.apply(null);
}
@@ -137,16 +149,6 @@ public final class CompilationUnitCache {
return cu;
}
private CompilationUnit parse(TextDocument document)
throws Exception, BadLocationException {
IJavaProject project = projectFinder.find(document.getId()).orElse(null);
CompilationUnit cu = parse(document, project);
if (project != null) {
projectToDocs.get(project, () -> new HashSet<>()).add(URI.create(document.getUri()));
}
return cu;
}
private static String[] getClasspathEntries(TextDocument document, IJavaProject project) throws Exception {
if (project == null) {
return new String[0];

View File

@@ -23,11 +23,12 @@ import java.nio.file.Paths;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
import org.springframework.ide.vscode.commons.java.DelegatingCachedClasspath;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
@@ -39,7 +40,7 @@ import org.springframework.ide.vscode.project.harness.ProjectsHarness;
*/
public class CompilationUnitCacheTest {
private LanguageServerHarness<BootJavaLanguageServer> harness;
private BootLanguageServerHarness harness;
@Before
public void setup() throws Exception {
@@ -48,6 +49,14 @@ public class CompilationUnitCacheTest {
@Test
public void cu_cached() throws Exception {
harness = BootLanguageServerHarness.builder()
.mockDefaults().build();
harness.useProject(new IJavaProject() {
@Override
public IClasspath getClasspath() {
return new DelegatingCachedClasspath<>(() -> null, null);
}
});
harness.intialize(null);
TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" +
@@ -62,12 +71,36 @@ public class CompilationUnitCacheTest {
assertTrue(cu == cuAnother);
}
@Test
public void cu_not_cached_without_project() throws Exception {
harness.intialize(null);
TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" +
"\n" +
"public class SomeClass {\n" +
"\n" +
"}\n");
CompilationUnit cu = getCompilationUnit(doc);
assertNotNull(cu);
CompilationUnit cuAnother = getCompilationUnit(doc);
assertFalse(cu == cuAnother);
}
private CompilationUnit getCompilationUnit(TextDocument doc) {
return harness.getServer().getCompilationUnitCache().withCompilationUnit(doc, cu -> cu);
}
@Test
public void cu_cache_invalidated_by_doc_change() throws Exception {
harness = BootLanguageServerHarness.builder()
.mockDefaults().build();
harness.useProject(new IJavaProject() {
@Override
public IClasspath getClasspath() {
return new DelegatingCachedClasspath<>(() -> null, null);
}
});
harness.intialize(null);
TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" +
@@ -91,6 +124,14 @@ public class CompilationUnitCacheTest {
@Test
public void cu_cache_invalidated_by_doc_close() throws Exception {
harness = BootLanguageServerHarness.builder()
.mockDefaults().build();
harness.useProject(new IJavaProject() {
@Override
public IClasspath getClasspath() {
return new DelegatingCachedClasspath<>(() -> null, null);
}
});
harness.intialize(null);
TextDocument doc = new TextDocument(harness.createTempUri(), LanguageId.JAVA, 0, "package my.package\n" +

View File

@@ -334,14 +334,19 @@ public class PropertiesCompletionProposalsCalculator {
DocumentEdits docEdits;
try {
docEdits = LazyProposalApplier.from(() -> {
Type type = TypeParser.parse(match.data.getType());
DocumentEdits edits = new DocumentEdits(doc);
edits.delete(offset-prefix.length(), offset);
edits.insert(offset, match.data.getId() + propertyCompletionPostfix(typeUtil, type));
return edits;
try {
Type type = TypeParser.parse(match.data.getType());
DocumentEdits edits = new DocumentEdits(doc);
edits.delete(offset-prefix.length(), offset);
edits.insert(offset, match.data.getId() + propertyCompletionPostfix(typeUtil, type));
return edits;
} catch (Throwable t) {
Log.log(t);
return new DocumentEdits(doc);
}
});
proposals.add(completionFactory.property(doc, docEdits, match, typeUtil));
} catch (Exception e) {
} catch (Throwable e) {
Log.log(e);
}
}

View File

@@ -51,8 +51,7 @@ public class GradleProjectCache extends AbstractFileToProjectCache<GradleJavaPro
GradleJavaProject gradleJavaProject = new GradleJavaProject(gradle, gradleFile,
projectCacheFolder == null ? null : gradleFile.toPath().resolve(projectCacheFolder)
);
boolean cached = gradleJavaProject.getClasspath().isCached();
performUpdate(gradleJavaProject, cached && asyncUpdate, cached);
performUpdate(gradleJavaProject, asyncUpdate, asyncUpdate);
return gradleJavaProject;
}

View File

@@ -54,6 +54,8 @@ import reactor.util.function.Tuple2;
public class DelegatingCachedClasspath<T extends IClasspath> implements IClasspath {
public static final String CLASSPATH_DATA_CACHE_FILE = "classpath-data.json";
private static final ClasspathData EMPTY_CLASSPATH_DATA = new ClasspathData(null, Collections.emptySet(),
Collections.emptySet(), null);
private static final String OUTPUT_FOLDER_PROPERTY = "outputFolder";
private static final String CLASSPATH_RESOURCES_PROPERTY = "classpathResources";
@@ -238,15 +240,20 @@ public class DelegatingCachedClasspath<T extends IClasspath> implements IClasspa
@Override
public Flux<IType> allSubtypesOf(IType type) {
return cachedDelegate.get().allSubtypesOf(type);
T t = cachedDelegate.get();
return t == null ? Flux.empty() : t.allSubtypesOf(type);
}
protected ClasspathData createClasspathData() throws Exception {
T newDelegate = delegateCreator.call();
cachedDelegate.set(newDelegate);
LinkedHashSet<Path> classpathEntries = new LinkedHashSet<>(newDelegate.getClasspathEntries());
return new ClasspathData(newDelegate.getName(), classpathEntries,
new LinkedHashSet<>(newDelegate.getClasspathResources()), newDelegate.getOutputFolder());
if (newDelegate == null) {
return EMPTY_CLASSPATH_DATA;
} else {
LinkedHashSet<Path> classpathEntries = new LinkedHashSet<>(newDelegate.getClasspathEntries());
return new ClasspathData(newDelegate.getName(), classpathEntries,
new LinkedHashSet<>(newDelegate.getClasspathResources()), newDelegate.getOutputFolder());
}
}
}

View File

@@ -50,8 +50,7 @@ public class MavenProjectCache extends AbstractFileToProjectCache<MavenJavaProje
MavenJavaProject mavenJavaProject = new MavenJavaProject(maven, pomFile,
projectCacheFolder == null ? null : pomFile.getParentFile().toPath().resolve(projectCacheFolder)
);
boolean cached = mavenJavaProject.getClasspath().isCached();
performUpdate(mavenJavaProject, cached && asyncUpdate, cached);
performUpdate(mavenJavaProject, asyncUpdate, asyncUpdate);
return mavenJavaProject;
}

View File

@@ -176,13 +176,7 @@ public class MavenProjectCacheTest {
MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder);
MavenJavaProject project = cache.project(pomFile);
assertEquals(48, project.getClasspath().getClasspathEntries().size());
progressDone.set(false);
writeContent(pomFile,
new String(Files.readAllBytes(testProjectPath.resolve("pom.newxml")), Charset.defaultCharset()));
fileObserver.notifyFileChanged(pomFile.toURI().toString());
assertTrue(project.getClasspath().getClasspathEntries().isEmpty());
CompletableFuture.runAsync(() -> {
while (!progressDone.get()) {
@@ -192,10 +186,10 @@ public class MavenProjectCacheTest {
e.printStackTrace();
}
}
}).get(10, TimeUnit.SECONDS);
}).get(30, TimeUnit.SECONDS);
assertTrue(classpathCacheFile.exists());
assertEquals(49, project.getClasspath().getClasspathEntries().size());
assertEquals(48, project.getClasspath().getClasspathEntries().size());
progressDone.set(false);
@@ -204,18 +198,7 @@ public class MavenProjectCacheTest {
// Check loaded from cache file
project = cache.project(pomFile);
assertEquals(49, project.getClasspath().getClasspathEntries().size());
// check async project update (no changes no project changed event)
CompletableFuture.runAsync(() -> {
while (!progressDone.get()) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).get(10, TimeUnit.SECONDS);
assertEquals(48, project.getClasspath().getClasspathEntries().size());
}
@Test
@@ -243,11 +226,20 @@ public class MavenProjectCacheTest {
MavenProjectCache cache = new MavenProjectCache(server, MavenCore.getDefault(), true, cacheFolder);
MavenJavaProject project = cache.project(pomFile);
assertEquals(48, project.getClasspath().getClasspathEntries().size());
assertTrue(project.getClasspath().getClasspathEntries().isEmpty());
CompletableFuture.runAsync(() -> {
while (!progressDone.get()) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).get(30, TimeUnit.SECONDS);
progressDone.set(false);
verify(diagnosticService, never()).diagnosticEvent(any(ShowMessageException.class));
progressDone.set(false);
writeContent(pomFile, "");
fileObserver.notifyFileChanged(pomFile.toURI().toString());
CompletableFuture.runAsync(() -> {
@@ -258,10 +250,10 @@ public class MavenProjectCacheTest {
e.printStackTrace();
}
}
}).get(10, TimeUnit.SECONDS);
}).get(30, TimeUnit.SECONDS);
progressDone.set(false);
verify(diagnosticService, times(1)).diagnosticEvent(any(ShowMessageException.class));
assertTrue(project.getClasspath().getClasspathEntries().isEmpty());
assertFalse(cacheFolder.resolve(DelegatingCachedClasspath.CLASSPATH_DATA_CACHE_FILE).toFile().exists());
}
}
}