From 80eba2aaf962714a59a58e800a3534220b78efca Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 28 May 2014 17:39:09 +0400 Subject: [PATCH] IDEA-42954 Watches are not saved on restart of debug sessions --- .../xdebugger/impl/XDebugSessionImpl.java | 5 + .../xdebugger/impl/XDebuggerManagerImpl.java | 24 +++- .../impl/XDebuggerWatchesManager.java | 117 ++++++++++++++++++ .../impl/breakpoints/BreakpointState.java | 43 +------ .../impl/breakpoints/XExpressionState.java | 71 +++++++++++ .../impl/frame/XWatchesViewImpl.java | 12 +- .../xdebugger/impl/ui/XDebugSessionData.java | 6 +- .../xdebugger/impl/ui/XDebugSessionTab.java | 4 +- 8 files changed, 223 insertions(+), 59 deletions(-) create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 70c115b43acb..d416095cfe75 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -913,4 +913,9 @@ public class XDebugSessionImpl implements XDebugSession { } } } + + public void setWatchExpressions(@NotNull XExpression[] watchExpressions) { + mySessionData.setWatchExpressions(watchExpressions); + myDebuggerManager.getWatchesManager().setWatches(getSessionName(), watchExpressions); + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index 3afd27f7f60f..f8e52f815a26 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -68,6 +68,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager @NonNls public static final String COMPONENT_NAME = "XDebuggerManager"; private final Project myProject; private final XBreakpointManagerImpl myBreakpointManager; + private final XDebuggerWatchesManager myWatchesManager; private final Map mySessionData; private final Map mySessionTabs; private final Map mySessions; @@ -77,6 +78,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager public XDebuggerManagerImpl(final Project project, final StartupManager startupManager, MessageBus messageBus) { myProject = project; myBreakpointManager = new XBreakpointManagerImpl(project, this, startupManager); + myWatchesManager = new XDebuggerWatchesManager(); mySessionData = new THashMap(); mySessionTabs = new THashMap(); mySessions = new LinkedHashMap(); @@ -144,6 +146,10 @@ public class XDebuggerManagerImpl extends XDebuggerManager return myBreakpointManager; } + public XDebuggerWatchesManager getWatchesManager() { + return myWatchesManager; + } + public Project getProject() { return myProject; } @@ -199,7 +205,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager XDebugSessionData oldSessionData = contentToReuse != null ? mySessionData.get(contentToReuse) : null; if (oldSessionData == null) { - oldSessionData = new XDebugSessionData(); + oldSessionData = new XDebugSessionData(myWatchesManager.getWatches(session.getSessionName())); } // Perform custom configuration of session data for XDebugProcessConfiguratorStarter classes @@ -310,12 +316,13 @@ public class XDebuggerManagerImpl extends XDebuggerManager @Override public XDebuggerState getState() { - return new XDebuggerState(myBreakpointManager.getState()); + return new XDebuggerState(myBreakpointManager.getState(), myWatchesManager.getState()); } @Override public void loadState(final XDebuggerState state) { myBreakpointManager.loadState(state.myBreakpointManagerState); + myWatchesManager.loadState(state.myWatchesManagerState); } public void showExecutionPosition() { @@ -325,12 +332,14 @@ public class XDebuggerManagerImpl extends XDebuggerManager @SuppressWarnings("UnusedDeclaration") public static class XDebuggerState { private XBreakpointManagerImpl.BreakpointManagerState myBreakpointManagerState; + private XDebuggerWatchesManager.WatchesManagerState myWatchesManagerState; public XDebuggerState() { } - public XDebuggerState(final XBreakpointManagerImpl.BreakpointManagerState breakpointManagerState) { + public XDebuggerState(final XBreakpointManagerImpl.BreakpointManagerState breakpointManagerState, XDebuggerWatchesManager.WatchesManagerState watchesManagerState) { myBreakpointManagerState = breakpointManagerState; + myWatchesManagerState = watchesManagerState; } @Property(surroundWithTag = false) @@ -341,5 +350,14 @@ public class XDebuggerManagerImpl extends XDebuggerManager public void setBreakpointManagerState(final XBreakpointManagerImpl.BreakpointManagerState breakpointManagerState) { myBreakpointManagerState = breakpointManagerState; } + + @Property(surroundWithTag = false) + public XDebuggerWatchesManager.WatchesManagerState getWatchesManagerState() { + return myWatchesManagerState; + } + + public void setWatchesManagerState(XDebuggerWatchesManager.WatchesManagerState watchesManagerState) { + myWatchesManagerState = watchesManagerState; + } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java new file mode 100644 index 000000000000..d40559f07c58 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java @@ -0,0 +1,117 @@ +/* + * Copyright 2000-2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.xdebugger.impl; + +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.xmlb.annotations.AbstractCollection; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Property; +import com.intellij.util.xmlb.annotations.Tag; +import com.intellij.xdebugger.XExpression; +import com.intellij.xdebugger.impl.breakpoints.XExpressionState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author egor + */ +public class XDebuggerWatchesManager implements PersistentStateComponent { + private final Map watches = ContainerUtil.newConcurrentMap(); + + @NotNull + public XExpression[] getWatches(String confName) { + XExpression[] expressions = watches.get(confName); + if (expressions == null) { + return new XExpression[0]; + } + return expressions; + } + + public void setWatches(String configurationName, XExpression[] expressions) { + if (expressions != null && expressions.length > 0) { + watches.put(configurationName, expressions); + } + else { + watches.remove(configurationName); + } + } + + @Nullable + @Override + public WatchesManagerState getState() { + WatchesManagerState state = new WatchesManagerState(); + for (Map.Entry entry : watches.entrySet()) { + state.expressions.add(new ConfigurationState(entry.getKey(), entry.getValue())); + } + return state; + } + + @Override + public void loadState(WatchesManagerState state) { + watches.clear(); + if (state != null) { + for (ConfigurationState expressionState : state.expressions) { + WatchState[] states = expressionState.myExpressionStates; + XExpression[] expressions = new XExpression[states.length]; + for (int i = 0; i < states.length; i++) { + expressions[i] = states[i].toXExpression(); + } + watches.put(expressionState.myName, expressions); + } + } + } + + @Tag("watches-manager") + public static class WatchesManagerState { + @Property(surroundWithTag = false) + @AbstractCollection(surroundWithTag = false) + public List expressions = new ArrayList(); + } + + @Tag("configuration") + public static class ConfigurationState { + @Attribute("name") + public String myName; + + @Property(surroundWithTag = false) + @AbstractCollection(surroundWithTag = false) + public WatchState[] myExpressionStates; + + public ConfigurationState() { + } + + public ConfigurationState(String name, XExpression[] expressions) { + this.myName = name; + myExpressionStates = new WatchState[expressions.length]; + for (int i = 0; i < expressions.length; i++) { + myExpressionStates[i] = new WatchState(expressions[i]); + } + } + } + @Tag("watch") + public static class WatchState extends XExpressionState { + public WatchState() {} + + public WatchState(XExpression expression) { + super(expression); + } + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java index caec361c29bc..2a106fb4e3dc 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java @@ -15,7 +15,6 @@ */ package com.intellij.xdebugger.impl.breakpoints; -import com.intellij.lang.Language; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.xmlb.annotations.*; import com.intellij.xdebugger.XExpression; @@ -192,7 +191,7 @@ public class BreakpointState, P extends XBreakpointProp } private Condition(boolean disabled, XExpression expression) { - super(disabled, expression.getExpression(), expression.getLanguage() != null ? expression.getLanguage().getID() : null, expression.getCustomInfo()); + super(disabled, expression); } @Nullable @@ -210,7 +209,7 @@ public class BreakpointState, P extends XBreakpointProp } private LogExpression(boolean disabled, XExpression expression) { - super(disabled, expression.getExpression(), expression.getLanguage() != null ? expression.getLanguage().getID() : null, expression.getCustomInfo()); + super(disabled, expression); } @Nullable @@ -221,42 +220,4 @@ public class BreakpointState, P extends XBreakpointProp return new LogExpression(disabled, expression); } } - - private static class XExpressionState { - @Attribute("disabled") - public boolean myDisabled; - - @Attribute("expression") - public String myExpression; - - @Attribute("language") - public String myLanguage; - - @Attribute("custom") - public String myCustomInfo; - - @Text - public String myOldExpression; - - public XExpressionState() { - } - - public XExpressionState(boolean disabled, @NotNull String expression, String language, String customInfo) { - myDisabled = disabled; - myExpression = expression; - myLanguage = language; - myCustomInfo = customInfo; - } - - void checkConverted() { - if (myOldExpression != null) { - myExpression = myOldExpression; - myOldExpression = null; - } - } - - public XExpression toXExpression() { - return new XExpressionImpl(myExpression, Language.findLanguageByID(myLanguage), myCustomInfo); - } - } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java new file mode 100644 index 000000000000..8fc46ba6477a --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java @@ -0,0 +1,71 @@ +/* + * Copyright 2000-2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.xdebugger.impl.breakpoints; + +import com.intellij.lang.Language; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Text; +import com.intellij.xdebugger.XExpression; +import org.jetbrains.annotations.NotNull; + +/** +* @author egor +*/ +public class XExpressionState { + @Attribute("disabled") + public boolean myDisabled; + + @Attribute("expression") + public String myExpression; + + @Attribute("language") + public String myLanguage; + + @Attribute("custom") + public String myCustomInfo; + + @Text + public String myOldExpression; + + public XExpressionState() { + } + + public XExpressionState(boolean disabled, @NotNull String expression, String language, String customInfo) { + myDisabled = disabled; + myExpression = expression; + myLanguage = language; + myCustomInfo = customInfo; + } + + public XExpressionState(boolean disabled, XExpression expression) { + this(disabled, expression.getExpression(), expression.getLanguage() != null ? expression.getLanguage().getID() : null, expression.getCustomInfo()); + } + + public XExpressionState(XExpression expression) { + this(false, expression); + } + + void checkConverted() { + if (myOldExpression != null) { + myExpression = myOldExpression; + myOldExpression = null; + } + } + + public XExpression toXExpression() { + return new XExpressionImpl(myExpression, Language.findLanguageByID(myLanguage), myCustomInfo); + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java index ddbb79419f5c..cd87fe91d9a3 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java @@ -30,14 +30,12 @@ import com.intellij.ui.border.CustomLineBorder; import com.intellij.util.Alarm; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; -import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.frame.XStackFrame; import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; -import com.intellij.xdebugger.impl.ui.XDebugSessionData; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer; @@ -65,14 +63,12 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi private XDebuggerTreeState myTreeState; private XDebuggerTreeRestorer myTreeRestorer; private final WatchesRootNode myRootNode; - @NotNull private final XDebugSession mySession; - private final XDebugSessionData mySessionData; + @NotNull private final XDebugSessionImpl mySession; private final JPanel myDecoratedPanel; private final CompositeDisposable myDisposables = new CompositeDisposable(); - public XWatchesViewImpl(@NotNull final XDebugSession session, final @NotNull XDebugSessionData sessionData) { + public XWatchesViewImpl(@NotNull final XDebugSessionImpl session) { mySession = session; - mySessionData = sessionData; myTreePanel = new XDebuggerTreePanel(session.getProject(), session.getDebugProcess().getEditorsProvider(), this, null, XDebuggerActions.WATCHES_TREE_POPUP_GROUP, ((XDebugSessionImpl)session).getValueMarkers()); @@ -86,7 +82,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree); DnDManager.getInstance().registerTarget(this, tree); - myRootNode = new WatchesRootNode(tree, session, this, sessionData.getWatchExpressions()); + myRootNode = new WatchesRootNode(tree, session, this, session.getSessionData().getWatchExpressions()); tree.setRoot(myRootNode, false); final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTreePanel.getTree()).disableUpDownActions(); @@ -295,7 +291,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi watchExpressions.add(child.getExpression()); } } - mySessionData.setWatchExpressions(watchExpressions.toArray(new XExpression[watchExpressions.size()])); + mySession.setWatchExpressions(watchExpressions.toArray(new XExpression[watchExpressions.size()])); } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java index acc8cc506e25..08bf63aea430 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java @@ -16,7 +16,6 @@ package com.intellij.xdebugger.impl.ui; import com.intellij.openapi.actionSystem.DataKey; -import com.intellij.util.ArrayUtil; import com.intellij.xdebugger.XExpression; import org.jetbrains.annotations.NotNull; @@ -26,6 +25,7 @@ import org.jetbrains.annotations.NotNull; public class XDebugSessionData { public static final DataKey DATA_KEY = DataKey.create("XDebugSessionData"); + @NotNull private XExpression[] myWatchExpressions; private boolean myBreakpointsMuted = false; @@ -33,10 +33,6 @@ public class XDebugSessionData { myWatchExpressions = watchExpressions; } - public XDebugSessionData() { - this(new XExpression[0]); - } - public void setWatchExpressions(@NotNull XExpression[] watchExpressions) { myWatchExpressions = watchExpressions; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java index 7137f1bdf488..ef0b72008cf7 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java @@ -90,8 +90,8 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { return result; } - private Content createWatchesContent(final XDebugSession session, final XDebugSessionData sessionData) { - myWatchesView = new XWatchesViewImpl(session, sessionData); + private Content createWatchesContent(final XDebugSessionImpl session, final XDebugSessionData sessionData) { + myWatchesView = new XWatchesViewImpl(session); myViews.add(myWatchesView); Content watchesContent = myUi.createContent(DebuggerContentInfo.WATCHES_CONTENT, myWatchesView.getMainPanel(), XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null);