blob: 1910781967653e5ce727cb223f9f14d90515acf2 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2017, 2018 Red Hat Inc. and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Lucas Bullen (Red Hat Inc.) - Initial implementation
*******************************************************************************/
package org.eclipse.corrosion;
import java.io.BufferedReader;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.lsp4e.server.StreamConnectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
public class RLSStreamConnectionProvider implements StreamConnectionProvider {
private static boolean hasCancelledSetup = false;
private boolean DEBUG = Boolean.parseBoolean(System.getProperty("rsl.lsp.debug"));
private Process process;
@Override
public void start() throws IOException {
boolean wereSystemPropertiesSet = setSystemProperties();
String rls = getRLS();
if ((rls.isEmpty() || !wereSystemPropertiesSet)) {
showSetupRustNotification();
return;
}
String[] command = new String[] { "/bin/bash", "-c", rls };
if (Platform.getOS().equals(Platform.OS_WIN32)) {
command = new String[] { "cmd", "/c", rls };
}
this.process = Runtime.getRuntime().exec(command);
}
private boolean setSystemProperties() {
CorrosionPlugin plugin = CorrosionPlugin.getDefault();
IPreferenceStore preferenceStore = plugin.getPreferenceStore();
int rustSourceIndex = CorrosionPreferencePage.RUST_SOURCE_OPTIONS
.indexOf(preferenceStore.getString(CorrosionPreferenceInitializer.rustSourcePreference));
String sysrootPath = "";
if (rustSourceIndex == 0) {
String rustup = preferenceStore.getString(CorrosionPreferenceInitializer.rustupPathPreference);
String toolchain = preferenceStore.getString(CorrosionPreferenceInitializer.toolchainIdPreference);
if (!(rustup.isEmpty() || toolchain.isEmpty())) {
String[] command = new String[] { rustup, "run", toolchain, "rustc", "--print", "sysroot" };
try {
Process process = Runtime.getRuntime().exec(command);
try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
sysrootPath = in.readLine();
}
} catch (IOException e) {
// Caught with final return
}
}
} else if (rustSourceIndex == 1) {
sysrootPath = preferenceStore.getString(CorrosionPreferenceInitializer.sysrootPathPreference);
}
if (!sysrootPath.isEmpty()) {
System.setProperty("SYS_ROOT", sysrootPath);
System.setProperty("LD_LIBRARY_PATH", sysrootPath + "/lib");
String sysRoot = System.getProperty("SYS_ROOT");
String ldLibraryPath = System.getProperty("LD_LIBRARY_PATH");
if (!(sysRoot == null || sysRoot.isEmpty() || ldLibraryPath == null || ldLibraryPath.isEmpty())) {
return true;
}
}
CorrosionPlugin.getDefault().getLog().log(new Status(IStatus.ERROR,
CorrosionPlugin.getDefault().getBundle().getSymbolicName(),
"Was unable to set the `SYS_ROOT` and `LD_LIBRARY_PATH` environment variables. Please do so manually."));
return false;
}
private String getRLS() {
CorrosionPlugin plugin = CorrosionPlugin.getDefault();
IPreferenceStore preferenceStore = plugin.getPreferenceStore();
int rustSourceIndex = CorrosionPreferencePage.RUST_SOURCE_OPTIONS
.indexOf(preferenceStore.getString(CorrosionPreferenceInitializer.rustSourcePreference));
if (rustSourceIndex == 0) {
String rustup = preferenceStore.getString(CorrosionPreferenceInitializer.rustupPathPreference);
String toolchain = preferenceStore.getString(CorrosionPreferenceInitializer.toolchainIdPreference);
if (!(rustup.isEmpty() || toolchain.isEmpty())) {
return rustup + " run " + toolchain + " rls";
}
} else if (rustSourceIndex == 1) {
String rls = preferenceStore.getString(CorrosionPreferenceInitializer.rlsPathPreference);
if (!rls.isEmpty()) {
return rls;
}
}
CorrosionPlugin.getDefault().getLog()
.log(new Status(IStatus.ERROR, CorrosionPlugin.getDefault().getBundle().getSymbolicName(),
"Rust Language Server not found. Update in Rust preferences."));
return "";
}
private void showSetupRustNotification() {
if (hasCancelledSetup) {
return;
}
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
int dialogResponse = MessageDialog.open(MessageDialog.CONFIRM, shell, "Rust Support Not Found",
"Requirments for Rust edition were not found. Install the required components or input their paths in the Rust Preferences.",
SWT.NONE, "Open Preferences", "Cancel");
if (dialogResponse == 0) {
PreferenceDialog preferenceDialog = PreferencesUtil.createPreferenceDialogOn(shell,
CorrosionPreferencePage.PAGE_ID, new String[] { CorrosionPreferencePage.PAGE_ID }, null);
preferenceDialog.setBlockOnOpen(true);
preferenceDialog.open();
} else {
hasCancelledSetup = true;
}
}
@Override
public InputStream getInputStream() {
if (DEBUG) {
return new FilterInputStream(process.getInputStream()) {
@Override
public int read() throws IOException {
int res = super.read();
System.err.print((char) res);
return res;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int bytes = super.read(b, off, len);
byte[] payload = new byte[bytes];
System.arraycopy(b, off, payload, 0, bytes);
System.err.print(new String(payload));
return bytes;
}
@Override
public int read(byte[] b) throws IOException {
int bytes = super.read(b);
byte[] payload = new byte[bytes];
System.arraycopy(b, 0, payload, 0, bytes);
System.err.print(new String(payload));
return bytes;
}
};
} else {
return process.getInputStream();
}
}
@Override
public OutputStream getOutputStream() {
if (DEBUG) {
return new FilterOutputStream(process.getOutputStream()) {
@Override
public void write(int b) throws IOException {
System.err.print((char) b);
super.write(b);
}
@Override
public void write(byte[] b) throws IOException {
System.err.print(new String(b));
super.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
byte[] actual = new byte[len];
System.arraycopy(b, off, actual, 0, len);
System.err.print(new String(actual));
super.write(b, off, len);
}
};
} else {
return process.getOutputStream();
}
}
@Override
public void stop() {
process.destroy();
}
@Override
public InputStream getErrorStream() {
if (DEBUG) {
return new FilterInputStream(process.getErrorStream()) {
@Override
public int read() throws IOException {
int res = super.read();
System.err.print((char) res);
return res;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int bytes = super.read(b, off, len);
byte[] payload = new byte[bytes];
System.arraycopy(b, off, payload, 0, bytes);
System.err.print(new String(payload));
return bytes;
}
@Override
public int read(byte[] b) throws IOException {
int bytes = super.read(b);
byte[] payload = new byte[bytes];
System.arraycopy(b, 0, payload, 0, bytes);
System.err.print(new String(payload));
return bytes;
}
};
} else {
return process.getErrorStream();
}
}
}