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(')'); 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) public void GetParamsDecl(String strBuffer)
{ {
int useParamIdx = 0; int useParamIdx = 0;

View file

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

View file

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

View file

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

View file

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

View file

@ -2977,11 +2977,15 @@ namespace IDE.ui
//insertText = insertText.Substring(0, insertText.Length - 1); //insertText = insertText.Substring(0, insertText.Length - 1);
String implText = null; String implText = null;
int tabIdx = insertText.IndexOf('\t'); 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 = scope:: String();
implText.Append(insertText, tabIdx); implText.Append(insertText, splitIdx);
insertText.RemoveToEnd(tabIdx); insertText.RemoveToEnd(splitIdx);
} }
String prevText = scope String(); String prevText = scope String();
mTargetEditWidget.Content.ExtractString(editSelection.mStartPos, editSelection.mEndPos - editSelection.mStartPos, prevText); mTargetEditWidget.Content.ExtractString(editSelection.mStartPos, editSelection.mEndPos - editSelection.mStartPos, prevText);

View file

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

View file

@ -347,7 +347,8 @@ namespace IDE.ui
AddPropertiesItem(root, "Symbol File Locations", "mSymbolSearchPath"); AddPropertiesItem(root, "Symbol File Locations", "mSymbolSearchPath");
AddPropertiesItem(root, "Auto Find Paths", "mAutoFindPaths"); AddPropertiesItem(root, "Auto Find Paths", "mAutoFindPaths");
AddPropertiesItem(root, "Profile Sample Rate", "mProfileSampleRate"); 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() protected override void ResetSettings()

View file

@ -54,6 +54,8 @@ namespace IDE.ui
public bool mIsNewExpression; public bool mIsNewExpression;
public bool mIsPending; public bool mIsPending;
public bool mUsedLock; public bool mUsedLock;
public bool? mAutoRefresh;
public int32 mDebuggerStateIdx;
public int32 mCurStackIdx; public int32 mCurStackIdx;
public int mMemoryBreakpointAddr; public int mMemoryBreakpointAddr;
public int32 mHadStepCount; public int32 mHadStepCount;
@ -66,6 +68,24 @@ namespace IDE.ui
public int32 mSeriesFirstVersion = -1; public int32 mSeriesFirstVersion = -1;
public int32 mSeriesVersion = -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 public bool IsConstant
{ {
get get
@ -1968,7 +1988,32 @@ namespace IDE.ui
{ {
mWatchRefreshButton = new WatchRefreshButton(); mWatchRefreshButton = new WatchRefreshButton();
mWatchRefreshButton.Resize(GS!(-16), 0, GS!(20), GS!(20)); 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); var typeSubItem = GetSubItem(columnIdx);
typeSubItem.AddWidget(mWatchRefreshButton); typeSubItem.AddWidget(mWatchRefreshButton);
mListView.mListSizeDirty = true; mListView.mListSizeDirty = true;
@ -2061,7 +2106,7 @@ namespace IDE.ui
return retVal; return retVal;
} }
void RefreshWatch() public void RefreshWatch()
{ {
var parentWatchListViewItem = mParentItem as WatchListViewItem; var parentWatchListViewItem = mParentItem as WatchListViewItem;
if (parentWatchListViewItem != null) if (parentWatchListViewItem != null)
@ -2997,7 +3042,12 @@ namespace IDE.ui
for (WatchListViewItem watchListViewItem in childItems) for (WatchListViewItem watchListViewItem in childItems)
{ {
var watchEntry = watchListViewItem.mWatchEntry; 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); IDEUtils.DeserializeListViewState(data, mListView);
for (let itemKey in data.Enumerate("Items")) for (let itemKey in data.Enumerate("Items"))
{
//for (int32 watchIdx = 0; watchIdx < data.Count; watchIdx++)
//for (var watchKV in data)
{ {
String watchEntry = scope String(); String watchEntry = scope String();
//data.GetString(watchIdx, watchEntry);
data.GetCurString(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) else if (watch.mEvalStr.Length > 0)
{ {
if (!gApp.mDebugger.IsPaused())
{
// Keep waiting
return;
}
String evalStr = scope String(1024); String evalStr = scope String(1024);
if (watch.mStackFrameId != null) if (watch.mStackFrameId != null)
{ {
@ -3637,6 +3702,7 @@ namespace IDE.ui
DebugManager.EvalExpressionFlags flags = .AllowStringView; DebugManager.EvalExpressionFlags flags = .AllowStringView;
if (watch.mIsNewExpression) if (watch.mIsNewExpression)
flags |= .AllowSideEffects | .AllowCalls; flags |= .AllowSideEffects | .AllowCalls;
gApp.DebugEvaluate(null, evalStr, val, -1, watch.mLanguage, flags); gApp.DebugEvaluate(null, evalStr, val, -1, watch.mLanguage, flags);
watch.mIsNewExpression = false; watch.mIsNewExpression = false;
} }
@ -3666,6 +3732,14 @@ namespace IDE.ui
if (((!valueSubItem.mFailed) && (watch.mHadValue)) || (hadSideEffects) || (hadPropertyEval)) if (((!valueSubItem.mFailed) && (watch.mHadValue)) || (hadSideEffects) || (hadPropertyEval))
{ {
watch.mHasValue = true; watch.mHasValue = true;
if ((hadSideEffects) && (watch.AutoRefresh))
{
if (watch.mDebuggerStateIdx != gApp.mDebugger.mStateIdx)
listViewItem.RefreshWatch();
return;
}
listViewItem.SetDisabled(true, hadSideEffects); listViewItem.SetDisabled(true, hadSideEffects);
return; return;
} }
@ -3730,6 +3804,7 @@ namespace IDE.ui
watch.mIsStackAlloc = false; watch.mIsStackAlloc = false;
watch.mUsedLock = false; watch.mUsedLock = false;
watch.mCurStackIdx = -1; watch.mCurStackIdx = -1;
watch.mDebuggerStateIdx = gApp.mDebugger.mStateIdx;
watch.mLanguage = .NotSet; watch.mLanguage = .NotSet;
DeleteAndNullify!(watch.mEditInitialize); DeleteAndNullify!(watch.mEditInitialize);
DeleteAndNullify!(watch.mAction); DeleteAndNullify!(watch.mAction);

View file

@ -2920,6 +2920,7 @@ bool WinDebugger::DoUpdate()
if (!handled) 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)); 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); ::ContinueDebugEvent(mDebuggerWaitingThread->mProcessId, mDebuggerWaitingThread->mThreadId, DBG_EXCEPTION_NOT_HANDLED);
mIsDebuggerWaiting = false; mIsDebuggerWaiting = false;