Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IDEA-239901 run on module path, similar to running via junit #772

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.cucumber.java.run.CucumberJavaApplicationConfigurable">
<grid id="27dc6" binding="myWholePanel" layout-manager="GridLayoutManager" row-count="8" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myWholePanel" layout-manager="GridLayoutManager" row-count="9" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
<xy x="20" y="20" width="500" height="404"/>
</constraints>
<properties/>
<border type="none"/>
Expand Down Expand Up @@ -41,7 +41,7 @@
</component>
<vspacer id="84c61">
<constraints>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="6ccd1" class="com.intellij.execution.ui.CommonJavaParametersPanel" binding="myCommonProgramParameters">
Expand All @@ -59,10 +59,21 @@
<labelLocation value="West"/>
<text resource-bundle="messages/ExecutionBundle" key="application.configuration.use.classpath.and.jdk.of.module.label"/>
</properties>
</component>
<component id="a287c" class="com.intellij.openapi.ui.LabeledComponent" binding="myUseModulePath">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<componentClass value="javax.swing.JCheckBox"/>
<enabled value="true"/>
<labelLocation value="West"/>
<text value=""/>
</properties>
</component>
<component id="cf19a" class="com.intellij.openapi.ui.LabeledComponent" binding="myShortenClasspathModeCombo">
<constraints>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<componentClass value="com.intellij.application.options.ModulesComboBox"/>
Expand All @@ -72,7 +83,7 @@
</component>
<component id="ca864" class="com.intellij.execution.ui.JrePathEditor" binding="myJrePathEditor">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package org.jetbrains.plugins.cucumber.java.run;

import com.intellij.application.options.ModuleDescriptionsComboBox;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.configurations.ConfigurationUtil;
import com.intellij.execution.ui.*;
import com.intellij.openapi.actionSystem.LangDataKeys;
Expand All @@ -16,6 +17,9 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaCodeFragment;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.EditorTextFieldWithBrowseButton;
Expand All @@ -36,6 +40,7 @@ public class CucumberJavaApplicationConfigurable extends SettingsEditor<Cucumber
private JPanel myWholePanel;
private LabeledComponent<EditorTextFieldWithBrowseButton> myMainClass;
private LabeledComponent<ModuleDescriptionsComboBox> myModule;
private LabeledComponent<JCheckBox> myUseModulePath;
private LabeledComponent<RawCommandLineEditor> myGlue;
private LabeledComponent<TextFieldWithBrowseButton> myFeatureOrFolder;
private CommonJavaParametersPanel myCommonProgramParameters;
Expand Down Expand Up @@ -64,8 +69,13 @@ public CucumberJavaApplicationConfigurable(Project project) {

myAnchor = UIUtil.mergeComponentsWithAnchor(myMainClass, myGlue, myFeatureOrFolder, myModule, myCommonProgramParameters);
myJrePathEditor.setAnchor(myModule.getLabel());
myUseModulePath.setAnchor(myModule.getLabel());
myShortenClasspathModeCombo.setAnchor(myModule.getLabel());
myShortenClasspathModeCombo.setComponent(new ShortenCommandLineModeCombo(myProject, myJrePathEditor, moduleComponent));

myUseModulePath.getComponent().setText(ExecutionBundle.message("use.module.path.checkbox.label"));
myUseModulePath.getComponent().setSelected(true);
myUseModulePath.setVisible(FilenameIndex.getFilesByName(project, PsiJavaModule.MODULE_INFO_FILE, GlobalSearchScope.projectScope(myProject)).length > 0);
}

public void setFeatureOrFolder(String path) {
Expand Down Expand Up @@ -110,6 +120,7 @@ protected void resetEditorFrom(@NotNull CucumberJavaRunConfiguration configurati
myFeatureOrFolder.getComponent().setText(configuration.getFilePath());
myJrePathEditor.setPathOrName(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled());
myShortenClasspathModeCombo.getComponent().setSelectedItem(configuration.getShortenCommandLine());
myUseModulePath.getComponent().setSelected(configuration.isUseModulePath());
}

@Override
Expand All @@ -124,6 +135,8 @@ protected void applyEditorTo(@NotNull CucumberJavaRunConfiguration configuration
configuration.setAlternativeJrePathEnabled(myJrePathEditor.isAlternativeJreSelected());
configuration.setShortenCommandLine(myShortenClasspathModeCombo.getComponent().getSelectedItem());
configuration.setModule(myModuleSelector.getModule());

configuration.setUseModulePath(myUseModulePath.isVisible() && myUseModulePath.getComponent().isSelected());
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.cucumber.java.run;

import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.diagnostic.logging.LogConfigurationPanel;
import com.intellij.execution.*;
import com.intellij.execution.application.ApplicationConfiguration;
Expand All @@ -18,15 +19,24 @@
import com.intellij.junit4.ExpectedPatterns;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.options.SettingsEditorGroup;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.PathUtil;
import com.intellij.util.PathsList;
import com.intellij.util.text.VersionComparatorUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
Expand All @@ -40,10 +50,11 @@
import java.util.*;
import java.util.function.Consumer;


public class CucumberJavaRunConfiguration extends ApplicationConfiguration {
private volatile CucumberGlueProvider myCucumberGlueProvider = null;
private final static Logger LOG = Logger.getInstance(CucumberJavaRunConfiguration.class);
private static final String JIGSAW_OPTIONS = "Jigsaw Options";
private boolean myUseModulePath = true;

protected CucumberJavaRunConfiguration(String name, Project project, ConfigurationFactory factory) {
super(name, project, factory);
Expand Down Expand Up @@ -80,6 +91,8 @@ protected JavaParameters createJavaParameters() throws ExecutionException {
params.getClassPath().add(path);
}

configureModulePath(params, module.getModule());

params.setMainClass(getMainClassName());
for (RunConfigurationExtension ext : RunConfigurationExtension.EP_NAME.getExtensionList()) {
ext.updateJavaParameters(CucumberJavaRunConfiguration.this, params, getRunnerSettings(), executor);
Expand Down Expand Up @@ -109,6 +122,121 @@ protected JavaParameters createJavaParameters() throws ExecutionException {
return params;
}

//code is copied from JavaTestFrameworkRunnableState

protected PsiJavaModule findJavaModule(Module module, boolean inTests) {
return DumbService.getInstance(module.getProject())
.computeWithAlternativeResolveEnabled(() -> JavaModuleGraphUtil.findDescriptorByModule(module, inTests));
}

private void configureModulePath(JavaParameters javaParameters, @NotNull Module module) {
if (!isUseModulePath()) return;
PsiJavaModule testModule = findJavaModule(module, true);
if (testModule != null) {
//adding the test module explicitly as it is unreachable from `idea.rt`
ParametersList vmParametersList = javaParameters
.getVMParametersList()
.addParamsGroup(JIGSAW_OPTIONS)
.getParametersList();

vmParametersList.add("--add-modules");
vmParametersList.add(testModule.getName());
//setup module path
PathsList classPath = javaParameters.getClassPath();
PathsList modulePath = javaParameters.getModulePath();
modulePath.addAll(classPath.getPathList());
classPath.clear();
}
else {
PsiJavaModule prodModule = findJavaModule(module, false);
if (prodModule != null) {
splitDepsBetweenModuleAndClasspath(javaParameters, module, prodModule);
}
}
}

private void splitDepsBetweenModuleAndClasspath(JavaParameters javaParameters, Module module, PsiJavaModule prodModule) {
CompilerModuleExtension compilerExt = CompilerModuleExtension.getInstance(module);
if (compilerExt == null) return;

PathsList modulePath = javaParameters.getModulePath();
PathsList classPath = javaParameters.getClassPath();

putDependenciesOnModulePath(modulePath, classPath, prodModule);

ParametersList vmParametersList = javaParameters.getVMParametersList()
.addParamsGroup(JIGSAW_OPTIONS)
.getParametersList();
String prodModuleName = prodModule.getName();

//ensure test output is merged to the production module
VirtualFile testOutput = compilerExt.getCompilerOutputPathForTests();
if (testOutput != null) {
// PATCH MODULE isn't really necessary, we don't want to 'open' our module
//vmParametersList.add("--patch-module");
//vmParametersList.add(prodModuleName + "=" + testOutput.getPath());
}

//ensure test dependencies missing from production module descriptor are available in tests
//todo enumerate all test dependencies explicitly
vmParametersList.add("--add-reads");
vmParametersList.add(prodModuleName + "=ALL-UNNAMED");

//open packages with tests to test runner
List<String> opensOptions = new ArrayList<>();
collectPackagesToOpen(opensOptions);
for (String option : opensOptions) {
if (option.isEmpty()) continue;
vmParametersList.add("--add-opens");
vmParametersList.add(prodModuleName + "/" + option + "=ALL-UNNAMED");
}

//ensure production module is explicitly added as test starter in `idea-rt` doesn't depend on it
vmParametersList.add("--add-modules");
vmParametersList.add(prodModuleName);
}

protected void putDependenciesOnModulePath(PathsList modulePath,
PathsList classPath,
PsiJavaModule prodModule) {
Set<PsiJavaModule> allRequires = JavaModuleGraphUtil.getAllDependencies(prodModule);
allRequires.add(prodModule); //put production output on the module path as well
JarFileSystem jarFS = JarFileSystem.getInstance();
ProjectFileIndex fileIndex = ProjectFileIndex.getInstance(prodModule.getProject());
allRequires.stream()
.filter(javaModule -> !PsiJavaModule.JAVA_BASE.equals(javaModule.getName()))
.map(javaModule -> getClasspathEntry(javaModule, fileIndex, jarFS))
.filter(Objects::nonNull)
.forEach(file -> putOnModulePath(modulePath, classPath, file));
}

protected void collectPackagesToOpen(List<String> options) {
//options.add(??? all glue packages ???); doesn't seem to be necessary, see remark patch-module above
}

private void putOnModulePath(PathsList modulePath, PathsList classPath, VirtualFile virtualFile) {
String path = PathUtil.getLocalPath(virtualFile.getPath());
if (classPath.getPathList().contains(path)) {
classPath.remove(path);
modulePath.add(path);
}
}

private VirtualFile getClasspathEntry(PsiJavaModule javaModule,
ProjectFileIndex fileIndex,
JarFileSystem jarFileSystem) {
VirtualFile moduleFile = PsiImplUtil.getModuleVirtualFile(javaModule);

Module moduleDependency = fileIndex.getModuleForFile(moduleFile);
if (moduleDependency == null) {
return jarFileSystem.getLocalVirtualFileFor(moduleFile);
}

CompilerModuleExtension moduleExtension = CompilerModuleExtension.getInstance(moduleDependency);
return moduleExtension != null ? moduleExtension.getCompilerOutputPath() : null;
}


@NotNull
private ConsoleView createConsole(@NotNull final Executor executor, ProcessHandler processHandler) throws ExecutionException {
@NonNls String testFrameworkName = "cucumber";
Expand Down Expand Up @@ -288,4 +416,12 @@ public void setSuggestedName(String suggestedName) {
public String getActionName() {
return getName();
}

public boolean isUseModulePath() {
return myUseModulePath;
}

public void setUseModulePath(boolean useModulePath) {
myUseModulePath = useModulePath;
}
}