diff --git a/IDE/src/Debugger/DebugManager.bf b/IDE/src/Debugger/DebugManager.bf index 89838d30..e21d84e8 100644 --- a/IDE/src/Debugger/DebugManager.bf +++ b/IDE/src/Debugger/DebugManager.bf @@ -83,9 +83,10 @@ namespace IDE.Debugger DeselectCallStackIdx = 0x04, AllowSideEffects = 0x08, AllowCalls = 0x10, - MemoryAddress = 0x20, - MemoryWatch = 0x40, - Symbol = 0x80 + AllowProperties = 0x20, + MemoryAddress = 0x40, + MemoryWatch = 0x80, + Symbol = 0x100 } [Reflect] diff --git a/IDE/src/Settings.bf b/IDE/src/Settings.bf index bbe9cec6..7dc442d2 100644 --- a/IDE/src/Settings.bf +++ b/IDE/src/Settings.bf @@ -123,6 +123,7 @@ namespace IDE public List mSymbolSearchPath = new .() ~ DeleteContainerAndItems!(_); public List mAutoFindPaths = new .() ~ DeleteContainerAndItems!(_); public int32 mProfileSampleRate = 1000; + public bool mAutoEvaluateProperties = false; public void Serialize(StructuredData sd) { @@ -163,6 +164,7 @@ namespace IDE sd.RemoveIfEmpty(); } sd.Add("ProfileSampleRate", mProfileSampleRate); + sd.Add("AutoEvaluateProperties", mAutoEvaluateProperties); } public void Deserialize(StructuredData sd) @@ -201,6 +203,7 @@ namespace IDE } } sd.Get("ProfileSampleRate", ref mProfileSampleRate); + sd.Get("AutoEvaluateProperties", ref mAutoEvaluateProperties); } public void Apply() diff --git a/IDE/src/ui/HoverWatch.bf b/IDE/src/ui/HoverWatch.bf index e9fd1581..a2c63544 100644 --- a/IDE/src/ui/HoverWatch.bf +++ b/IDE/src/ui/HoverWatch.bf @@ -435,7 +435,22 @@ namespace IDE.ui public override void Update() { base.Update(); - + + for (let item in mListView.GetRoot().mChildItems) + { + let listViewItem = (HoverListViewItem)item; + if (listViewItem.mWatchEntry?.mIsPending == true) + { + if ((gApp.mDebugger.IsPaused(true)) && (!gApp.mDebugger.HasMessages())) + { + let listView = (HoverListView)listViewItem.mListView; + DoListViewItem(listView, listViewItem, listViewItem.mWatchEntry.mName, listViewItem.mWatchEntry.mEvalStr, true); + FinishListView(listView, listView.mX, listView.mY, true); + gApp.RefreshVisibleViews(); + } + } + } + if (mCloseDelay > 1) mCloseDelay--; if (mCloseCountdown > 0) @@ -591,6 +606,7 @@ namespace IDE.ui public void Refresh() { + mAllowSideEffects = true; if (mListView != null) RefreshListView(mListView); MarkDirty(); @@ -606,8 +622,15 @@ namespace IDE.ui DoListViewItem(hoverListView, (HoverListViewItem)listViewItem, name, evalStr, false); } + void RefreshWatch() + { + Refresh(); + } + HoverListViewItem DoListViewItem(HoverListView listView, HoverListViewItem listViewItem, String displayString, String evalString, bool isPending, WatchEntry parentWatchEntry = null) { + Debug.WriteLine("{} {}", evalString, isPending); + if ((displayString.StartsWith(":")) && (displayString.Contains('\n'))) { HoverListViewItem headListView = null; @@ -719,6 +742,8 @@ namespace IDE.ui flags |= DebugManager.EvalExpressionFlags.DeselectCallStackIdx; if (mAllowSideEffects) flags |= .AllowSideEffects | .AllowCalls; + if (gApp.mSettings.mDebuggerSettings.mAutoEvaluateProperties) + flags |= .AllowProperties; DebugManager.Language language = mLanguage; if (parentWatchEntry != null) @@ -731,11 +756,26 @@ namespace IDE.ui valueSubItem.Label = ""; return useListViewItem; } + watch.mIsPending = false; } var vals = scope List(val.Split('\n')); String.NewOrSet!(valueSubItem.mLabel, vals[0]); - if (valueSubItem.mLabel.StartsWith("!", StringComparison.Ordinal)) + if (vals[0] == "!sideeffects") + { + if (useListViewItem.mWatchRefreshButton == null) + { + useListViewItem.mWatchRefreshButton = new WatchRefreshButton(); + useListViewItem.mWatchRefreshButton.Resize(GS!(-22), 0, GS!(20), GS!(20)); + useListViewItem.mWatchRefreshButton.mOnMouseDown.Add(new (evt) => RefreshWatch()); + valueSubItem.AddWidget(useListViewItem.mWatchRefreshButton); + mListView.mListSizeDirty = true; + } + + valueSubItem.mFailed = false; + valueSubItem.Label = ""; + } + else if (valueSubItem.mLabel.StartsWith("!", StringComparison.Ordinal)) { var errorVals = scope List(scope String(valueSubItem.mLabel, 1).Split('\t')); if (errorVals.Count > 1) @@ -1052,10 +1092,11 @@ namespace IDE.ui //TODO: FontMetrics fontMetrics = .(); float nameHeight = font.Draw(null, listViewItem.mLabel, 0, 0, -1, 0, FontOverflowMode.Clip, &fontMetrics); - nameWidth = Math.Max(nameWidth, fontMetrics.mMaxWidth); - //listViewItem.mSelfHeight += nameHeight - font.GetLineSpacing(); - //listViewItem.mSelfHeight = nameHeight; - + float thisNameWidth = fontMetrics.mMaxWidth; + if (listViewItem.mWatchRefreshButton != null) + thisNameWidth += GS!(18); + nameWidth = Math.Max(nameWidth, thisNameWidth); + float addHeight = nameHeight - listView.mFont.GetLineSpacing(); childHeights += addHeight; listViewItem.mSelfHeight += addHeight; diff --git a/IDE/src/ui/SettingsDialog.bf b/IDE/src/ui/SettingsDialog.bf index 7fa3b938..fd1676dd 100644 --- a/IDE/src/ui/SettingsDialog.bf +++ b/IDE/src/ui/SettingsDialog.bf @@ -269,6 +269,7 @@ 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"); } protected override void ResetSettings() diff --git a/IDE/src/ui/WatchPanel.bf b/IDE/src/ui/WatchPanel.bf index 3ee2aee3..ed25ea40 100644 --- a/IDE/src/ui/WatchPanel.bf +++ b/IDE/src/ui/WatchPanel.bf @@ -1005,12 +1005,13 @@ namespace IDE.ui public void AddRefreshButton() { - if ((mWatchRefreshButton == null) && (mColumnIdx == 0) && (mSubItems.Count >= 3)) + int columnIdx = 2; + if ((mWatchRefreshButton == null) && (mColumnIdx == 0) && (columnIdx < mSubItems.Count)) { mWatchRefreshButton = new WatchRefreshButton(); - mWatchRefreshButton.Resize(-16, 0, 20, 20); + mWatchRefreshButton.Resize(GS!(-16), 0, GS!(20), GS!(20)); mWatchRefreshButton.mOnMouseDown.Add(new (evt) => RefreshWatch()); - var typeSubItem = GetSubItem(2); + var typeSubItem = GetSubItem(columnIdx); typeSubItem.AddWidget(mWatchRefreshButton); mListView.mListSizeDirty = true; } @@ -2236,11 +2237,12 @@ namespace IDE.ui var errStr = scope String(vals[0]); errStr.Remove(0); - bool hadSideEffects = vals[0] == "!sideeffects"; + bool hadSideEffects = vals[0] == "!sideeffects"; + bool hadPropertyEval = vals[0] == "!property"; if ((!wasNewExpression) && (isTopLevel)) { - if (((!valueSubItem.mFailed) && (watch.mHadValue)) || (hadSideEffects)) + if (((!valueSubItem.mFailed) && (watch.mHadValue)) || (hadSideEffects) || (hadPropertyEval)) { watch.mHasValue = true; listViewItem.SetDisabled(true, hadSideEffects); diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index f4f45f25..7a13dc43 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -745,9 +745,9 @@ DbgExprEvaluator::DbgExprEvaluator(WinDebugger* winDebugger, DbgModule* dbgModul mCursorPos = cursorPos; mAutoComplete = NULL; mIsEmptyTarget = (dbgModule == NULL) || (dbgModule->mDebugTarget->mIsEmpty); - mExpressionFlags = DwEvalExpressionFlag_None; + mExpressionFlags = DwEvalExpressionFlag_None; mHadSideEffects = false; - mBlockedSideEffects = false; + mBlockedSideEffects = false; mReferenceId = NULL; mIsComplexExpression = false; mHadMemberReference = false; @@ -4084,7 +4084,10 @@ DbgTypedValue DbgExprEvaluator::GetResult() // Fail("Indexer parameter count mismatch", mPropSrc); // } // } - + + SetAndRestoreValue prevFlags(mExpressionFlags); + if ((mExpressionFlags & DwEvalExpressionFlag_AllowPropertyEval) != 0) + mExpressionFlags = (DwEvalExpressionFlags)(mExpressionFlags | DwEvalExpressionFlag_AllowCalls); mResult = CreateCall(mPropSrc, mPropTarget, mPropGet, false, mIndexerExprValues, mIndexerValues); } } diff --git a/IDEHelper/DbgExprEvaluator.h b/IDEHelper/DbgExprEvaluator.h index 6b24188d..9b0a750d 100644 --- a/IDEHelper/DbgExprEvaluator.h +++ b/IDEHelper/DbgExprEvaluator.h @@ -300,7 +300,7 @@ public: bool mIsEmptyTarget; DwEvalExpressionFlags mExpressionFlags; bool mHadSideEffects; - bool mBlockedSideEffects; + bool mBlockedSideEffects; bool mIgnoreErrors; bool mCreatedPendingCall; bool mValidateOnly; diff --git a/IDEHelper/Debugger.h b/IDEHelper/Debugger.h index 694e74d3..f52c8d80 100644 --- a/IDEHelper/Debugger.h +++ b/IDEHelper/Debugger.h @@ -105,10 +105,11 @@ enum DwEvalExpressionFlags : int16 DwEvalExpressionFlag_DeselectCallStackIdx = 0x04, DwEvalExpressionFlag_AllowSideEffects = 0x08, DwEvalExpressionFlag_AllowCalls = 0x10, - DwEvalExpressionFlag_MemoryAddress = 0x20, - DwEvalExpressionFlag_MemoryWatch = 0x40, - DwEvalExpressionFlag_Symbol = 0x80, - DwEvalExpressionFlag_StepIntoCalls = 0x100, + DwEvalExpressionFlag_AllowPropertyEval = 0x20, + DwEvalExpressionFlag_MemoryAddress = 0x40, + DwEvalExpressionFlag_MemoryWatch = 0x80, + DwEvalExpressionFlag_Symbol = 0x100, + DwEvalExpressionFlag_StepIntoCalls = 0x200, }; struct DwDisplayInfo diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index a13990e3..f3deb2fd 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/IDEHelper/WinDebugger.cpp @@ -9017,7 +9017,7 @@ String WinDebugger::EvaluateContinue(DbgPendingExpr* pendingExpr, BfPassInstance { BfLogDbgExpr("Evaluate blocked side effects\n"); val = "!sideeffects"; - } + } else if (!exprResult) { if (exprResult.mType != NULL)