diff --git a/.gitignore b/.gitignore index fc0d887..700005d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,36 @@ -.settings -/bin -/.project -target \ No newline at end of file +build/ +.out/ +bin/ +.bin/ +target/ + +/gradle.properties +/archive/ +/META-INF + +.classpath +.project +.settings + +.idea/ +*.iml +*.iws +*.ipr +.idea_modules/ +**/out/ + +*.tmp +*.bak +*.swp +*~ + +.gradle + +.DS_Store* +.AppleDouble +.LSOverride + +.directory +.Trash* + +**/adhoctest/ \ No newline at end of file diff --git a/README.md b/README.md index a660c7e..9251b6f 100644 --- a/README.md +++ b/README.md @@ -41,3 +41,21 @@ Once https://github.com/mickaelistria/eclipse-bluesky/issues/63 will work in Pho HTML syntax coloration (managed with TextMate) and HTML completion, mark occurrences, etc is not a part of this plugin. I suggest you that you install https://github.com/mickaelistria/eclipse-bluesky which provides those features. + +Development in Eclipse +====================== + +1. Use "Eclipse for Committers" (Photon M6 as of this writing). + +2. Under "Help" -> "Install New Software..." -> "Add" -> "Archive", and point to + `lsp4e-freemarker/repository/target/repository-X.X.X-SNAPSHOT.zip`. + Here install only the Dependencies, with the exception of those containing "freemarker" in their names. + (TODO: Find a better solution.) + +2. Now you can import the projects as Maven project. + +3. Wait until Eclipse finishes (there will be some errors). Now there should be a + `target-platform/target/target-platform-pde.target file.` Select that as the target + platform Under "Window" -> "Preferences" -> "Plug-in Development" -> "Target platform". (This file has + to be re-generated when new dependencies are added to the project. This file is only needed for development + in Eclipse, and is not used by the Maven build.) diff --git a/org.eclipse.lsp4e.freemarker.feature/.project b/org.eclipse.lsp4e.freemarker.feature/.project index 8a7975b..221f934 100644 --- a/org.eclipse.lsp4e.freemarker.feature/.project +++ b/org.eclipse.lsp4e.freemarker.feature/.project @@ -5,6 +5,11 @@ + + org.eclipse.jdt.core.javabuilder + + + org.eclipse.pde.FeatureBuilder @@ -17,6 +22,7 @@ + org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature org.eclipse.pde.FeatureNature diff --git a/org.eclipse.lsp4e.freemarker/META-INF/MANIFEST.MF b/org.eclipse.lsp4e.freemarker/META-INF/MANIFEST.MF index 5ac8e68..efba462 100644 --- a/org.eclipse.lsp4e.freemarker/META-INF/MANIFEST.MF +++ b/org.eclipse.lsp4e.freemarker/META-INF/MANIFEST.MF @@ -15,7 +15,7 @@ Require-Bundle: org.eclipse.lsp4e, org.eclipse.ui.workbench.texteditor, org.eclipse.ui.editors, org.eclipse.ui.genericeditor, - org.eclipse.jdt.launching + org.freemarker.languageserver-bundle Bundle-Activator: org.eclipse.lsp4e.freemarker.FreemarkerPlugin Bundle-ActivationPolicy: lazy Eclipse-BundleShape: dir diff --git a/org.eclipse.lsp4e.freemarker/build.properties b/org.eclipse.lsp4e.freemarker/build.properties index 9055566..a19665e 100644 --- a/org.eclipse.lsp4e.freemarker/build.properties +++ b/org.eclipse.lsp4e.freemarker/build.properties @@ -7,6 +7,5 @@ bin.includes = META-INF/,\ plugin.xml,\ snippets/,\ syntaxes/,\ - server/,\ templates/,\ icons/ diff --git a/org.eclipse.lsp4e.freemarker/plugin.xml b/org.eclipse.lsp4e.freemarker/plugin.xml index e68868b..5861929 100644 --- a/org.eclipse.lsp4e.freemarker/plugin.xml +++ b/org.eclipse.lsp4e.freemarker/plugin.xml @@ -34,7 +34,7 @@ diff --git a/org.eclipse.lsp4e.freemarker/server/freemarker-languageserver-all.jar b/org.eclipse.lsp4e.freemarker/server/freemarker-languageserver-all.jar deleted file mode 100644 index 0a7226b..0000000 Binary files a/org.eclipse.lsp4e.freemarker/server/freemarker-languageserver-all.jar and /dev/null differ diff --git a/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/FreemarkerLanguageServer.java b/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/FreemarkerLanguageServer.java deleted file mode 100644 index ae77b33..0000000 --- a/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/FreemarkerLanguageServer.java +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Copyright (c) 2018 Angelo ZERR. - * 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: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.lsp4e.freemarker; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.Field; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; -import org.eclipse.jdt.internal.launching.StandardVMType; -import org.eclipse.jdt.launching.IVMInstall; -import org.eclipse.jdt.launching.JavaRuntime; -import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider; -import org.osgi.framework.Bundle; - -/** - * LSP4e Freemarker Language server. - * - */ -public class FreemarkerLanguageServer extends ProcessStreamConnectionProvider { - - public FreemarkerLanguageServer() { - super(computeCommands(), computeWorkingDir()); - } - - private static String computeWorkingDir() { - return System.getProperty("user.dir"); - } - - private static List computeCommands() { - List commands = new ArrayList<>(); - // Try to use the configured Install JRE. - IVMInstall install = JavaRuntime.getDefaultVMInstall(); - if (install != null) { - File vmInstallLocation = install.getInstallLocation(); - File javaExecutableLocation = StandardVMType.findJavaExecutable(vmInstallLocation); - // ex: C:\Program Files\Java\jre1.8.0_77\bin\javaw.exe - commands.add(javaExecutableLocation.getAbsolutePath()); - } else { - commands.add("java"); - } - commands.add("-jar"); - commands.add(computeFreemarkerLanguageServerJarPath()); - return commands; - } - - private static String computeFreemarkerLanguageServerJarPath() { - Bundle bundle = Platform.getBundle(FreemarkerPlugin.PLUGIN_ID); - URL fileURL = bundle.getEntry("server/freemarker-languageserver-all.jar"); - try { - URL resolvedFileURL = FileLocator.toFileURL(fileURL); - - // We need to use the 3-arg constructor of URI in order to properly escape file - // system chars - URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null); - File file = new File(resolvedURI); - if (Platform.OS_WIN32.equals(Platform.getOS())) { - return "\"" + file.getAbsolutePath() + "\""; - } else { - return file.getAbsolutePath(); - } - } catch (URISyntaxException | IOException exception) { - FreemarkerPlugin.log(new Status(IStatus.ERROR, FreemarkerPlugin.PLUGIN_ID, - "Cannot get the FreeMarker LSP Server jar.", exception)); //$NON-NLS-1$ - } - return ""; - } - - class GetErrorThread extends Thread { - - private final Process process; - private String message = null; - - public GetErrorThread(Process process) { - this.process = process; - } - - @Override - public void run() { - try (final BufferedReader b = new BufferedReader(new InputStreamReader(getErrorStream()))) { - String line; - if ((line = b.readLine()) != null) { - message = line; - synchronized (FreemarkerLanguageServer.this) { - FreemarkerLanguageServer.this.notifyAll(); - } - } - } catch (IOException e) { - message = e.getMessage(); - } - } - - public void check() throws IOException { - if (message != null) { - throw new IOException(message); - } - if (!process.isAlive()) { - throw new IOException("Process is not alive"); //$NON-NLS-1$ - } - } - - } - - @Override - public void start() throws IOException { - // Start the process - super.start(); - // Get the process by Java reflection - Process p = getProcess(); - if (p != null) { - // Sart a thread which read error stream to check that the java command is - // working. - GetErrorThread t = new GetErrorThread(p); - try { - t.start(); - // wait a little to execute java command line... - synchronized (FreemarkerLanguageServer.this) { - try { - this.wait(500); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - // check if there is an error or if process is not alived. - try { - t.check(); - } catch (IOException e) { - throw new IOException("Unable to start language server: " + this.toString(), e); //$NON-NLS-1$ - } - } finally { - t.interrupt(); - } - } - } - - private Process getProcess() { - try { - Field f = ProcessStreamConnectionProvider.class.getDeclaredField("process"); - f.setAccessible(true); - Process p = (Process) f.get(this); - return p; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - @Override - protected ProcessBuilder createProcessBuilder() { - ProcessBuilder builder = super.createProcessBuilder(); - // override redirect to PIPE to read error stream with GetErrorThread - builder.redirectError(ProcessBuilder.Redirect.PIPE); - return builder; - } - - @Override - public String toString() { - return "FreeMarker (" + super.toString() + ")"; - } - -} diff --git a/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/FreemarkerLanguageServerStreamConnectionProvider.java b/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/FreemarkerLanguageServerStreamConnectionProvider.java new file mode 100644 index 0000000..bc27cc3 --- /dev/null +++ b/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/FreemarkerLanguageServerStreamConnectionProvider.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2018 Angelo ZERR. + * 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: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.lsp4e.freemarker; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.Future; + +import freemarker.ext.languageserver.FreemarkerLanguageServerLauncher; + +/** + * Provides a connection to the Freemarker Language Server, through which one can communicate with it through + * the protocol specified by the Language Server Protocol Specification. + */ +public class FreemarkerLanguageServerStreamConnectionProvider extends LocalStreamConnectionProvider { + + @Override + protected Future launch(InputStream clientToServerStream, OutputStream serverToClientStream) throws IOException { + return FreemarkerLanguageServerLauncher.launch(clientToServerStream, serverToClientStream); + } + +} diff --git a/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/LocalStreamConnectionProvider.java b/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/LocalStreamConnectionProvider.java new file mode 100644 index 0000000..143b6e9 --- /dev/null +++ b/org.eclipse.lsp4e.freemarker/src/org/eclipse/lsp4e/freemarker/LocalStreamConnectionProvider.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2018 Angelo ZERR. + * 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: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.lsp4e.freemarker; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.concurrent.Future; + +import org.eclipse.lsp4e.server.StreamConnectionProvider; + +/** + * A {@link StreamConnectionProvider} that connects to a LSP server that runs in the client's JVM, not as a separate process. + */ +public abstract class LocalStreamConnectionProvider implements StreamConnectionProvider { + + private static final int PIPE_BUFFER_SIZE = 8192; + + private PipedOutputStream clientToServerStream; + private PipedInputStream serverToClientStream; + private PipedInputStream clientToServerStreamReverse; + private PipedOutputStream serverToClientStreamReverse; + private Future launched; + + public LocalStreamConnectionProvider() { + } + + @Override + public synchronized void start() throws IOException { + clientToServerStream = new PipedOutputStream(); + serverToClientStream = new PipedInputStream(PIPE_BUFFER_SIZE); + clientToServerStreamReverse = new PipedInputStream(clientToServerStream, PIPE_BUFFER_SIZE); + serverToClientStreamReverse = new PipedOutputStream(serverToClientStream); + launched = launch(clientToServerStreamReverse, serverToClientStreamReverse); + } + + protected abstract Future launch(InputStream clientToServerStream, OutputStream serverToClientStream) throws IOException; + + @Override + public InputStream getInputStream() { + return serverToClientStream; + } + + @Override + public OutputStream getOutputStream() { + return clientToServerStream; + } + + @Override + public InputStream getErrorStream() { + return null; + } + + @Override + public synchronized void stop() { + if (launched == null) { + return; + } + + // TODO Not sure if it works like this... + launched.cancel(true); + launched = null; + + try { + clientToServerStream.close(); + } catch (IOException e) { + // TODO Log + e.printStackTrace(); + } + clientToServerStream = null; + + try { + clientToServerStreamReverse.close(); + } catch (IOException e) { + // TODO Log + e.printStackTrace(); + } + clientToServerStreamReverse = null; + + try { + serverToClientStreamReverse.close(); + } catch (IOException e) { + // TODO Log + e.printStackTrace(); + } + serverToClientStreamReverse = null; + + try { + serverToClientStream.close(); + } catch (IOException e) { + // TODO Log + e.printStackTrace(); + } + serverToClientStream = null; + } + +} diff --git a/pom.xml b/pom.xml index 14d9a4e..d98c28e 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,10 @@ https://github.com/angelozerr/lsp4e-freemarker 2018 + + + 1.1.0 + @@ -53,13 +57,13 @@ org.eclipse.tycho tycho-maven-plugin - 1.0.0 + ${tycho.version} true org.eclipse.tycho target-platform-configuration - 1.0.0 + ${tycho.version} true p2 @@ -77,7 +81,7 @@ org.eclipse.tycho tycho-source-plugin - 1.0.0 + ${tycho.version} plugin-source @@ -88,13 +92,13 @@ org.eclipse.tycho tycho-p2-plugin - 1.0.0 + ${tycho.version} attach-p2-metadata @@ -140,6 +144,16 @@ + + + + + org.freemarker + freemarker-languageserver-bundle + 0.0.1-SNAPSHOT + + + cbi diff --git a/repository/.project b/repository/.project index 468a3db..0c38fcd 100644 --- a/repository/.project +++ b/repository/.project @@ -5,6 +5,11 @@ + + org.eclipse.jdt.core.javabuilder + + + org.eclipse.m2e.core.maven2Builder @@ -12,6 +17,7 @@ + org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature diff --git a/repository/category.xml b/repository/category.xml index fb11087..d570634 100644 --- a/repository/category.xml +++ b/repository/category.xml @@ -69,6 +69,9 @@ + + + diff --git a/target-platform/pom.xml b/target-platform/pom.xml index fa635fa..ab06c8e 100644 --- a/target-platform/pom.xml +++ b/target-platform/pom.xml @@ -7,4 +7,37 @@ 1.0.0-SNAPSHOT eclipse-target-definition + + + + + + lt.velykis.maven + pde-target-maven-plugin + 1.0.0 + + + pde-target + + add-pom-dependencies + + + ${project.basedir}/target-platform.target + ${project.build.directory}/target-platform-pde.target + + + + + + diff --git a/target-platform/target-platform.target b/target-platform/target-platform.target index 412209a..56a8972 100644 --- a/target-platform/target-platform.target +++ b/target-platform/target-platform.target @@ -1,5 +1,5 @@ - +