diff --git a/eclipse-language-servers/org.springframework.tooling.boot.java.ls.feature/feature.xml b/eclipse-language-servers/org.springframework.tooling.boot.java.ls.feature/feature.xml index f928a6a9b..00ef93583 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.java.ls.feature/feature.xml +++ b/eclipse-language-servers/org.springframework.tooling.boot.java.ls.feature/feature.xml @@ -26,4 +26,11 @@ unpack="false"> + + diff --git a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/META-INF/MANIFEST.MF b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/META-INF/MANIFEST.MF index 3203fb180..e82533c6b 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/META-INF/MANIFEST.MF +++ b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/META-INF/MANIFEST.MF @@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0", org.eclipse.lsp4j, org.eclipse.ui.workbench, org.eclipse.jface, - org.eclipse.xtext.xbase.lib + org.eclipse.xtext.xbase.lib, + org.springframework.tooling.ls.eclipse.commons 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.boot.java.ls/plugin.xml b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/plugin.xml index a268a7672..ff3b0db66 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/plugin.xml +++ b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/plugin.xml @@ -7,6 +7,7 @@ + + + + + + diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/.project b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/.project new file mode 100644 index 000000000..8e91c72d0 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/.project @@ -0,0 +1,28 @@ + + + org.springframework.tooling.ls.eclipse.commons + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/.settings/org.eclipse.jdt.core.prefs b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..0c68a61dc --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 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 new file mode 100644 index 000000000..a2efd8a6d --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Eclipse Language Server Commons +Bundle-SymbolicName: org.springframework.tooling.ls.eclipse.commons;singleton:=true +Bundle-Version: 4.0.0.qualifier +Bundle-Activator: org.springframework.tooling.ls.eclipse.commons.LsEclipseCommonsActivator +Bundle-Vendor: Pivotal, Inc. +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.lsp4e;bundle-version="0.3.0", + org.eclipse.lsp4j.jsonrpc, + org.eclipse.lsp4j, + org.eclipse.ui.workbench.texteditor, + org.eclipse.jface.text, + com.google.guava +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Export-Package: org.springframework.tooling.ls.eclipse.commons diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/build.properties b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/build.properties new file mode 100644 index 000000000..e9863e281 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/icons/boot-icon.png b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/icons/boot-icon.png new file mode 100644 index 000000000..de88ef0d5 Binary files /dev/null and b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/icons/boot-icon.png differ diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml new file mode 100644 index 000000000..64529da6a --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/plugin.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/pom.xml b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/pom.xml new file mode 100644 index 000000000..137d90143 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + org.springframework.boot.ide + org.springframework.boot.ide.servers + 4.0.0-SNAPSHOT + ../pom.xml + + + org.springframework.tooling.ls.eclipse.commons + eclipse-plugin + + diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/HighlightParams.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/HighlightParams.java new file mode 100644 index 000000000..aa0836a97 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/HighlightParams.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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.util.List; + +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.TextDocumentIdentifier; + +public class HighlightParams { + + //TODO: Identical copy of this exists in org.springframework.ide.vscode.commons.languageserver.HighlightParams + // But because that is only built in plain maven jar (not osgi) we can't use it. We should find a solution + // for this somehow (i.e. build a version of some of our 'plain maven' jars as osgi bundles and publish on + // a update site. + + private TextDocumentIdentifier doc; + private List ranges; + + public HighlightParams() { + } + + public HighlightParams(TextDocumentIdentifier doc, List ranges) { + super(); + this.doc = doc; + this.ranges = ranges; + } + public TextDocumentIdentifier getDoc() { + return doc; + } + public void setDoc(TextDocumentIdentifier doc) { + this.doc = doc; + } + public List getRanges() { + return ranges; + } + public void setRanges(List ranges) { + this.ranges = ranges; + } + + @Override + public String toString() { + return "HighlightParams [doc=" + doc + ", ranges=" + ranges + "]"; + } +} diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LsEclipseCommonsActivator.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LsEclipseCommonsActivator.java new file mode 100644 index 000000000..58f80c83c --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/LsEclipseCommonsActivator.java @@ -0,0 +1,50 @@ +package org.springframework.tooling.ls.eclipse.commons; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class LsEclipseCommonsActivator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.springframework.tooling.ls.eclipse.commons"; //$NON-NLS-1$ + + // The shared instance + private static LsEclipseCommonsActivator plugin; + + /** + * The constructor + */ + public LsEclipseCommonsActivator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static LsEclipseCommonsActivator getDefault() { + return plugin; + } + +} 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 new file mode 100644 index 000000000..bd35b3d3f --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClient.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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.util.concurrent.CompletableFuture; + +import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; +import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; +import org.eclipse.lsp4j.services.LanguageClient; + +/** + * Some 'custom' extensions to standard LSP {@link LanguageClient}. + * + * @author Kris De Volder + */ +public interface STS4LanguageClient extends LanguageClient { + + @JsonNotification("sts/highlight") + void highlight(HighlightParams highlights); + +// TODO: @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 new file mode 100644 index 000000000..6057c6ab4 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * 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.lang.reflect.Method; +import java.net.URI; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +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.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.IAnnotationModelExtension; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.lsp4e.LSPEclipseUtils; +import org.eclipse.lsp4e.LanguageClientImpl; +import org.eclipse.lsp4e.LanguageServiceAccessor; +import org.eclipse.lsp4e.LanguageServiceAccessor.LSPDocumentInfo; +import org.eclipse.lsp4j.Range; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.progress.UIJob; +import org.eclipse.ui.texteditor.AbstractTextEditor; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +@SuppressWarnings("restriction") +public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4LanguageClient { + + private static final String ANNOTION_TYPE_ID = "org.springframework.tooling.bootinfo"; + + class UpdateHighlights extends UIJob { + + private String target; + + UpdateHighlights(String target) { + super("Update highlights"); + this.target = target; + setSystem(true); + schedule(); + } + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + IWorkbenchWindow ww = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (ww!=null) { + IWorkbenchPage page = ww.getActivePage(); + if (page!=null) { + IEditorPart editorPart = page.getActiveEditor(); + if (editorPart instanceof AbstractTextEditor) { + try { + Method m = AbstractTextEditor.class.getDeclaredMethod("getSourceViewer"); + m.setAccessible(true); + ISourceViewer sourceViewer = (ISourceViewer) m.invoke(editorPart); + if (sourceViewer!=null) { + IAnnotationModel annotationModel = sourceViewer.getAnnotationModel(); + if (annotationModel!=null) { + IDocument doc = sourceViewer.getDocument(); + if (sourceViewer!=null) { + if (doc!=null && annotationModel instanceof IAnnotationModelExtension) { + updateAnnotations(target, doc, (IAnnotationModelExtension) annotationModel); + } + } + } + } + } catch (Exception e) { + //ignore reflection errors + } + } + } + } + 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> currentHighlights = new HashMap<>(); + + /** + * Current markers... indexed per document uri, needed sp we to be removed upon next update. + */ + private Map currentAnnotations = new HashMap<>(); + + private synchronized void updateAnnotations(String target, IDocument doc, IAnnotationModelExtension annotationModel) { + if (target!=null) { + Collection infos = LanguageServiceAccessor.getLSPDocumentInfosFor(doc, (x) -> true); + for (LSPDocumentInfo docInfo : infos) { + URI uri = docInfo.getFileUri(); + if (uri!=null && uri.toString().equals(target)) { + Annotation[] toRemove = currentAnnotations.get(target); + if (toRemove==null) { + toRemove = new Annotation[0]; + } + Map newAnnotations = createAnnotations(doc, currentHighlights.get(target)); + annotationModel.replaceAnnotations(toRemove, newAnnotations); + currentAnnotations.put(target, newAnnotations.keySet().toArray(new Annotation[newAnnotations.size()])); + } + } + } + } + + private Map createAnnotations(IDocument doc, List highlights) { + ImmutableMap.Builder annotations = ImmutableMap.builder(); + if (highlights==null) { + highlights = ImmutableList.of(); + } + for (Range rng : highlights) { + try { + int start = LSPEclipseUtils.toOffset(rng.getStart(), doc); + int end = LSPEclipseUtils.toOffset(rng.getEnd(), doc); + Position e_rng = new Position(start, Math.max(0, end-start)); + annotations.put(new Annotation(ANNOTION_TYPE_ID, false, null), e_rng); + } catch (BadLocationException e) { + //ignore invalid highlights + } + } + return annotations.build(); + } + + @Override + public synchronized void highlight(HighlightParams highlights) { + String target = highlights.getDoc().getUri(); + if (target!=null) { + currentHighlights.put(target, highlights.getRanges()); + new UpdateHighlights(target); + } + } + +} diff --git a/eclipse-language-servers/org.springframework.tooling.properties.ls/src/org/springframework/tooling/properties/ls/SpringBootPropertiesLanguageServer.java b/eclipse-language-servers/org.springframework.tooling.properties.ls/src/org/springframework/tooling/properties/ls/SpringBootPropertiesLanguageServer.java index 32ab8c49b..44e3434fa 100644 --- a/eclipse-language-servers/org.springframework.tooling.properties.ls/src/org/springframework/tooling/properties/ls/SpringBootPropertiesLanguageServer.java +++ b/eclipse-language-servers/org.springframework.tooling.properties.ls/src/org/springframework/tooling/properties/ls/SpringBootPropertiesLanguageServer.java @@ -12,6 +12,7 @@ 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; @@ -58,7 +59,8 @@ public class SpringBootPropertiesLanguageServer extends ProcessStreamConnectionP setWorkingDirectory(workingDir); } - public void handleMessage(Message message, LanguageServer languageServer, String rootPath) { + @Override + public void handleMessage(Message message, LanguageServer languageServer, URI rootPath) { if (message instanceof NotificationMessage) { NotificationMessage notificationMessage = (NotificationMessage) message; if ("sts/progress".equals(notificationMessage.getMethod())) { diff --git a/eclipse-language-servers/pom.xml b/eclipse-language-servers/pom.xml index a888127e1..71aafefdf 100644 --- a/eclipse-language-servers/pom.xml +++ b/eclipse-language-servers/pom.xml @@ -27,6 +27,8 @@ + org.springframework.tooling.ls.eclipse.commons + org.springframework.tooling.cloudfoundry.manifest.ls org.springframework.tooling.cloudfoundry.manifest.ls.feature org.springframework.tooling.ls.repository diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/STS4LanguageClient.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/STS4LanguageClient.java index 2d7892023..c8f868ae2 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/STS4LanguageClient.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/STS4LanguageClient.java @@ -21,7 +21,7 @@ import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEd /** * Some 'custom' extensions to standard LSP {@link LanguageClient}. * - * @author + * @author Kris De Volder */ public interface STS4LanguageClient extends LanguageClient { diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java index f732c61bc..7de3d0e94 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java @@ -459,5 +459,4 @@ public abstract class SimpleLanguageServer implements LanguageServer, LanguageCl Assert.isLegal(this.testListener==null); testListener = languageServerTestListener; } - } diff --git a/vscode-extensions/commons-vscode/src/highlight-service.ts b/vscode-extensions/commons-vscode/src/highlight-service.ts index f31c5888d..81b8e265a 100644 --- a/vscode-extensions/commons-vscode/src/highlight-service.ts +++ b/vscode-extensions/commons-vscode/src/highlight-service.ts @@ -43,8 +43,6 @@ export class HighlightService { refresh(uri : String) { let editor = VSCode.window.activeTextEditor; let activeUri = editor.document.uri.toString(); - console.log("Refreshing uri :" + uri); - console.log(" active editor uri :" + editor.document.uri); if (uri===activeUri) { //We only update highlights in the active editor for now let highlights : Range[] = this.highlights.get(uri) || [];