Skip to content

Commit

Permalink
Report invalid runtime config back to the client (#1550)
Browse files Browse the repository at this point in the history
  • Loading branch information
testforstephen authored Sep 28, 2020
1 parent 8b7e12d commit e69383c
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Red Hat Inc. and others.
* Copyright (c) 2019-2020 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -42,7 +42,11 @@
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences.Severity;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.MessageType;

/**
* Configures and listens to JVM changes.
Expand Down Expand Up @@ -89,6 +93,10 @@ public static boolean configureDefaultVM(String javaHome) throws CoreException {
}

public static boolean configureJVMs(Preferences preferences) throws CoreException {
return configureJVMs(preferences, null);
}

public static boolean configureJVMs(Preferences preferences, JavaClientConnection connection) throws CoreException {
boolean changed = false;
boolean defaultVMSet = false;
Set<RuntimeEnvironment> runtimes = preferences.getRuntimes();
Expand Down Expand Up @@ -116,10 +124,16 @@ public static boolean configureJVMs(Preferences preferences) throws CoreExceptio

IStatus status = installType.validateInstallLocation(file);
if (!status.isOK()) {
if (Objects.equals(file.getName(), "bin")) {
sendNotification(connection, "Invalid runtime for " + runtime.getName() + ": 'bin' should be removed from the path (" + runtime.getPath() + ").");
} else {
sendNotification(connection, "Invalid runtime for " + runtime.getName() + ": The path (" + runtime.getPath() + ") does not point to a JDK.");
}
JavaLanguageServerPlugin.log(status);
continue;
}


vmStandin.setName(runtime.getName());
vmStandin.setInstallLocation(file);

Expand Down Expand Up @@ -158,9 +172,11 @@ public static boolean configureJVMs(Preferences preferences) throws CoreExceptio
}
}
if (!setDefaultEnvironmentVM(vm, runtime.getName())) {
sendNotification(connection, "Invalid runtime for " + runtime.getName() + ": Runtime at '" + runtime.getPath() + "' is not compatible with the '" + runtime.getName() + "' environment.");
JavaLanguageServerPlugin.logError("Runtime at '" + runtime.getPath() + "' is not compatible with the '" + runtime.getName() + "' environment");
}
} else {
sendNotification(connection, "Invalid runtime for " + runtime.getName() + ": The path points to a missing or inaccessible folder (" + runtime.getPath() + ").");
JavaLanguageServerPlugin.logInfo("Invalid runtime: " + runtime);
}
}
Expand All @@ -177,6 +193,26 @@ public static boolean configureJVMs(Preferences preferences) throws CoreExceptio
return changed;
}

private static void sendNotification(JavaClientConnection connection, String message) {
if (connection == null) {
return;
}

PreferenceManager preferencesManager = JavaLanguageServerPlugin.getPreferencesManager();
if (preferencesManager != null && preferencesManager.getClientPreferences().isActionableRuntimeNotificationSupport()) {
ActionableNotification runtimeNotification = new ActionableNotification()
.withSeverity(Severity.error.toMessageType())
.withMessage(message)
.withCommands(Arrays.asList(
new Command("Open Settings", "java.runtimeValidation.open", null)
));
connection.sendActionableNotification(runtimeNotification);
return;
}

connection.showNotificationMessage(MessageType.Error, message);
}

private static boolean setDefaultEnvironmentVM(IVMInstall vm, String name) {
IExecutionEnvironment environment = getExecutionEnvironment(name);
if (environment != null) {
Expand Down Expand Up @@ -287,7 +323,6 @@ public static void configureJVMSettings(IJavaProject javaProject, IVMInstall vmI
Map<String, String> options = javaProject.getOptions(false);
JavaCore.setComplianceOptions(compliance, options);
}
;
if (JavaCore.compareJavaVersions(version, JavaCore.latestSupportedJavaVersion()) >= 0) {
//Enable Java preview features for the latest JDK release by default and stfu about it
javaProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.ENABLED);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ public void didChangeConfiguration(DidChangeConfigurationParams params) {
syncCapabilitiesToSettings();
boolean jvmChanged = false;
try {
jvmChanged = jvmConfigurator.configureJVMs(preferenceManager.getPreferences());
jvmChanged = jvmConfigurator.configureJVMs(preferenceManager.getPreferences(), this.client);
} catch (Exception e) {
JavaLanguageServerPlugin.logException(e.getMessage(), e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017-2018 Red Hat Inc. and others.
* Copyright (c) 2017-2020 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -229,6 +229,10 @@ public boolean isActionableNotificationSupported() {
return Boolean.parseBoolean(extendedClientCapabilities.getOrDefault("actionableNotificationSupported", "false").toString());
}

public boolean isActionableRuntimeNotificationSupport() {
return Boolean.parseBoolean(extendedClientCapabilities.getOrDefault("actionableRuntimeNotificationSupport", "false").toString());
}

public boolean isGradleChecksumWrapperPromptSupport() {
return Boolean.parseBoolean(extendedClientCapabilities.getOrDefault("gradleChecksumWrapperPromptSupport", "false").toString());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 Red Hat Inc. and others.
* Copyright (c) 2019-2020 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
Expand All @@ -17,10 +17,13 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import java.io.File;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
Expand All @@ -41,11 +44,15 @@
import org.eclipse.jdt.launching.LibraryLocation;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.ls.core.internal.managers.AbstractInvisibleProjectBasedTest;
import org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences;
import org.eclipse.lsp4j.MessageParams;
import org.eclipse.lsp4j.MessageType;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.osgi.framework.Bundle;

Expand All @@ -57,16 +64,22 @@ public class JVMConfiguratorTest extends AbstractInvisibleProjectBasedTest {

private static final String ENVIRONMENT_NAME = "JavaSE-11";
private IVMInstall originalVm;
private JavaClientConnection javaClient;

@Mock
private ClientPreferences clientPreferences;

@Before
public void setup() {
originalVm = JavaRuntime.getDefaultVMInstall();
javaClient = new JavaClientConnection(client);
}

@Override
@After
public void cleanUp() throws CoreException {
JavaRuntime.setDefaultVMInstall(originalVm, new NullProgressMonitor());
javaClient.disconnect();
}

@Test
Expand Down Expand Up @@ -160,14 +173,67 @@ public void testPreviewFeatureSettings() throws Exception {
assertComplianceAndPreviewSupport(defaultProject, "1.8", false);
assertComplianceAndPreviewSupport(randomProject, "1.8", false);


} finally {
JavaRuntime.removeVMInstallChangedListener(jvmConfigurator);
}
}

@Test
public void testInvalidRuntimeWithActionableNotification() throws Exception {
when(this.preferenceManager.getClientPreferences()).thenReturn(clientPreferences);
when(clientPreferences.isActionableRuntimeNotificationSupport()).thenReturn(true);

Preferences prefs = new Preferences();
File file = new File("fakejdk2", "11a_nonexist");
String path = file.getAbsolutePath();
Set<RuntimeEnvironment> runtimes = new HashSet<>();
RuntimeEnvironment runtime = new RuntimeEnvironment();
runtime.setPath(path);
runtime.setName(ENVIRONMENT_NAME);
runtimes.add(runtime);
prefs.setRuntimes(runtimes);

JVMConfigurator.configureJVMs(prefs, javaClient);

List<ActionableNotification> notifications = getClientRequests("sendActionableNotification");
assertEquals(1, notifications.size());
ActionableNotification notification = notifications.get(0);
assertEquals(MessageType.Error, notification.getSeverity());
assertEquals(1, notification.getCommands().size());
}

@Test
public void testInvalidRuntime() throws Exception {
when(this.preferenceManager.getClientPreferences()).thenReturn(clientPreferences);
when(clientPreferences.isActionableRuntimeNotificationSupport()).thenReturn(false);

Preferences prefs = new Preferences();
File file = new File("fakejdk2", "11a" + File.separator + "bin");
String path = file.getAbsolutePath();
Set<RuntimeEnvironment> runtimes = new HashSet<>();
RuntimeEnvironment runtime = new RuntimeEnvironment();
runtime.setPath(path);
runtime.setName(ENVIRONMENT_NAME);
runtimes.add(runtime);
prefs.setRuntimes(runtimes);

JVMConfigurator.configureJVMs(prefs, javaClient);

List<MessageParams> notifications = getClientRequests("showMessage");
assertEquals(1, notifications.size());
MessageParams notification = notifications.get(0);
assertEquals(MessageType.Error, notification.getType());
assertEquals("Invalid runtime for " + runtime.getName() + ": 'bin' should be removed from the path (" + runtime.getPath() + ").", notification.getMessage());
}

private void assertComplianceAndPreviewSupport(IJavaProject javaProject, String compliance, boolean previewEnabled) {
assertEquals(previewEnabled ? JavaCore.ENABLED : JavaCore.DISABLED, javaProject.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, true));
assertEquals(compliance, javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true));
}

@SuppressWarnings("unchecked")
private <T> List<T> getClientRequests(String name) {
List<?> requests = clientRequests.get(name);
return requests != null ? (List<T>) requests : Collections.emptyList();
}
}

0 comments on commit e69383c

Please sign in to comment.