1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Improved debugger side effect handling, auto refresh options

This commit is contained in:
Brian Fiete 2024-12-31 13:17:53 -08:00
parent 7548bf23cd
commit 1484a5f53c
10 changed files with 150 additions and 30 deletions

View file

@ -1017,6 +1017,25 @@ namespace System.Reflection
strBuffer.Append(')');
}
public void GetMethodSig(String strBuffer)
{
strBuffer.Append('(');
int useParamIdx = 0;
for (int paramIdx < ParamCount)
{
var flag = GetParamFlags(paramIdx);
if (flag.HasFlag(.Implicit))
continue;
if (useParamIdx > 0)
strBuffer.Append(", ");
if (flag.HasFlag(.Params))
strBuffer.Append("params ");
strBuffer.Append(GetParamType(paramIdx));
useParamIdx++;
}
strBuffer.Append(')');
}
public void GetParamsDecl(String strBuffer)
{
int useParamIdx = 0;

View file

@ -432,7 +432,8 @@ namespace IDE.Debugger
public int32 mActiveCallStackIdx;
public Event<Action> mBreakpointsChangedDelegate ~ _.Dispose();
public Breakpoint mRunToCursorBreakpoint;
public int32 mDebugIdx;
public int32 mSessionIdx;
public int32 mStateIdx;
public bool IsRunning
{
@ -466,6 +467,17 @@ namespace IDE.Debugger
Debugger_Delete();
}
public void IncrementSessionIdx()
{
mSessionIdx++;
mStateIdx++;
}
public void IncrementStateIdx()
{
mStateIdx++;
}
public void Reset()
{
for (var breakpoint in mBreakpointList)

View file

@ -4864,7 +4864,7 @@ namespace IDE
{
if (mDebugger.mIsRunning)
{
if (mExecutionPaused)
if ((mExecutionPaused) && (mDebugger.IsPaused()))
{
DebuggerUnpaused();
mDebugger.StepInto(IsInDisassemblyMode());
@ -4882,7 +4882,7 @@ namespace IDE
mStepCount++;
if (mDebugger.mIsRunning)
{
if (mExecutionPaused)
if ((mExecutionPaused) && (mDebugger.IsPaused()))
{
DebuggerUnpaused();
mDebugger.StepOver(IsInDisassemblyMode());
@ -4902,7 +4902,7 @@ namespace IDE
[IDECommand]
void StepOut()
{
if (mExecutionPaused)
if ((mExecutionPaused) && (mDebugger.IsPaused()))
{
DebuggerUnpaused();
mDebugger.StepOut(IsInDisassemblyMode());
@ -12437,7 +12437,7 @@ namespace IDE
CheckDebugVisualizers();
mDebugger.mIsRunning = true;
mDebugger.mDebugIdx++;
mDebugger.IncrementSessionIdx();
WithSourceViewPanels(scope (sourceView) =>
{
sourceView.RehupAlias();
@ -12496,7 +12496,7 @@ namespace IDE
CheckDebugVisualizers();
mDebugger.mIsRunning = true;
mDebugger.mDebugIdx++;
mDebugger.IncrementSessionIdx();
mDebugger.RehupBreakpoints(true);
mDebugger.Run();
mIsAttachPendingSourceShow = true;
@ -12969,7 +12969,7 @@ namespace IDE
if (mDebugger.OpenMiniDump(mCrashDumpPath))
{
mDebugger.mIsRunning = true;
mDebugger.mDebugIdx++;
mDebugger.IncrementSessionIdx();
mExecutionPaused = false; // Make this false so we can detect a Pause immediately
mIsAttachPendingSourceShow = true;
}
@ -13281,6 +13281,7 @@ namespace IDE
void DebuggerPaused()
{
mDebugger.IncrementStateIdx();
mDebugger.mActiveCallStackIdx = 0;
mExecutionPaused = true;
mDebugger.GetRunState();
@ -13294,6 +13295,8 @@ namespace IDE
void WithWatchPanels(delegate void(WatchPanel watchPanel) dlg)
{
if (mWatchPanel == null)
return;
dlg(mWatchPanel);
dlg(mAutoWatchPanel);
for (let window in mWindows)

View file

@ -153,7 +153,8 @@ namespace IDE
public List<String> mSymbolSearchPath = new .() ~ DeleteContainerAndItems!(_);
public List<String> mAutoFindPaths = new .() ~ DeleteContainerAndItems!(_);
public int32 mProfileSampleRate = 1000;
public bool mAutoEvaluateProperties = false;
public bool mAutoEvaluatePropertiesOnHover = false;
public bool mAutoRefreshWatches = false;
public void Serialize(StructuredData sd)
{
@ -194,7 +195,8 @@ namespace IDE
sd.RemoveIfEmpty();
}
sd.Add("ProfileSampleRate", mProfileSampleRate);
sd.Add("AutoEvaluateProperties", mAutoEvaluateProperties);
sd.Add("AutoEvaluateProperties", mAutoEvaluatePropertiesOnHover);
sd.Add("AutoRefreshWatches", mAutoRefreshWatches);
}
public void Deserialize(StructuredData sd)
@ -233,7 +235,8 @@ namespace IDE
}
}
sd.Get("ProfileSampleRate", ref mProfileSampleRate);
sd.Get("AutoEvaluateProperties", ref mAutoEvaluateProperties);
sd.Get("AutoEvaluateProperties", ref mAutoEvaluatePropertiesOnHover);
sd.Get("AutoRefreshWatches", ref mAutoRefreshWatches);
}
public void Apply()
@ -264,6 +267,9 @@ namespace IDE
gApp.mDebugger.SetSourcePathRemap(remapStr);
mProfileSampleRate = Math.Clamp(mProfileSampleRate, 10, 10000);
gApp.mDebugger.IncrementStateIdx();
gApp.RefreshWatches();
}
public void SetDefaults()
@ -1349,7 +1355,6 @@ namespace IDE
mKeySettings.Apply();
mDebuggerSettings.Apply();
for (var window in gApp.mWindows)
{
if (var widgetWindow = window as WidgetWindow)

View file

@ -639,7 +639,7 @@ namespace IDE
gApp.mDebugger.RehupBreakpoints(true);
gApp.mDebugger.Run();
gApp.mDebugger.mIsRunning = true;
gApp.mDebugger.mDebugIdx++;
gApp.mDebugger.IncrementSessionIdx();
}
mTestInstance.mThread.Start(false);

View file

@ -2977,11 +2977,15 @@ namespace IDE.ui
//insertText = insertText.Substring(0, insertText.Length - 1);
String implText = null;
int tabIdx = insertText.IndexOf('\t');
if (tabIdx != -1)
int splitIdx = tabIdx;
int crIdx = insertText.IndexOf('\r');
if ((crIdx != -1) && (tabIdx != -1) && (crIdx < tabIdx))
splitIdx = crIdx;
if (splitIdx != -1)
{
implText = scope:: String();
implText.Append(insertText, tabIdx);
insertText.RemoveToEnd(tabIdx);
implText.Append(insertText, splitIdx);
insertText.RemoveToEnd(splitIdx);
}
String prevText = scope String();
mTargetEditWidget.Content.ExtractString(editSelection.mStartPos, editSelection.mEndPos - editSelection.mStartPos, prevText);

View file

@ -775,7 +775,7 @@ namespace IDE.ui
flags |= DebugManager.EvalExpressionFlags.DeselectCallStackIdx;
if (mAllowSideEffects)
flags |= .AllowSideEffects | .AllowCalls;
if (gApp.mSettings.mDebuggerSettings.mAutoEvaluateProperties)
if (gApp.mSettings.mDebuggerSettings.mAutoEvaluatePropertiesOnHover)
flags |= .AllowProperties;
if (watch.mResultType == .RawText)
flags |= .RawStr;

View file

@ -347,7 +347,8 @@ namespace IDE.ui
AddPropertiesItem(root, "Symbol File Locations", "mSymbolSearchPath");
AddPropertiesItem(root, "Auto Find Paths", "mAutoFindPaths");
AddPropertiesItem(root, "Profile Sample Rate", "mProfileSampleRate");
AddPropertiesItem(root, "Auto Evaluate Properties", "mAutoEvaluateProperties");
AddPropertiesItem(root, "Auto Eval Properties on Hover", "mAutoEvaluatePropertiesOnHover");
AddPropertiesItem(root, "Auto Refresh Side Effects", "mAutoRefreshWatches");
}
protected override void ResetSettings()

View file

@ -54,6 +54,8 @@ namespace IDE.ui
public bool mIsNewExpression;
public bool mIsPending;
public bool mUsedLock;
public bool? mAutoRefresh;
public int32 mDebuggerStateIdx;
public int32 mCurStackIdx;
public int mMemoryBreakpointAddr;
public int32 mHadStepCount;
@ -66,6 +68,24 @@ namespace IDE.ui
public int32 mSeriesFirstVersion = -1;
public int32 mSeriesVersion = -1;
public bool AutoRefresh
{
get
{
if (mAutoRefresh != null)
return mAutoRefresh.Value;
return gApp.mSettings.mDebuggerSettings.mAutoRefreshWatches;
}
set
{
if (value == gApp.mSettings.mDebuggerSettings.mAutoRefreshWatches)
mAutoRefresh = null;
else
mAutoRefresh = value;
}
}
public bool IsConstant
{
get
@ -1968,7 +1988,32 @@ namespace IDE.ui
{
mWatchRefreshButton = new WatchRefreshButton();
mWatchRefreshButton.Resize(GS!(-16), 0, GS!(20), GS!(20));
mWatchRefreshButton.mOnMouseDown.Add(new (evt) => RefreshWatch());
mWatchRefreshButton.mOnMouseDown.Add(new (evt) =>
{
if (evt.mBtn == 0)
RefreshWatch();
if (evt.mBtn == 1)
{
Menu menu = new Menu();
Menu anItem;
anItem = menu.AddItem("Refresh");
anItem.mOnMenuItemSelected.Add(new (item) => { RefreshWatch(); });
anItem = menu.AddItem("Auto Refresh");
if (mWatchEntry.AutoRefresh)
anItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
anItem.mOnMenuItemSelected.Add(new (item) =>
{
mWatchEntry.AutoRefresh = !mWatchEntry.AutoRefresh;
if (mWatchEntry.AutoRefresh)
RefreshWatch();
});
MenuWidget menuWidget = ThemeFactory.mDefault.CreateMenuWidget(menu);
menuWidget.Init(mWatchRefreshButton, evt.mX, mHeight + GS!(2));
}
});
var typeSubItem = GetSubItem(columnIdx);
typeSubItem.AddWidget(mWatchRefreshButton);
mListView.mListSizeDirty = true;
@ -2061,7 +2106,7 @@ namespace IDE.ui
return retVal;
}
void RefreshWatch()
public void RefreshWatch()
{
var parentWatchListViewItem = mParentItem as WatchListViewItem;
if (parentWatchListViewItem != null)
@ -2997,7 +3042,12 @@ namespace IDE.ui
for (WatchListViewItem watchListViewItem in childItems)
{
var watchEntry = watchListViewItem.mWatchEntry;
data.Add(watchEntry.mEvalStr);
using (data.CreateObject())
{
data.Add("EvalStr", watchEntry.mEvalStr);
if (watchEntry.mAutoRefresh != null)
data.Add("AutoRefresh", watchEntry.mAutoRefresh.Value);
}
}
}
}
@ -3016,14 +3066,23 @@ namespace IDE.ui
IDEUtils.DeserializeListViewState(data, mListView);
for (let itemKey in data.Enumerate("Items"))
{
//for (int32 watchIdx = 0; watchIdx < data.Count; watchIdx++)
//for (var watchKV in data)
{
String watchEntry = scope String();
//data.GetString(watchIdx, watchEntry);
data.GetCurString(watchEntry);
AddWatch(watchEntry);
WatchListViewItem watchItem;
if (!watchEntry.IsEmpty)
{
watchItem = AddWatch(watchEntry);
}
else
{
data.GetString("EvalStr", watchEntry);
watchItem = AddWatch(watchEntry);
if (data.Contains("AutoRefresh"))
{
watchItem.mWatchEntry.mAutoRefresh = data.GetBool("AutoRefresh");
}
}
}
@ -3622,6 +3681,12 @@ namespace IDE.ui
}
else if (watch.mEvalStr.Length > 0)
{
if (!gApp.mDebugger.IsPaused())
{
// Keep waiting
return;
}
String evalStr = scope String(1024);
if (watch.mStackFrameId != null)
{
@ -3637,6 +3702,7 @@ namespace IDE.ui
DebugManager.EvalExpressionFlags flags = .AllowStringView;
if (watch.mIsNewExpression)
flags |= .AllowSideEffects | .AllowCalls;
gApp.DebugEvaluate(null, evalStr, val, -1, watch.mLanguage, flags);
watch.mIsNewExpression = false;
}
@ -3666,6 +3732,14 @@ namespace IDE.ui
if (((!valueSubItem.mFailed) && (watch.mHadValue)) || (hadSideEffects) || (hadPropertyEval))
{
watch.mHasValue = true;
if ((hadSideEffects) && (watch.AutoRefresh))
{
if (watch.mDebuggerStateIdx != gApp.mDebugger.mStateIdx)
listViewItem.RefreshWatch();
return;
}
listViewItem.SetDisabled(true, hadSideEffects);
return;
}
@ -3730,6 +3804,7 @@ namespace IDE.ui
watch.mIsStackAlloc = false;
watch.mUsedLock = false;
watch.mCurStackIdx = -1;
watch.mDebuggerStateIdx = gApp.mDebugger.mStateIdx;
watch.mLanguage = .NotSet;
DeleteAndNullify!(watch.mEditInitialize);
DeleteAndNullify!(watch.mAction);

View file

@ -2920,6 +2920,7 @@ bool WinDebugger::DoUpdate()
if (!handled)
{
if (mRunState != RunState_DebugEval)
OutputMessage(StrFormat("Skipping first chance exception %08X at address %@ in thread %d\n", exceptionRecord->ExceptionCode, exceptionRecord->ExceptionAddress, threadInfo->mThreadId));
::ContinueDebugEvent(mDebuggerWaitingThread->mProcessId, mDebuggerWaitingThread->mThreadId, DBG_EXCEPTION_NOT_HANDLED);
mIsDebuggerWaiting = false;