diff --git a/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java b/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java index b227005e9529..451e25655dd2 100644 --- a/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java +++ b/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java @@ -124,7 +124,7 @@ public class JavaParametersUtil { JavaParameters parameters, @MagicConstant(valuesFromClass = JavaParameters.class) int classPathType, @Nullable String jreHome) throws CantRunException { - parameters.configureByModule(module, classPathType, createModuleJdk(module, jreHome)); + parameters.configureByModule(module, classPathType, createModuleJdk(module, (classPathType & JavaParameters.TESTS_ONLY) == 0, jreHome)); } public static void configureProject(Project project, @@ -134,8 +134,8 @@ public class JavaParametersUtil { parameters.configureByProject(project, classPathType, createProjectJdk(project, jreHome)); } - private static Sdk createModuleJdk(final Module module, @Nullable String jreHome) throws CantRunException { - return jreHome == null ? JavaParameters.getModuleJdk(module) : createAlternativeJdk(jreHome); + private static Sdk createModuleJdk(final Module module, boolean productionOnly, @Nullable String jreHome) throws CantRunException { + return jreHome == null ? JavaParameters.getValidJdkToRunModule(module, productionOnly) : createAlternativeJdk(jreHome); } public static Sdk createProjectJdk(final Project project, @Nullable String jreHome) throws CantRunException { diff --git a/java/execution/openapi/src/com/intellij/execution/configurations/JavaParameters.java b/java/execution/openapi/src/com/intellij/execution/configurations/JavaParameters.java index 7025dc3188ff..516290113e97 100644 --- a/java/execution/openapi/src/com/intellij/execution/configurations/JavaParameters.java +++ b/java/execution/openapi/src/com/intellij/execution/configurations/JavaParameters.java @@ -27,11 +27,15 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.encoding.EncodingProjectManager; import com.intellij.util.NotNullFunction; import com.intellij.util.PathsList; +import com.intellij.util.Processor; +import com.intellij.util.text.VersionComparatorUtil; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.nio.charset.Charset; +import java.util.LinkedHashSet; +import java.util.Set; public class JavaParameters extends SimpleJavaParameters { private static final Logger LOG = Logger.getInstance(JavaParameters.class); @@ -53,7 +57,7 @@ public class JavaParameters extends SimpleJavaParameters { public static final int JDK_ONLY = 0x1; public static final int CLASSES_ONLY = 0x2; - private static final int TESTS_ONLY = 0x4; + public static final int TESTS_ONLY = 0x4; public static final int JDK_AND_CLASSES = JDK_ONLY | CLASSES_ONLY; public static final int JDK_AND_CLASSES_AND_TESTS = JDK_ONLY | CLASSES_ONLY | TESTS_ONLY; public static final int CLASSES_AND_TESTS = CLASSES_ONLY | TESTS_ONLY; @@ -112,11 +116,19 @@ public class JavaParameters extends SimpleJavaParameters { public void configureByModule(final Module module, @MagicConstant(valuesFromClass = JavaParameters.class) final int classPathType) throws CantRunException { - configureByModule(module, classPathType, getModuleJdk(module)); + configureByModule(module, classPathType, getValidJdkToRunModule(module, (classPathType & TESTS_ONLY) == 0)); } + /** + * @deprecated use {@link #getValidJdkToRunModule(Module, boolean)} instead + */ public static Sdk getModuleJdk(final Module module) throws CantRunException { - final Sdk jdk = ModuleRootManager.getInstance(module).getSdk(); + return getValidJdkToRunModule(module, false); + } + + @NotNull + public static Sdk getValidJdkToRunModule(final Module module, boolean productionOnly) throws CantRunException { + Sdk jdk = getJdkToRunModule(module, productionOnly); if (jdk == null) { throw CantRunException.noJdkForModule(module); } @@ -127,6 +139,42 @@ public class JavaParameters extends SimpleJavaParameters { return jdk; } + @Nullable + public static Sdk getJdkToRunModule(Module module, boolean productionOnly) { + final Sdk moduleSdk = ModuleRootManager.getInstance(module).getSdk(); + if (moduleSdk == null) { + return null; + } + + final Set sdksFromDependencies = new LinkedHashSet(); + OrderEnumerator enumerator = OrderEnumerator.orderEntries(module).runtimeOnly().recursively(); + if (productionOnly) { + enumerator = enumerator.productionOnly(); + } + enumerator.forEachModule(new Processor() { + @Override + public boolean process(Module module) { + Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + if (sdk != null && sdk.getSdkType().equals(moduleSdk.getSdkType())) { + sdksFromDependencies.add(sdk); + } + return true; + } + }); + return findLatestVersion(moduleSdk, sdksFromDependencies); + } + + @NotNull + private static Sdk findLatestVersion(@NotNull Sdk mainSdk, @NotNull Set sdks) { + Sdk result = mainSdk; + for (Sdk sdk : sdks) { + if (VersionComparatorUtil.compare(result.getVersionString(), sdk.getVersionString()) < 0) { + result = sdk; + } + } + return result; + } + public void configureByProject(final Project project, @MagicConstant(valuesFromClass = JavaParameters.class) final int classPathType, final Sdk jdk) throws CantRunException { if ((classPathType & JDK_ONLY) != 0) { if (jdk == null) { diff --git a/java/java-tests/testSrc/com/intellij/execution/configurations/JavaParametersTest.java b/java/java-tests/testSrc/com/intellij/execution/configurations/JavaParametersTest.java index 179de1c82600..fe1bdb0cf304 100644 --- a/java/java-tests/testSrc/com/intellij/execution/configurations/JavaParametersTest.java +++ b/java/java-tests/testSrc/com/intellij/execution/configurations/JavaParametersTest.java @@ -22,6 +22,7 @@ import com.intellij.openapi.roots.DependencyScope; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.roots.ModuleRootManagerTestCase; +import org.intellij.lang.annotations.MagicConstant; /** * @author nik @@ -96,13 +97,22 @@ public class JavaParametersTest extends ModuleRootManagerTestCase { getJDomJar()); } - private static void assertClasspath(final Module module, final int type, VirtualFile... roots) throws CantRunException { + public void testUseNewestJreVersion() throws CantRunException { + Module dep = createModule("dep"); + ModuleRootModificationUtil.addDependency(myModule, dep, DependencyScope.TEST, true); + ModuleRootModificationUtil.setModuleSdk(myModule, getMockJdk17WithRtJarOnly()); + ModuleRootModificationUtil.setModuleSdk(dep, getMockJdk18WithRtJarOnly()); + assertClasspath(myModule, JavaParameters.JDK_AND_CLASSES, getRtJarJdk17()); + assertClasspath(myModule, JavaParameters.JDK_AND_CLASSES_AND_TESTS, getRtJarJdk18()); + } + + private static void assertClasspath(final Module module, @MagicConstant(flagsFromClass = JavaParameters.class) int type, VirtualFile... roots) throws CantRunException { final JavaParameters javaParameters = new JavaParameters(); javaParameters.configureByModule(module, type); assertRoots(javaParameters.getClassPath(), roots); } - private void assertClasspath(final Project project, final int type, VirtualFile... roots) throws CantRunException { + private void assertClasspath(final Project project, @MagicConstant(flagsFromClass = JavaParameters.class) int type, VirtualFile... roots) throws CantRunException { final JavaParameters javaParameters = new JavaParameters(); javaParameters.configureByProject(project, type, getTestProjectJdk()); assertRoots(javaParameters.getClassPath(), roots); diff --git a/java/java-tests/testSrc/com/intellij/roots/ModuleRootManagerTestCase.java b/java/java-tests/testSrc/com/intellij/roots/ModuleRootManagerTestCase.java index a0c21b482f44..a9473a4393bf 100644 --- a/java/java-tests/testSrc/com/intellij/roots/ModuleRootManagerTestCase.java +++ b/java/java-tests/testSrc/com/intellij/roots/ModuleRootManagerTestCase.java @@ -33,15 +33,15 @@ public abstract class ModuleRootManagerTestCase extends ModuleTestCase { @NotNull protected static Sdk getMockJdk17WithRtJarOnly() { - return retainRtJarOnly(IdeaTestUtil.getMockJdk17()); + return retainRtJarOnlyAndSetVersion(IdeaTestUtil.getMockJdk17()); } protected Sdk getMockJdk18WithRtJarOnly() { - return retainRtJarOnly(IdeaTestUtil.getMockJdk18()); + return retainRtJarOnlyAndSetVersion(IdeaTestUtil.getMockJdk18()); } @NotNull - private static Sdk retainRtJarOnly(Sdk jdk) { + private static Sdk retainRtJarOnlyAndSetVersion(Sdk jdk) { final SdkModificator modificator = jdk.getSdkModificator(); VirtualFile rtJar = null; for (VirtualFile root : modificator.getRoots(OrderRootType.CLASSES)) { @@ -51,6 +51,7 @@ public abstract class ModuleRootManagerTestCase extends ModuleTestCase { } } assertNotNull("rt.jar not found in jdk: " + jdk, rtJar); + modificator.setVersionString(IdeaTestUtil.getMockJdkVersion(jdk.getHomePath())); modificator.removeAllRoots(); modificator.addRoot(rtJar, OrderRootType.CLASSES); modificator.commitChanges();