RunConfigurableTest - fix mem leak

GitOrigin-RevId: 9aae2413f469f198a3b6f674ec26c4e539cb5bfe
This commit is contained in:
Vladimir Krivosheev
2020-07-03 14:36:05 +02:00
committed by intellij-monorepo-bot
parent 097b020d21
commit 1ef5aedd24
8 changed files with 79 additions and 43 deletions

View File

@@ -21,7 +21,7 @@ import java.util.List;
import static com.intellij.execution.ui.CommandLinePanel.setMinimumWidth;
import static com.intellij.openapi.util.text.StringUtil.isNotEmpty;
public class JavaApplicationSettingsEditor extends RunConfigurationFragmentedEditor<ApplicationConfiguration> {
public final class JavaApplicationSettingsEditor extends RunConfigurationFragmentedEditor<ApplicationConfiguration> {
private final Project myProject;
public JavaApplicationSettingsEditor(ApplicationConfiguration configuration) {
@@ -32,7 +32,7 @@ public class JavaApplicationSettingsEditor extends RunConfigurationFragmentedEdi
@Override
protected List<SettingsEditorFragment<ApplicationConfiguration, ?>> createRunFragments() {
List<SettingsEditorFragment<ApplicationConfiguration, ?>> fragments = new ArrayList<>();
BeforeRunComponent beforeRunComponent = new BeforeRunComponent();
BeforeRunComponent beforeRunComponent = new BeforeRunComponent(this);
fragments.add(BeforeRunFragment.createBeforeRun(beforeRunComponent, CompileStepBeforeRun.ID));
fragments.addAll(BeforeRunFragment.createGroup());

View File

@@ -27,7 +27,8 @@ import kotlin.test.assertFalse
private val ORDER = arrayOf(CONFIGURATION_TYPE, //Application
FOLDER, //1
CONFIGURATION, CONFIGURATION, CONFIGURATION, CONFIGURATION, CONFIGURATION, TEMPORARY_CONFIGURATION, TEMPORARY_CONFIGURATION, FOLDER, //2
CONFIGURATION, CONFIGURATION, CONFIGURATION, CONFIGURATION, CONFIGURATION, TEMPORARY_CONFIGURATION,
TEMPORARY_CONFIGURATION, FOLDER, //2
TEMPORARY_CONFIGURATION, FOLDER, //3
CONFIGURATION, TEMPORARY_CONFIGURATION, CONFIGURATION_TYPE, //JUnit
FOLDER, //4
@@ -41,12 +42,6 @@ internal class RunConfigurableTest {
@JvmField
@ClassRule
val projectRule = ProjectRule(runPostStartUpActivities = false)
private class MockRunConfigurable(override val runManager: RunManagerImpl) : ProjectRunConfigurationConfigurable(projectRule.project) {
init {
createComponent()
}
}
}
@JvmField
@@ -61,8 +56,12 @@ internal class RunConfigurableTest {
val runManager = RunManagerImpl(projectRule.project)
runManager.initializeConfigurationTypes(listOf(ApplicationConfigurationType.getInstance(), JUnitConfigurationType.getInstance()))
runManager.loadState(JDOMUtil.load(RunConfigurableTest::class.java.getResourceAsStream("folders.xml")))
val result = MockRunConfigurable(runManager)
Disposer.register(projectRule.project, runManager)
val result = object : ProjectRunConfigurationConfigurable(projectRule.project) {
override val runManager = runManager
}
result.createComponent()
Disposer.register(disposableRule.disposable, runManager)
Disposer.register(runManager, result)
result
}
@@ -190,7 +189,9 @@ internal class RunConfigurableTest {
checkPositionToMove(17, 1, Trinity.create<Int, Int, RowsDnDSupport.RefinedDropSupport.Position>(17, 18, BELOW))
}
private fun checkPositionToMove(selectedRow: Int, direction: Int, expected: Trinity<Int, Int, RowsDnDSupport.RefinedDropSupport.Position>?) {
private fun checkPositionToMove(selectedRow: Int,
direction: Int,
expected: Trinity<Int, Int, RowsDnDSupport.RefinedDropSupport.Position>?) {
tree.setSelectionRow(selectedRow)
assertThat(configurable.getAvailableDropPosition(direction)).isEqualTo(expected)
}

View File

@@ -16,6 +16,7 @@ import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.InplaceButton;
@@ -36,7 +37,7 @@ import java.util.List;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable {
public final class BeforeRunComponent extends JPanel implements DnDTarget {
private List<TaskButton> myTags;
private final InplaceButton myAddButton;
private final JPanel myAddPanel;
@@ -45,7 +46,7 @@ public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable
private RunConfiguration myConfiguration;
private final LinkLabel<Object> myAddLabel;
public BeforeRunComponent() {
public BeforeRunComponent(@NotNull Disposable parentDisposable) {
super(new WrapLayout(FlowLayout.LEADING, 0, 0));
add(Box.createVerticalStrut(35));
JBEmptyBorder border = JBUI.Borders.empty(5, 0, 0, 5);
@@ -55,7 +56,16 @@ public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable
myAddPanel.add(myAddButton);
myAddLabel = new LinkLabel<>(ExecutionBundle.message("run.configuration.before.run.add.task"), null, (aSource, aLinkData) -> showPopup());
myAddLabel.setBorder(border);
DnDManager.getInstance().registerTarget(this, this);
DnDManager.getInstance().registerTarget(this, this, parentDisposable);
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
if (myTags != null) {
myTags.forEach(Disposer::dispose);
myTags = null;
}
}
});
}
private List<BeforeRunTaskProvider<BeforeRunTask<?>>> getProviders() {
@@ -66,12 +76,11 @@ public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable
private void createTags() {
myTags = new ArrayList<>();
for (BeforeRunTaskProvider<BeforeRunTask<?>> provider : getProviders()) {
TaskButton button = new TaskButton(provider, () -> {
myTags.add(new TaskButton(provider, () -> {
myChangeListener.run();
updateAddLabel();
myTagListener.accept(provider.getId(), false);
});
myTags.add(button);
}));
}
}
@@ -139,7 +148,7 @@ public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable
myTagListener.accept(tag.myProvider.getId(), true);
}
public void reset(RunnerAndConfigurationSettingsImpl s) {
public void reset(@NotNull RunnerAndConfigurationSettingsImpl s) {
myConfiguration = s.getConfiguration();
if (myTags == null) {
createTags();
@@ -210,11 +219,6 @@ public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable
return true;
}
@Override
public void dispose() {
DnDManager.getInstance().unregisterTarget(this, this);
}
public void setTagListener(BiConsumer<Key<? extends BeforeRunTask<?>>, Boolean> tagListener) {
myTagListener = tagListener;
}
@@ -223,8 +227,9 @@ public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable
private final BeforeRunTaskProvider<BeforeRunTask<?>> myProvider;
private BeforeRunTask<?> myTask;
private TaskButton(BeforeRunTaskProvider<BeforeRunTask<?>> provider, Runnable action) {
private TaskButton(@NotNull BeforeRunTaskProvider<BeforeRunTask<?>> provider, @NotNull Runnable action) {
super(provider.getName(), action);
myProvider = provider;
setVisible(false);
myButton.addMouseListener(new MouseAdapter() {
@@ -236,7 +241,7 @@ public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable
}
}
});
DnDManager.getInstance().registerSource(this, myButton);
DnDManager.getInstance().registerSource(this, myButton, this);
myButton.setToolTipText(ExecutionBundle.message("run.configuration.before.run.tooltip"));
}
@@ -248,12 +253,6 @@ public class BeforeRunComponent extends JPanel implements DnDTarget, Disposable
}
}
@Override
public void dispose() {
super.dispose();
DnDManager.getInstance().unregisterSource(this, myButton);
}
@Override
public boolean canStartDragging(DnDAction action, Point dragOrigin) {
return true;

View File

@@ -5,7 +5,6 @@ import com.intellij.execution.BeforeRunTask;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.JBUI;
@@ -23,7 +22,7 @@ public final class BeforeRunFragment<S extends RunConfigurationBase<?>> extends
private RunnerAndConfigurationSettingsImpl mySettings;
public static <S extends RunConfigurationBase<?>> List<SettingsEditorFragment<S, ?>> createGroup() {
ArrayList<SettingsEditorFragment<S, ?>> list = new ArrayList<>();
List<SettingsEditorFragment<S, ?>> list = new ArrayList<>();
list.add(RunConfigurationEditorFragment.createSettingsTag("before.launch.openToolWindow",
ExecutionBundle.message("run.configuration.before.run.open.tool.window"),
ExecutionBundle.message("run.configuration.before.run.group"),
@@ -37,18 +36,16 @@ public final class BeforeRunFragment<S extends RunConfigurationBase<?>> extends
return list;
}
public static <S extends RunConfigurationBase<?>> BeforeRunFragment<S> createBeforeRun(BeforeRunComponent component,
Key<?> key) {
public static <S extends RunConfigurationBase<?>> BeforeRunFragment<S> createBeforeRun(@NotNull BeforeRunComponent component, Key<?> key) {
return new BeforeRunFragment<>(component, key);
}
private BeforeRunFragment(BeforeRunComponent component, Key<?> key) {
private BeforeRunFragment(@NotNull BeforeRunComponent component, Key<?> key) {
super("beforeRunTasks", ExecutionBundle.message("run.configuration.before.run.task"),
ExecutionBundle.message("run.configuration.before.run.group"), wrap(component), -2);
myComponent = component;
myKey = key;
component.myChangeListener = () -> fireEditorStateChanged();
Disposer.register(this, component);
}
@Override

View File

@@ -25,12 +25,16 @@ public abstract class RunConfigurationEditorFragment<Settings, C extends JCompon
public abstract void applyEditorTo(@NotNull RunnerAndConfigurationSettingsImpl s);
public static <Settings> SettingsEditorFragment<Settings, ?> createSettingsTag(String id, String name, String group,
Predicate<RunnerAndConfigurationSettingsImpl> getter,
BiConsumer<RunnerAndConfigurationSettingsImpl, Boolean> setter,
@NotNull Predicate<RunnerAndConfigurationSettingsImpl> getter,
@NotNull BiConsumer<RunnerAndConfigurationSettingsImpl, Boolean> setter,
int menuPosition) {
Ref<SettingsEditorFragment<?, ?>> ref = new Ref<>();
TagButton button = new TagButton(name, () -> ref.get().setSelected(false));
RunConfigurationEditorFragment<Settings, ?> fragment = new RunConfigurationEditorFragment<Settings, JComponent>(id, name, group, button, 0) {
RunConfigurationEditorFragment<Settings, ?> fragment = new RunConfigurationEditorFragment<Settings, TagButton>(id, name, group, button, 0) {
@Override
protected void disposeEditor() {
Disposer.dispose(myComponent);
}
@Override
public void resetEditorFrom(@NotNull RunnerAndConfigurationSettingsImpl s) {
@@ -57,7 +61,6 @@ public abstract class RunConfigurationEditorFragment<Settings, C extends JCompon
return menuPosition;
}
};
Disposer.register(fragment, button);
ref.set(fragment);
return fragment;
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2020 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.ide.dnd;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -15,6 +16,8 @@ public abstract class DnDManager {
public abstract void registerSource(@NotNull DnDSource source, @NotNull JComponent component);
public abstract void registerSource(@NotNull DnDSource source, @NotNull JComponent component, @NotNull Disposable parentDisposable);
public abstract void registerSource(@NotNull AdvancedDnDSource source);
public abstract void unregisterSource(@NotNull DnDSource source, @NotNull JComponent component);
@@ -23,6 +26,8 @@ public abstract class DnDManager {
public abstract void registerTarget(DnDTarget target, JComponent component);
public abstract void registerTarget(@NotNull DnDTarget target, @NotNull JComponent component, @NotNull Disposable parentDisposable);
public abstract void unregisterTarget(DnDTarget target, JComponent component);
@Nullable

View File

@@ -2,8 +2,10 @@
package com.intellij.ide.dnd;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
@@ -71,6 +73,17 @@ public final class DnDManagerImpl extends DnDManager {
defaultDragSource.createDefaultDragGestureRecognizer(component, DnDConstants.ACTION_COPY_OR_MOVE, myDragGestureListener);
}
@Override
public void registerSource(@NotNull DnDSource source, @NotNull JComponent component, @NotNull Disposable parentDisposable) {
registerSource(source, component);
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
unregisterSource(source, component);
}
});
}
@Override
public void unregisterSource(@NotNull AdvancedDnDSource source) {
unregisterSource(source, source.getComponent());
@@ -125,6 +138,17 @@ public final class DnDManagerImpl extends DnDManager {
new DropTarget(component, DnDConstants.ACTION_COPY_OR_MOVE, myDropTargetListener);
}
@Override
public void registerTarget(@NotNull DnDTarget target, @NotNull JComponent component, @NotNull Disposable parentDisposable) {
registerTarget(target, component);
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
unregisterTarget(target, component);
}
});
}
@Override
public void unregisterTarget(DnDTarget target, JComponent component) {
component.putClientProperty(TARGET_KEY, null);

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2020 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.ide.dnd
import com.intellij.openapi.Disposable
import java.awt.Component
import javax.swing.JComponent
@@ -14,12 +15,18 @@ internal class HeadlessDnDManager : DnDManager() {
override fun registerTarget(target: DnDTarget?, component: JComponent?) {
}
override fun registerTarget(target: DnDTarget, component: JComponent, parentDisposable: Disposable) {
}
override fun unregisterTarget(target: DnDTarget?, component: JComponent?) {
}
override fun registerSource(source: DnDSource, component: JComponent) {
}
override fun registerSource(source: DnDSource, component: JComponent, parentDisposable: Disposable) {
}
override fun registerSource(source: AdvancedDnDSource) {
}