shorten command line: suggest to edit configuration settings

when command line is too long and configuration allows to choose explicitly method to shorten the command line
This commit is contained in:
Anna.Kozlova
2017-10-04 20:41:55 +02:00
parent 6827fec286
commit c75f9abc16
9 changed files with 143 additions and 40 deletions

View File

@@ -37,17 +37,4 @@ public interface CommonJavaRunConfigurationParameters extends CommonProgramRunCo
@Nullable
String getPackage();
/**
* @return null if option was not selected explicitly, legacy user-local options to be used
*/
@Nullable
default ShortenClasspath getShortenClasspath() {
return null;
}
/**
* Called from UI, when user explicitly selects method to be used to shorten the command line or from the deserialization
*/
default void setShortenClasspath(ShortenClasspath mode) {}
}

View File

@@ -33,7 +33,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public abstract class JavaTestConfigurationBase extends ModuleBasedConfiguration<JavaRunConfigurationModule>
implements CommonJavaRunConfigurationParameters, RefactoringListenerProvider, SMRunnerConsolePropertiesProvider {
implements CommonJavaRunConfigurationParameters, ConfigurationWithClasspathShortener, RefactoringListenerProvider, SMRunnerConsolePropertiesProvider {
private ShortenClasspath myShortenClasspath = null;
public JavaTestConfigurationBase(String name,

View File

@@ -74,6 +74,7 @@ import java.util.Map;
public abstract class JavaTestFrameworkRunnableState<T extends
ModuleBasedConfiguration<JavaRunConfigurationModule>
& CommonJavaRunConfigurationParameters
& ConfigurationWithClasspathShortener
& SMRunnerConsolePropertiesProvider> extends JavaCommandLineState implements RemoteConnectionCreator {
private static final Logger LOG = Logger.getInstance(JavaTestFrameworkRunnableState.class);
protected ServerSocket myServerSocket;

View File

@@ -51,7 +51,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
public class ApplicationConfiguration extends ModuleBasedConfiguration<JavaRunConfigurationModule>
implements CommonJavaRunConfigurationParameters, SingleClassConfiguration, RefactoringListenerProvider {
implements CommonJavaRunConfigurationParameters, ConfigurationWithClasspathShortener, SingleClassConfiguration, RefactoringListenerProvider {
public String MAIN_CLASS_NAME;
public String VM_PARAMETERS;

View File

@@ -83,30 +83,45 @@ public class ExecutionUtil {
LOG.debug(e);
String description = e.getMessage();
HyperlinkListener listener = null;
if (isProcessNotCreated(e) && !PropertiesComponent.getInstance(project).isTrueValue("dynamic.classpath")) {
description = "Command line is too long. In order to reduce its length classpath file can be used.<br>" +
"Would you like to enable classpath file mode for all run configurations of your project?<br>" +
"<a href=\"\">Enable</a>";
listener = new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent event) {
PropertiesComponent.getInstance(project).setValue("dynamic.classpath", "true");
}
};
}
handleExecutionError(project, toolWindowId, taskName, e, description, listener);
}
public static boolean isProcessNotCreated(@NotNull Throwable e) {
if (e instanceof ProcessNotCreatedException) {
String description = e.getMessage();
return (description.contains("87") || description.contains("111") || description.contains("206")) &&
((ProcessNotCreatedException)e).getCommandLine().getCommandLineString().length() > 10/*24 * 32*/;
}
return false;
}
public static void handleExecutionError(@NotNull Project project,
@NotNull String toolWindowId,
@NotNull String taskName,
@NotNull Throwable e,
@Nullable String description,
@Nullable HyperlinkListener listener) {
final String title = ExecutionBundle.message("error.running.configuration.message", taskName);
if (StringUtil.isEmptyOrSpaces(description)) {
LOG.warn("Execution error without description", e);
description = "Unknown error";
}
HyperlinkListener listener = null;
if ((description.contains("87") || description.contains("111") || description.contains("206")) &&
e instanceof ProcessNotCreatedException &&
!PropertiesComponent.getInstance(project).isTrueValue("dynamic.classpath")) {
final String commandLineString = ((ProcessNotCreatedException)e).getCommandLine().getCommandLineString();
if (commandLineString.length() > 1024 * 32) {
description = "Command line is too long. In order to reduce its length classpath file can be used.<br>" +
"Would you like to enable classpath file mode for all run configurations of your project?<br>" +
"<a href=\"\">Enable</a>";
listener = new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent event) {
PropertiesComponent.getInstance(project).setValue("dynamic.classpath", "true");
}
};
}
}
final String title = ExecutionBundle.message("error.running.configuration.message", taskName);
final String fullMessage = title + ":<br>" + description;
if (ApplicationManager.getApplication().isUnitTestMode()) {

View File

@@ -0,0 +1,20 @@
// Copyright 2000-2017 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 com.intellij.execution;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nullable;
public interface ConfigurationWithClasspathShortener {
/**
* @return null if option was not selected explicitly, legacy user-local options to be used
*/
@Nullable
ShortenClasspath getShortenClasspath();
/**
* Called from UI, when user explicitly selects method to be used to shorten the command line or from the deserialization
*/
void setShortenClasspath(ShortenClasspath mode);
Project getProject();
}

View File

@@ -16,9 +16,11 @@
package com.intellij.execution;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.impl.RunDialog;
import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.execution.process.ProcessNotCreatedException;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ExecutionUtil;
@@ -27,6 +29,7 @@ import com.intellij.icons.AllIcons;
import com.intellij.internal.statistic.UsageTrigger;
import com.intellij.internal.statistic.beans.ConvertUsagesUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
@@ -37,6 +40,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
public class ProgramRunnerUtil {
private static final Logger LOG = Logger.getInstance(ProgramRunnerUtil.class);
@@ -95,11 +100,12 @@ public class ProgramRunnerUtil {
environment.assignNewExecutionId();
}
if (callback != null) {
/* if (callback != null) {
environment.getRunner().execute(environment, callback);
} else {
environment.getRunner().execute(environment);
}
}*/
throw new ProcessNotCreatedException("87", new GeneralCommandLine("zvewrgvewrvgbrtbnre"));
}
catch (ExecutionException e) {
String name = runnerAndConfigurationSettings != null ? runnerAndConfigurationSettings.getName() : null;
@@ -112,12 +118,52 @@ public class ProgramRunnerUtil {
if (name == null) {
name = "<Unknown>";
}
ExecutionUtil.handleExecutionError(project,
ExecutionManager.getInstance(project).getContentManager().getToolWindowIdByEnvironment(environment),
name, e);
String windowId = ExecutionManager.getInstance(project).getContentManager().getToolWindowIdByEnvironment(environment);
RunConfiguration configuration = runnerAndConfigurationSettings != null ? runnerAndConfigurationSettings.getConfiguration() : null;
if (configuration instanceof ConfigurationWithClasspathShortener && ExecutionUtil.isProcessNotCreated(e)) {
handelProcessNotStartedError(runnerAndConfigurationSettings, e, name, windowId);
}
else {
ExecutionUtil.handleExecutionError(project, windowId, name, e);
}
}
}
private static void handelProcessNotStartedError(RunnerAndConfigurationSettings runnerAndConfigurationSettings,
ExecutionException e,
String name,
String windowId) {
String description = e.getMessage();
HyperlinkListener listener = null;
ConfigurationWithClasspathShortener configuration = (ConfigurationWithClasspathShortener)runnerAndConfigurationSettings.getConfiguration();
Project project = configuration.getProject();
if (configuration.getShortenClasspath() == null) {
ConfigurationFactory factory = runnerAndConfigurationSettings.getFactory();
RunnerAndConfigurationSettings configurationTemplate = RunManager.getInstance(project)
.getConfigurationTemplate(factory);
description = "Command line is too long. Shorten command line for <a href=\"current\">" + name + "</a>";
if (((ConfigurationWithClasspathShortener)configurationTemplate.getConfiguration()).getShortenClasspath() == null) {
description += " or also for " + factory.getName() + " <a href=\"default\">default</a> configuration";
}
description += ".";
listener = event -> {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
boolean isDefaultConfigurationChosen = "default".equals(event.getDescription());
SingleConfigurableEditor dialog = RunDialog.editShortenClasspathSetting(isDefaultConfigurationChosen ? configurationTemplate : runnerAndConfigurationSettings,
"Edit" + (isDefaultConfigurationChosen ? " Default" : "") + " Configuration");
if (dialog.showAndGet() && isDefaultConfigurationChosen) {
((ConfigurationWithClasspathShortener)runnerAndConfigurationSettings.getConfiguration())
.setShortenClasspath(((ConfigurationWithClasspathShortener)configurationTemplate.getConfiguration()).getShortenClasspath());
}
}
};
}
ExecutionUtil.handleExecutionError(project, windowId, name, e, description, listener);
}
/**
* @deprecated Use {@link #executeConfiguration(RunnerAndConfigurationSettings, Executor)}
*/

View File

@@ -21,19 +21,25 @@ import com.intellij.execution.Executor;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.plaf.basic.ComboPopup;
import java.awt.event.ActionEvent;
import java.util.List;
public class RunDialog extends DialogWrapper implements RunDialogBase {
private final Project myProject;
@@ -127,6 +133,34 @@ public class RunDialog extends DialogWrapper implements RunDialogBase {
return dialog.showAndGet();
}
public static SingleConfigurableEditor editShortenClasspathSetting(final RunnerAndConfigurationSettings settings, final String title) {
SingleConfigurationConfigurable<RunConfiguration> configurable = SingleConfigurationConfigurable.editSettings(settings, null);
final SingleConfigurableEditor dialog = new SingleConfigurableEditor(settings.getConfiguration().getProject(), configurable, IdeModalityType.IDE) {
@Override
public JComponent getPreferredFocusedComponent() {
List<LabeledComponent> labeledComponents = UIUtil.findComponentsOfType(getContentPanel(), LabeledComponent.class);
String shortenLabelText = ExecutionBundle.message("application.configuration.shorten.command.line.label").replace("\u001B", "");
for (LabeledComponent component : labeledComponents) {
if (shortenLabelText.equals(component.getRawText())) {
JComponent cp = component.getComponent();
if (cp instanceof ComboBox) {
ApplicationManager.getApplication().invokeLater(() -> {
ComboPopup popup = ((ComboBox)cp).getPopup();
if (popup != null) {
popup.show();
}
});
return cp;
}
}
}
return super.getPreferredFocusedComponent();
}
};
dialog.setTitle(title);
return dialog;
}
private class ApplyAction extends AbstractAction {
public ApplyAction() {
super(ExecutionBundle.message("apply.action.name"));

View File

@@ -219,7 +219,7 @@ class.not.specified.error.message=Class not specified.
failed.to.generate.wrapper.error.message=Failed to generate temporary html wrapper for applet class
application.configuration.use.classpath.and.jdk.of.module.label=Use classpath of m&odule:
application.configuration.shorten.command.line.label=Shorten command line:
application.configuration.shorten.command.line.label=Shorten command &line:
application.configuration.main.class.label=Main &class:
jre.path.is.not.valid.jre.home.error.message=''{0}'' is not a valid JRE home
jre.path.is.jdk.error.message=Alternative JRE path needs to point to a JRE, not to a complete JDK installation