fix mem leak in debugger settings

This commit is contained in:
Vladimir Krivosheev
2015-07-16 15:14:32 +02:00
parent 747f15faf1
commit 36385bf0a7
12 changed files with 108 additions and 91 deletions
@@ -28,7 +28,6 @@ import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder;
import com.intellij.debugger.engine.requests.RequestManagerImpl;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.debugger.requests.Requestor;
import com.intellij.debugger.ui.CompletionEditor;
import com.intellij.debugger.ui.breakpoints.Breakpoint;
import com.intellij.debugger.ui.tree.DebuggerTreeNode;
import com.intellij.execution.filters.ExceptionFilters;
@@ -461,8 +460,6 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
public abstract EvaluatorBuilder getEvaluatorBuilder();
public abstract CompletionEditor createEditor(Project project, PsiElement context, @NonNls String recentsId);
@NotNull
public static CodeFragmentFactory findAppropriateCodeFragmentFactory(final TextWithImports text, final PsiElement context) {
CodeFragmentFactory factory = ApplicationManager.getApplication().runReadAction(new Computable<CodeFragmentFactory>() {
@@ -20,11 +20,12 @@ import com.intellij.debugger.apiAdapters.TransportServiceWrapper;
import com.intellij.debugger.engine.DebugProcess;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.StackFrameContext;
import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder;
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl;
import com.intellij.debugger.ui.CompletionEditor;
import com.intellij.debugger.ui.DebuggerExpressionComboBox;
import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeExpression;
import com.intellij.debugger.ui.tree.DebuggerTreeNode;
import com.intellij.debugger.ui.tree.render.BatchEvaluator;
@@ -122,11 +123,6 @@ public class DebuggerUtilsImpl extends DebuggerUtilsEx{
return dialog.getSelected();
}
@Override
public CompletionEditor createEditor(Project project, PsiElement context, String recentsId) {
return new DebuggerExpressionComboBox(project, context, recentsId, DefaultCodeFragmentFactory.getInstance());
}
@Override
public String findAvailableDebugAddress(final boolean useSockets) throws ExecutionException {
final TransportServiceWrapper transportService = TransportServiceWrapper.getTransportService(useSockets);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.ui.DebuggerExpressionTextField;
import com.intellij.debugger.ui.JavaDebuggerSupport;
import com.intellij.debugger.ui.tree.render.*;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Document;
@@ -69,7 +70,7 @@ class CompoundRendererConfigurable extends JPanel {
private static final int NAME_TABLE_COLUMN = 0;
private static final int EXPRESSION_TABLE_COLUMN = 1;
public CompoundRendererConfigurable() {
public CompoundRendererConfigurable(@NotNull Disposable parentDisposable) {
super(new CardLayout());
if (myProject == null) {
@@ -90,10 +91,10 @@ class CompoundRendererConfigurable extends JPanel {
childrenButtonGroup.add(myRbExpressionChildrenRenderer);
childrenButtonGroup.add(myRbListChildrenRenderer);
myLabelEditor = new DebuggerExpressionTextField(myProject, null, "ClassLabelExpression");
myChildrenEditor = new DebuggerExpressionTextField(myProject, null, "ClassChildrenExpression");
myChildrenExpandedEditor = new DebuggerExpressionTextField(myProject, null, "ClassChildrenExpression");
JComponent myChildrenListEditor = createChildrenListEditor();
myLabelEditor = new DebuggerExpressionTextField(myProject, parentDisposable, null, "ClassLabelExpression");
myChildrenEditor = new DebuggerExpressionTextField(myProject, parentDisposable, null, "ClassChildrenExpression");
myChildrenExpandedEditor = new DebuggerExpressionTextField(myProject, parentDisposable, null, "ClassChildrenExpression");
JComponent myChildrenListEditor = createChildrenListEditor(parentDisposable);
final ItemListener updateListener = new ItemListener() {
@Override
@@ -226,10 +227,10 @@ class CompoundRendererConfigurable extends JPanel {
myTable.setEnabled(myRbListChildrenRenderer.isSelected());
}
private JComponent createChildrenListEditor() {
private JComponent createChildrenListEditor(@NotNull Disposable parentDisposable) {
final MyTableModel tableModel = new MyTableModel();
myTable = new JBTable(tableModel);
myListChildrenEditor = new DebuggerExpressionTextField(myProject, null, "NamedChildrenConfigurable");
myListChildrenEditor = new DebuggerExpressionTextField(myProject, parentDisposable, null, "NamedChildrenConfigurable");
final TableColumn exprColumn = myTable.getColumnModel().getColumn(EXPRESSION_TABLE_COLUMN);
exprColumn.setCellEditor(new AbstractTableCellEditor() {
@@ -19,7 +19,9 @@ import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.ui.tree.render.CompoundNodeRenderer;
import com.intellij.debugger.ui.tree.render.NodeRenderer;
import com.intellij.ide.util.ElementsChooser;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionToolbarPosition;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.options.ConfigurableUi;
import com.intellij.openapi.ui.Splitter;
import com.intellij.ui.AnActionButton;
@@ -38,12 +40,12 @@ import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public final class UserRenderersConfigurable extends JPanel implements ConfigurableUi<NodeRendererSettings> {
public final class UserRenderersConfigurable extends JPanel implements ConfigurableUi<NodeRendererSettings>, Disposable {
private final JPanel myNameFieldPanel;
private final JTextField myNameField;
private final ElementsChooser<NodeRenderer> myRendererChooser;
private NodeRenderer myCurrentRenderer = null;
private final CompoundRendererConfigurable myRendererDataConfigurable = new CompoundRendererConfigurable();
private final CompoundRendererConfigurable myRendererDataConfigurable = new CompoundRendererConfigurable(this);
public UserRenderersConfigurable() {
super(new BorderLayout(4, 0));
@@ -86,6 +88,10 @@ public final class UserRenderersConfigurable extends JPanel implements Configura
add(splitter, BorderLayout.CENTER);
}
@Override
public void dispose() {
}
@Override
@NotNull
public JComponent getComponent() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,8 +21,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public abstract class CompletionEditor extends JComponent{
public abstract void setText (TextWithImports text);
public abstract class CompletionEditor extends JComponent {
public abstract void setText(TextWithImports text);
public abstract TextWithImports getText();
@@ -30,7 +30,5 @@ public abstract class CompletionEditor extends JComponent{
public abstract PsiElement getContext();
public abstract void dispose();
public abstract String getRecentsId();
}
@@ -20,6 +20,7 @@ import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.impl.PositionUtil;
import com.intellij.ide.DataManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
@@ -70,41 +71,40 @@ public abstract class DebuggerEditorImpl extends CompletionEditor {
private final JLabel myChooseFactory = new JLabel();
private WeakReference<ListPopup> myPopup;
private final PsiTreeChangeListener myPsiListener = new PsiTreeChangeAdapter() {
@Override
public void childRemoved(@NotNull PsiTreeChangeEvent event) {
checkContext();
}
@Override
public void childReplaced(@NotNull PsiTreeChangeEvent event) {
checkContext();
}
@Override
public void childMoved(@NotNull PsiTreeChangeEvent event) {
checkContext();
}
private void checkContext() {
PsiElement contextElement = getContext();
if (contextElement == null || !contextElement.isValid()) {
DebuggerManagerEx manager = DebuggerManagerEx.getInstanceEx(myProject);
if (manager == null) {
LOG.error("Cannot obtain debugger manager for project " + myProject);
return;
}
PsiElement newContextElement = PositionUtil.getContextElement(manager.getContextManager().getContext());
setContext(newContextElement != null && newContextElement.isValid() ? newContextElement : null);
}
}
};
private CodeFragmentFactory myFactory;
protected boolean myInitialFactory;
public DebuggerEditorImpl(@NotNull Project project, PsiElement context, String recentsId, @NotNull CodeFragmentFactory factory) {
public DebuggerEditorImpl(@NotNull Project project, @NotNull CodeFragmentFactory factory, @NotNull Disposable parentDisposable, @Nullable PsiElement context, @Nullable String recentsId) {
myProject = project;
myContext = context;
myRecentsId = recentsId;
PsiManager.getInstance(project).addPsiTreeChangeListener(myPsiListener);
PsiManager.getInstance(project).addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
@Override
public void childRemoved(@NotNull PsiTreeChangeEvent event) {
checkContext();
}
@Override
public void childReplaced(@NotNull PsiTreeChangeEvent event) {
checkContext();
}
@Override
public void childMoved(@NotNull PsiTreeChangeEvent event) {
checkContext();
}
private void checkContext() {
PsiElement contextElement = getContext();
if (contextElement == null || !contextElement.isValid()) {
DebuggerManagerEx manager = DebuggerManagerEx.getInstanceEx(myProject);
if (manager == null) {
LOG.error("Cannot obtain debugger manager for project " + myProject);
return;
}
PsiElement newContextElement = PositionUtil.getContextElement(manager.getContextManager().getContext());
setContext(newContextElement != null && newContextElement.isValid() ? newContextElement : null);
}
}
}, parentDisposable);
setFactory(factory);
myInitialFactory = true;
@@ -287,12 +287,6 @@ public abstract class DebuggerEditorImpl extends CompletionEditor {
}
}
@Override
public void dispose() {
PsiManager.getInstance(myProject).removePsiTreeChangeListener(myPsiListener);
myCurrentDocument = null;
}
@NotNull
private static CodeFragmentFactory findAppropriateFactory(@NotNull TextWithImports text, @Nullable PsiElement context) {
for (CodeFragmentFactory factory : DebuggerUtilsEx.getCodeFragmentFactories(context)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package com.intellij.debugger.ui;
import com.intellij.debugger.engine.evaluation.*;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.event.DocumentAdapter;
@@ -32,7 +33,7 @@ import com.intellij.ui.EditorComboBoxRenderer;
import com.intellij.ui.EditorTextField;
import com.intellij.xdebugger.XExpression;
import com.intellij.xdebugger.impl.XDebuggerHistoryManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -96,12 +97,13 @@ public class DebuggerExpressionComboBox extends DebuggerEditorImpl {
}
};
public DebuggerExpressionComboBox(Project project, @NonNls String recentsId) {
this(project, null, recentsId, DefaultCodeFragmentFactory.getInstance());
public DebuggerExpressionComboBox(@NotNull Project project, @NotNull Disposable parentDisposable, @Nullable PsiElement context, @Nullable String recentsId) {
this(project, parentDisposable, context, recentsId, DefaultCodeFragmentFactory.getInstance());
}
public DebuggerExpressionComboBox(Project project, PsiElement context, @NonNls String recentsId, final CodeFragmentFactory factory) {
super(project, context, recentsId, factory);
public DebuggerExpressionComboBox(@NotNull Project project, @NotNull Disposable parentDisposable, @Nullable PsiElement context, @Nullable String recentsId, @NotNull CodeFragmentFactory factory) {
super(project, factory, parentDisposable, context, recentsId);
setLayout(new BorderLayout(0, 0));
myComboBox = new ComboBox(new MyComboboxModel(getRecents()), 100);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,15 +17,18 @@ package com.intellij.debugger.ui;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
import com.intellij.debugger.engine.evaluation.DefaultCodeFragmentFactory;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
import com.intellij.debugger.engine.evaluation.DefaultCodeFragmentFactory;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.ui.EditorTextField;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -37,8 +40,9 @@ public class DebuggerExpressionTextField extends DebuggerEditorImpl {
private static final @NonNls String EDITOR = "editor";
private static final @NonNls String STUB = "stub";
public DebuggerExpressionTextField(Project project, PsiElement context, final @NonNls String recentsId) {
super(project, context, recentsId, DefaultCodeFragmentFactory.getInstance());
public DebuggerExpressionTextField(@NotNull Project project, @NotNull Disposable parentDisposable, @Nullable PsiElement context, @Nullable String recentsId) {
super(project, DefaultCodeFragmentFactory.getInstance(), parentDisposable, context, recentsId);
myStubField.setEnabled(false);
myEditor = new EditorTextField("", project, StdFileTypes.JAVA);
setLayout(new BorderLayout());
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,20 +16,23 @@
package com.intellij.debugger.ui.tree.render.configurables;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.ui.CompletionEditor;
import com.intellij.debugger.ui.DebuggerExpressionComboBox;
import com.intellij.debugger.ui.tree.render.ExpressionChildrenRenderer;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
public class ClassChildrenExpressionConfigurable implements UnnamedConfigurable{
public class ClassChildrenExpressionConfigurable implements UnnamedConfigurable, Disposable {
private final ExpressionChildrenRenderer myRenderer;
private JPanel myPanel;
@@ -39,18 +42,18 @@ public class ClassChildrenExpressionConfigurable implements UnnamedConfigurable{
private final CompletionEditor myChildrenEditor;
private final CompletionEditor myExpandableEditor;
public ClassChildrenExpressionConfigurable(Project project, ExpressionChildrenRenderer renderer) {
public ClassChildrenExpressionConfigurable(@NotNull Project project, @NotNull ExpressionChildrenRenderer renderer) {
myRenderer = renderer;
PsiClass psiClass = DebuggerUtils.findClass(myRenderer.getClassName(), project, GlobalSearchScope.allScope(project));
myChildrenEditor = ((DebuggerUtilsEx)DebuggerUtils.getInstance()).createEditor(project, psiClass, "ClassChildrenExpression");
myExpandableEditor = ((DebuggerUtilsEx)DebuggerUtils.getInstance()).createEditor(project, psiClass, "ClassChildrenExpression");
myChildrenEditor = new DebuggerExpressionComboBox(project, this, psiClass, "ClassChildrenExpression");
myExpandableEditor = new DebuggerExpressionComboBox(project, this, psiClass, "ClassChildrenExpression");
myChildrenPanel.getComponent().setLayout(new BorderLayout());
myChildrenPanel.getComponent().add(myChildrenEditor);
myExpandablePanel.getComponent().setLayout(new BorderLayout());
myExpandablePanel.getComponent().add(myExpandableEditor);
myExpandablePanel.getComponent().add(myExpandableEditor);
}
public JComponent createComponent() {
@@ -72,8 +75,11 @@ public class ClassChildrenExpressionConfigurable implements UnnamedConfigurable{
myExpandableEditor.setText(myRenderer.getChildrenExpandable());
}
@Override
public void dispose() {
}
public void disposeUIResources() {
myChildrenEditor.dispose();
myExpandableEditor.dispose();
Disposer.dispose(this);
}
}
@@ -18,12 +18,14 @@ package com.intellij.debugger.ui.tree.render.configurables;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.ui.CompletionEditor;
import com.intellij.debugger.ui.DebuggerExpressionComboBox;
import com.intellij.debugger.ui.tree.render.EnumerationChildrenRenderer;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
@@ -31,6 +33,7 @@ import com.intellij.ui.TableUtil;
import com.intellij.util.ui.AbstractTableCellEditor;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.Table;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
@@ -41,7 +44,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
public class NamedChildrenConfigurable implements UnnamedConfigurable{
public class NamedChildrenConfigurable implements UnnamedConfigurable, Disposable {
private Table myTable;
private final EnumerationChildrenRenderer myRenderer;
private JPanel myPanel;
@@ -52,7 +55,7 @@ public class NamedChildrenConfigurable implements UnnamedConfigurable{
private JButton myButtonDown;
private CompletionEditor myCompletionEditor;
public NamedChildrenConfigurable(Project project, EnumerationChildrenRenderer renderer) {
public NamedChildrenConfigurable(@NotNull Project project, EnumerationChildrenRenderer renderer) {
myRenderer = renderer;
myTableLabel.setLabelFor(myTable);
@@ -62,7 +65,7 @@ public class NamedChildrenConfigurable implements UnnamedConfigurable{
getModel().addColumn(expressionColumnName, (Object[])null);
PsiClass psiClass = DebuggerUtils.findClass(myRenderer.getClassName(), project, GlobalSearchScope.allScope(project));
myCompletionEditor = ((DebuggerUtilsEx)DebuggerUtils.getInstance()).createEditor(project, psiClass, "NamedChildrenConfigurable");
myCompletionEditor = new DebuggerExpressionComboBox(project, this, psiClass, "NamedChildrenConfigurable");
myTable.setDragEnabled(false);
myTable.setIntercellSpacing(JBUI.emptySize());
@@ -155,12 +158,12 @@ public class NamedChildrenConfigurable implements UnnamedConfigurable{
}
public void disposeUIResources() {
if (myCompletionEditor != null) {
myCompletionEditor.dispose();
myCompletionEditor = null;
}
Disposer.dispose(this);
}
@Override
public void dispose() {
}
/*
private class TextWithImportsTableRenderer implements TableCellRenderer{
@@ -184,5 +187,4 @@ public class NamedChildrenConfigurable implements UnnamedConfigurable{
}
}
*/
}
@@ -15,6 +15,8 @@
*/
package com.intellij.openapi.options;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -93,6 +95,12 @@ public abstract class ConfigurableBase<UI extends ConfigurableUi<S>, S> implemen
@Override
public void disposeUIResources() {
ui = null;
UI ui = this.ui;
if (ui != null) {
this.ui = null;
if (ui instanceof Disposable) {
Disposer.dispose((Disposable)ui);
}
}
}
}
@@ -19,6 +19,9 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* Implement {@link com.intellij.openapi.Disposable} if you need explicit dispose logic.
*/
public interface ConfigurableUi<S> {
void reset(@NotNull S settings);