diff --git a/eclipse-distribution/org.springframework.boot.ide.branding.feature/p2.inf b/eclipse-distribution/org.springframework.boot.ide.branding.feature/p2.inf index 82001f975..a060eefdf 100644 --- a/eclipse-distribution/org.springframework.boot.ide.branding.feature/p2.inf +++ b/eclipse-distribution/org.springframework.boot.ide.branding.feature/p2.inf @@ -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); diff --git a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/SpringBootJavaLanguageServer.java b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/SpringBootJavaLanguageServer.java index 3856499b7..4e2bbd1eb 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/SpringBootJavaLanguageServer.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/SpringBootJavaLanguageServer.java @@ -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 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 ); diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF index 6a945e88b..7443c1a53 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls/META-INF/MANIFEST.MF @@ -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", diff --git a/eclipse-language-servers/org.springframework.tooling.bosh.ls/plugin.xml b/eclipse-language-servers/org.springframework.tooling.bosh.ls/plugin.xml index 7f8ae7c10..66c711985 100644 --- a/eclipse-language-servers/org.springframework.tooling.bosh.ls/plugin.xml +++ b/eclipse-language-servers/org.springframework.tooling.bosh.ls/plugin.xml @@ -85,6 +85,7 @@ 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 ); diff --git a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/plugin.xml b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/plugin.xml index f13feb6b2..538d4e5be 100644 --- a/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/plugin.xml +++ b/eclipse-language-servers/org.springframework.tooling.cloudfoundry.manifest.ls/plugin.xml @@ -7,6 +7,7 @@ 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 ); diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF index 498fe1ac0..9cfeb7391 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF @@ -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, diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/ProgressParams.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/ProgressParams.java new file mode 100644 index 000000000..11322fcc4 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/ProgressParams.java @@ -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; + } + +} diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClient.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClient.java index 513711148..9e72b46fc 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClient.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClient.java @@ -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 moveCursor(CursorMovement cursorMovement); diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java index 6057c6ab4..adf5a1ebe 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java @@ -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; + } + } + } diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java new file mode 100644 index 000000000..e5e89c430 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java @@ -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"); + } + +} diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolDialog.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolDialog.java index b351f1fa1..2548458bd 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolDialog.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.gotosymbol/src/org/springframework/tooling/ls/eclipse/gotosymbol/dialogs/GotoSymbolDialog.java @@ -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 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 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 getWorkspaceLocation(SymbolInformation symbolInformation) { + private Optional 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(); diff --git a/eclipse-language-servers/org.springframework.tooling.properties.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.properties.ls/META-INF/MANIFEST.MF index 5cee1cc31..ea9911ca8 100644 --- a/eclipse-language-servers/org.springframework.tooling.properties.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.properties.ls/META-INF/MANIFEST.MF @@ -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", diff --git a/eclipse-language-servers/org.springframework.tooling.properties.ls/plugin.xml b/eclipse-language-servers/org.springframework.tooling.properties.ls/plugin.xml index 2715a02be..8d7011e19 100644 --- a/eclipse-language-servers/org.springframework.tooling.properties.ls/plugin.xml +++ b/eclipse-language-servers/org.springframework.tooling.properties.ls/plugin.xml @@ -81,6 +81,7 @@ 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 ); diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java index a3111cbc6..a35a14572 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/CompilationUnitCache.java @@ -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 withCompilationUnit(TextDocument document, Function 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]; diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java index 367cfe26f..67d021f85 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java @@ -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 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" + diff --git a/headless-services/boot-properties-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/PropertiesCompletionProposalsCalculator.java b/headless-services/boot-properties-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/PropertiesCompletionProposalsCalculator.java index 2b6ff9e5e..7ca069404 100644 --- a/headless-services/boot-properties-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/PropertiesCompletionProposalsCalculator.java +++ b/headless-services/boot-properties-language-server/src/main/java/org/springframework/ide/vscode/boot/properties/completions/PropertiesCompletionProposalsCalculator.java @@ -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); } } diff --git a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectCache.java b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectCache.java index f494882c9..657a0cd66 100644 --- a/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectCache.java +++ b/headless-services/commons/commons-gradle/src/main/java/org/springframework/ide/vscode/commons/gradle/GradleProjectCache.java @@ -51,8 +51,7 @@ public class GradleProjectCache extends AbstractFileToProjectCache 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 implements IClasspa @Override public Flux 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 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 classpathEntries = new LinkedHashSet<>(newDelegate.getClasspathEntries()); + return new ClasspathData(newDelegate.getName(), classpathEntries, + new LinkedHashSet<>(newDelegate.getClasspathResources()), newDelegate.getOutputFolder()); + } } } diff --git a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java index 2a237238b..19d451445 100644 --- a/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java +++ b/headless-services/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectCache.java @@ -50,8 +50,7 @@ public class MavenProjectCache extends AbstractFileToProjectCache { 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()); } -} +} \ No newline at end of file