1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-14 14:24:10 +02:00

Merge pull request #1886 from daafu/output_filters

Add output window filtering options similar to what Visual Studio offers
This commit is contained in:
Brian Fiete 2023-09-05 07:13:04 -07:00 committed by GitHub
commit 18e0576d79
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 221 additions and 15 deletions

View file

@ -104,6 +104,19 @@ namespace IDE.Debugger
AllowStringView = 0x800 AllowStringView = 0x800
} }
//[Flags]
public enum OutputFilterFlags
{
None = 0x0,
ModuleLoadMessages = 0x1,
ModuleUnloadMessages = 0x2,
ProcessExitMessages = 0x4,
ThreadCreateMessages = 0x8,
ThreadExitMessages = 0x10,
SymbolLoadMessages = 0x20,
ProgramOutput = 0x30
}
[Reflect] [Reflect]
public enum SymSrvFlags public enum SymSrvFlags
{ {
@ -386,6 +399,12 @@ namespace IDE.Debugger
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern char8* Debugger_GetEmitSource(char8* fileName); static extern char8* Debugger_GetEmitSource(char8* fileName);
[CallingConvention(.Stdcall), CLink]
static extern void Debugger_SetOutputFilterFlags(int32 flags);
[CallingConvention(.Stdcall), CLink]
static extern int32 Debugger_GetOutputFilterFlags();
public String mRunningPath ~ delete _; public String mRunningPath ~ delete _;
public bool mIsRunning; public bool mIsRunning;
public bool mIsRunningCompiled; public bool mIsRunningCompiled;
@ -1285,5 +1304,15 @@ namespace IDE.Debugger
outString.Append(stackId); outString.Append(stackId);
return true; return true;
} }
public void SetOutputFilterFlags(OutputFilterFlags outputFilterFlags)
{
Debugger_SetOutputFilterFlags((int32)outputFilterFlags);
}
public OutputFilterFlags GetOutputFilterFlags()
{
return (OutputFilterFlags)Debugger_GetOutputFilterFlags();
}
} }
} }

View file

@ -2011,6 +2011,23 @@ namespace IDE
} }
sd.RemoveIfEmpty(); sd.RemoveIfEmpty();
} }
using (sd.CreateObject("OutputFilters"))
{
IDE.Debugger.DebugManager.OutputFilterFlags outputFilterFlags = 0;
if (gApp.mDebugger != null)
{
outputFilterFlags = gApp.mDebugger.GetOutputFilterFlags();
}
sd.Add("ModuleLoadMessages", outputFilterFlags.HasFlag(.ModuleLoadMessages));
sd.Add("ModuleUnloadMessages", outputFilterFlags.HasFlag(.ModuleUnloadMessages));
sd.Add("ProcessExitMessages", outputFilterFlags.HasFlag(.ProcessExitMessages));
sd.Add("ThreadCreateMessages", outputFilterFlags.HasFlag(.ThreadCreateMessages));
sd.Add("ThreadExitMessages", outputFilterFlags.HasFlag(.ThreadExitMessages));
sd.Add("SymbolLoadMessages", outputFilterFlags.HasFlag(.SymbolLoadMessages));
sd.Add("ProgramOutput", outputFilterFlags.HasFlag(.ProgramOutput));
}
} }
bool SaveWorkspaceUserData(bool showErrors = true) bool SaveWorkspaceUserData(bool showErrors = true)
@ -3466,6 +3483,24 @@ namespace IDE
mDebugger.CreateStepFilter(filter, false, .NotFiltered); mDebugger.CreateStepFilter(filter, false, .NotFiltered);
} }
using (data.Open("OutputFilters"))
{
IDE.Debugger.DebugManager.OutputFilterFlags outputFilterFlags = 0;
outputFilterFlags |= data.GetBool("ModuleLoadMessages", false) ? .ModuleLoadMessages : 0;
outputFilterFlags |= data.GetBool("ModuleUnloadMessages", false) ? .ModuleUnloadMessages : 0;
outputFilterFlags |= data.GetBool("ProcessExitMessages", false) ? .ProcessExitMessages : 0;
outputFilterFlags |= data.GetBool("ThreadCreateMessages", false) ? .ThreadCreateMessages : 0;
outputFilterFlags |= data.GetBool("ThreadExitMessages", false) ? .ThreadExitMessages : 0;
outputFilterFlags |= data.GetBool("SymbolLoadMessages", false) ? .SymbolLoadMessages : 0;
outputFilterFlags |= data.GetBool("ProgramOutput", false) ? .ProgramOutput : 0;
if (gApp.mDebugger != null)
{
gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags);
}
}
return true; return true;
} }

View file

@ -244,15 +244,100 @@ namespace IDE.ui
Menu menu = new Menu(); Menu menu = new Menu();
var menuItem = menu.AddItem("Clear All"); var menuItemClearAll = menu.AddItem("Clear All");
var panel = mParent.mParent.mParent as TextPanel; var panel = mParent.mParent.mParent as TextPanel;
menuItem.mOnMenuItemSelected.Add(new (evt) => menuItemClearAll.mOnMenuItemSelected.Add(new (evt) =>
{ {
if (panel != null) if (panel != null)
panel.Clear(); panel.Clear();
else else
ClearText(); ClearText();
}); });
// Separator
menu.AddItem();
IDE.Debugger.DebugManager.OutputFilterFlags outputFilterFlags = gApp.mDebugger.GetOutputFilterFlags();
var menuItemModuleLoadMessages = menu.AddItem("Module Load Messages");
if (!outputFilterFlags.HasFlag(.ModuleLoadMessages))
{
menuItemModuleLoadMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check);
}
menuItemModuleLoadMessages.mOnMenuItemSelected.Add(new (evt) =>
{
gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ModuleLoadMessages);
});
var menuItemModuleUnloadMessages = menu.AddItem("Module Unload Messages");
if (!outputFilterFlags.HasFlag(.ModuleUnloadMessages))
{
menuItemModuleUnloadMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check);
}
menuItemModuleUnloadMessages.mOnMenuItemSelected.Add(new (evt) =>
{
gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ModuleUnloadMessages);
});
var menuItemProcessExitMessages = menu.AddItem("Process Exit Messages");
if (!outputFilterFlags.HasFlag(.ProcessExitMessages))
{
menuItemProcessExitMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check);
}
menuItemProcessExitMessages.mOnMenuItemSelected.Add(new (evt) =>
{
gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ProcessExitMessages);
});
var menuItemThreadCreateMessages = menu.AddItem("Thread Creation Messages");
if (!outputFilterFlags.HasFlag(.ThreadCreateMessages))
{
menuItemThreadCreateMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check);
}
menuItemThreadCreateMessages.mOnMenuItemSelected.Add(new (evt) =>
{
gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ThreadCreateMessages);
});
var menuItemThreadExitMessages = menu.AddItem("Thread Exit Messages");
if (!outputFilterFlags.HasFlag(.ThreadExitMessages))
{
menuItemThreadExitMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check);
}
menuItemThreadExitMessages.mOnMenuItemSelected.Add(new (evt) =>
{
gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ThreadExitMessages);
});
var menuItemSymbolLoadMessages = menu.AddItem("Symbol Load Messages");
if (!outputFilterFlags.HasFlag(.SymbolLoadMessages))
{
menuItemSymbolLoadMessages.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check);
}
menuItemSymbolLoadMessages.mOnMenuItemSelected.Add(new (evt) =>
{
gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .SymbolLoadMessages);
});
/* Not sure how to filter Program Output, it's handled in BeefSysLib not the IDE/Debugger. Perhaps we would
also need SetOutputFilterFlags() in BeefSysLib
var menuItemProgramOutput = menu.AddItem("Program Output");
if (!outputFilterFlags.HasFlag(.ProgramOutput))
{
menuItemProgramOutput.mIconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Check);
}
menuItemProgramOutput.mOnMenuItemSelected.Add(new (evt) =>
{
gApp.mDebugger.SetOutputFilterFlags(outputFilterFlags ^ .ProgramOutput);
});
*/
MenuWidget menuWidget = DarkTheme.sDarkTheme.CreateMenuWidget(menu); MenuWidget menuWidget = DarkTheme.sDarkTheme.CreateMenuWidget(menu);
menuWidget.Init(this, useX, useY); menuWidget.Init(this, useX, useY);

View file

@ -6020,7 +6020,7 @@ bool COFF::TryLoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge)
BP_ZONE("COFF::TryLoadPDB"); BP_ZONE("COFF::TryLoadPDB");
if (!isVerifyOnly) if (!isVerifyOnly && !(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_SymbolLoadMessages))
mDebugger->OutputMessage(StrFormat("Loading PDB %s\n", pdbPath.c_str())); mDebugger->OutputMessage(StrFormat("Loading PDB %s\n", pdbPath.c_str()));
DWORD highFileSize = 0; DWORD highFileSize = 0;

View file

@ -94,6 +94,8 @@ DebugManager::DebugManager()
mSymSrvOptions.mSymbolServers.Add("http://127.0.0.1/symbols"); mSymSrvOptions.mSymbolServers.Add("http://127.0.0.1/symbols");
SetSourceServerCacheDir(); SetSourceServerCacheDir();
mOutputFilterFlags = BfOutputFilterFlags_None;
} }
DebugManager::~DebugManager() DebugManager::~DebugManager()
@ -143,6 +145,16 @@ void DebugManager::SetSourceServerCacheDir()
#endif #endif
} }
void DebugManager::SetOutputFilterFlags(BfOutputFilterFlags outputFilterFlags)
{
mOutputFilterFlags = outputFilterFlags;
}
BfOutputFilterFlags DebugManager::GetOutputFilterFlags()
{
return mOutputFilterFlags;
}
//#define CAPTURE_ALLOC_BACKTRACE //#define CAPTURE_ALLOC_BACKTRACE
//#define CAPTURE_ALLOC_SOURCES //#define CAPTURE_ALLOC_SOURCES
@ -1661,6 +1673,24 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetEmitSource(char* inFilePath)
return outString.c_str(); return outString.c_str();
} }
BF_EXPORT void BF_CALLTYPE Debugger_SetOutputFilterFlags(int flags)
{
if (gDebugManager != NULL)
{
gDebugManager->SetOutputFilterFlags((BfOutputFilterFlags)flags);
}
}
BF_EXPORT int BF_CALLTYPE Debugger_GetOutputFilterFlags()
{
if (gDebugManager != NULL)
{
return (int)gDebugManager->GetOutputFilterFlags();
}
return 0;
}
BF_EXPORT NetResult* HTTP_GetFile(char* url, char* destPath) BF_EXPORT NetResult* HTTP_GetFile(char* url, char* destPath)
{ {
AutoCrit autoCrit(gDebugManager->mNetManager->mThreadPool.mCritSect); AutoCrit autoCrit(gDebugManager->mNetManager->mThreadPool.mCritSect);

View file

@ -35,6 +35,18 @@ enum BfStepFilterKind
BfStepFilterKind_NotFiltered = 2 BfStepFilterKind_NotFiltered = 2
}; };
enum BfOutputFilterFlags : uint16
{
BfOutputFilterFlags_None = 0x0,
BfOutputFilterFlags_ModuleLoadMessages = 0x1,
BfOutputFilterFlags_ModuleUnloadMessages = 0x2,
BfOutputFilterFlags_ProcessExitMessages = 0x4,
BfOutputFilterFlags_ThreadCreateMessages = 0x8,
BfOutputFilterFlags_ThreadExitMessages = 0x10,
BfOutputFilterFlags_SymbolLoadMessages = 0x20,
BfOutputFilterFlags_ProgramOutput = 0x40 // Can't trap these easily, they're in BeefSysLib
};
class StepFilter class StepFilter
{ {
public: public:
@ -81,6 +93,8 @@ public:
NetManager* mNetManager; NetManager* mNetManager;
DbgSymSrvOptions mSymSrvOptions; DbgSymSrvOptions mSymSrvOptions;
BfOutputFilterFlags mOutputFilterFlags;
public: public:
DebugManager(); DebugManager();
~DebugManager(); ~DebugManager();
@ -88,6 +102,9 @@ public:
void OutputMessage(const StringImpl& msg); void OutputMessage(const StringImpl& msg);
void OutputRawMessage(const StringImpl& msg); void OutputRawMessage(const StringImpl& msg);
void SetSourceServerCacheDir(); void SetSourceServerCacheDir();
void SetOutputFilterFlags(BfOutputFilterFlags outputFilterFlags);
BfOutputFilterFlags GetOutputFilterFlags();
}; };
extern DebugManager* gDebugManager; extern DebugManager* gDebugManager;

View file

@ -1708,7 +1708,9 @@ bool WinDebugger::DoUpdate()
mDebuggerWaitingThread = newThreadInfo; mDebuggerWaitingThread = newThreadInfo;
mThreadList.push_back(mDebuggerWaitingThread); mThreadList.push_back(mDebuggerWaitingThread);
UpdateThreadDebugRegisters(); UpdateThreadDebugRegisters();
OutputMessage(StrFormat("Creating thread from CREATE_PROCESS_DEBUG_EVENT %d\n", mDebugEvent.dwThreadId));
if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ThreadCreateMessages))
OutputMessage(StrFormat("Creating thread from CREATE_PROCESS_DEBUG_EVENT %d\n", mDebugEvent.dwThreadId));
threadInfo = mDebuggerWaitingThread; threadInfo = mDebuggerWaitingThread;
mProcessInfo.dwThreadId = threadInfo->mThreadId; mProcessInfo.dwThreadId = threadInfo->mThreadId;
@ -1776,10 +1778,14 @@ bool WinDebugger::DoUpdate()
else else
exitCodeStr = StrFormat("%d", exitCode); exitCodeStr = StrFormat("%d", exitCode);
if (!exitMessage.IsEmpty()) if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ProcessExitMessages))
OutputMessage(StrFormat("Process terminated. ExitCode: %s (%s).\n", exitCodeStr.c_str(), exitMessage.c_str())); {
else if (!exitMessage.IsEmpty())
OutputMessage(StrFormat("Process terminated. ExitCode: %s.\n", exitCodeStr.c_str())); OutputMessage(StrFormat("Process terminated. ExitCode: %s (%s).\n", exitCodeStr.c_str(), exitMessage.c_str()));
else
OutputMessage(StrFormat("Process terminated. ExitCode: %s.\n", exitCodeStr.c_str()));
}
mRunState = RunState_Terminated; mRunState = RunState_Terminated;
mDebugManager->mOutMessages.push_back("modulesChanged"); mDebugManager->mOutMessages.push_back("modulesChanged");
} }
@ -1858,7 +1864,8 @@ bool WinDebugger::DoUpdate()
stream.mFileHandle = 0; stream.mFileHandle = 0;
} }
OutputMessage(loadMsg + "\n"); if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ModuleLoadMessages))
OutputMessage(loadMsg + "\n");
if (altFileHandle != INVALID_HANDLE_VALUE) if (altFileHandle != INVALID_HANDLE_VALUE)
::CloseHandle(altFileHandle); ::CloseHandle(altFileHandle);
@ -1913,7 +1920,7 @@ bool WinDebugger::DoUpdate()
mDebugManager->mOutMessages.push_back("modulesChanged"); mDebugManager->mOutMessages.push_back("modulesChanged");
} }
if (!name.empty()) if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ModuleUnloadMessages) && !name.empty())
OutputMessage(StrFormat("Unloading DLL: %s @ %0s\n", name.c_str(), EncodeDataPtr((addr_target)(intptr)mDebugEvent.u.UnloadDll.lpBaseOfDll, true).c_str())); OutputMessage(StrFormat("Unloading DLL: %s @ %0s\n", name.c_str(), EncodeDataPtr((addr_target)(intptr)mDebugEvent.u.UnloadDll.lpBaseOfDll, true).c_str()));
BfLogDbg("UNLOAD_DLL_DEBUG_EVENT %s\n", name.c_str()); BfLogDbg("UNLOAD_DLL_DEBUG_EVENT %s\n", name.c_str());
@ -1959,12 +1966,15 @@ bool WinDebugger::DoUpdate()
mDebuggerWaitingThread = threadInfo; mDebuggerWaitingThread = threadInfo;
mThreadList.push_back(mDebuggerWaitingThread); mThreadList.push_back(mDebuggerWaitingThread);
UpdateThreadDebugRegisters(); UpdateThreadDebugRegisters();
OutputMessage(StrFormat("Creating thread %d\n", mDebugEvent.dwThreadId)); if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ThreadCreateMessages))
OutputMessage(StrFormat("Creating thread %d\n", mDebugEvent.dwThreadId));
} }
break; break;
case EXIT_THREAD_DEBUG_EVENT: case EXIT_THREAD_DEBUG_EVENT:
{ {
OutputMessage(StrFormat("Exiting thread %d\n", mDebugEvent.dwThreadId)); if (!(gDebugManager->GetOutputFilterFlags() & BfOutputFilterFlags_ThreadExitMessages))
OutputMessage(StrFormat("Exiting thread %d\n", mDebugEvent.dwThreadId));
if (mSteppingThread == threadInfo) if (mSteppingThread == threadInfo)
{ {
// We were attempting stepping on this thread, but not anymore! // We were attempting stepping on this thread, but not anymore!