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 @@
-
+