Debugger: Cleanups.

Get rid of ExpressionEvaluationWindow.

- When asking to evaluate an expression via the Tools menu, we now
  bring up a prompt window the same as the one used to add a watch
  expression. This in turn works exactly the same as the latter,
  except an additional flag is sent indicating that the expression
  in question should not be persisted. As such, the results are
  shown in the variables view, with all the capabilities that allows,
  but also without the expression following the function as a watch
  expression would.
This commit is contained in:
Rene Gollent 2014-12-15 17:14:33 -05:00
parent 7b48414c40
commit 9dcef0489e
9 changed files with 79 additions and 360 deletions

View File

@ -275,7 +275,6 @@ Application Debugger :
BreakpointListView.cpp
BreakpointsView.cpp
ConsoleOutputView.cpp
ExpressionEvaluationWindow.cpp
ExpressionPromptWindow.cpp
ImageFunctionsView.cpp
ImageListView.cpp

View File

@ -1,219 +0,0 @@
/*
* Copyright 2014, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "ExpressionEvaluationWindow.h"
#include <Alert.h>
#include <Button.h>
#include <LayoutBuilder.h>
#include <MenuField.h>
#include <String.h>
#include <StringView.h>
#include <TextControl.h>
#include "AutoLocker.h"
#include "IntegerValue.h"
#include "MessageCodes.h"
#include "SourceLanguage.h"
#include "StackFrame.h"
#include "SyntheticPrimitiveType.h"
#include "Thread.h"
#include "UiUtils.h"
#include "UserInterface.h"
ExpressionEvaluationWindow::ExpressionEvaluationWindow(
SourceLanguage* language, StackFrame* frame, ::Thread* thread,
UserInterfaceListener* listener, BHandler* target)
:
BWindow(BRect(), "Evaluate Expression", B_FLOATING_WINDOW,
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fLanguage(language),
fExpressionInfo(NULL),
fExpressionInput(NULL),
fExpressionOutput(NULL),
fEvaluateButton(NULL),
fListener(listener),
fStackFrame(frame),
fThread(thread),
fCloseTarget(target)
{
fLanguage->AcquireReference();
if (fStackFrame != NULL)
fStackFrame->AcquireReference();
if (fThread != NULL)
fThread->AcquireReference();
}
ExpressionEvaluationWindow::~ExpressionEvaluationWindow()
{
fLanguage->ReleaseReference();
if (fStackFrame != NULL)
fStackFrame->ReleaseReference();
if (fThread != NULL)
fThread->ReleaseReference();
fExpressionInfo->ReleaseReference();
}
ExpressionEvaluationWindow*
ExpressionEvaluationWindow::Create(SourceLanguage* language, StackFrame* frame,
::Thread* thread, UserInterfaceListener* listener, BHandler* target)
{
ExpressionEvaluationWindow* self = new ExpressionEvaluationWindow(language,
frame, thread, listener, target);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
ExpressionEvaluationWindow::_Init()
{
fExpressionInfo = new ExpressionInfo;
fExpressionInfo->AddListener(this);
fExpressionInput = new BTextControl("Expression:", NULL,
new BMessage(MSG_EVALUATE_EXPRESSION));
BLayoutItem* labelItem = fExpressionInput->CreateLabelLayoutItem();
BLayoutItem* inputItem = fExpressionInput->CreateTextViewLayoutItem();
inputItem->SetExplicitMinSize(BSize(200.0, B_SIZE_UNSET));
inputItem->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
labelItem->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fExpressionOutput = new BStringView("ExpressionOutputView", NULL);
fExpressionOutput->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,
B_SIZE_UNSET));
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.AddGroup(B_HORIZONTAL, 4.0f)
.Add(labelItem)
.Add(inputItem)
.End()
.AddGroup(B_HORIZONTAL, 4.0f)
.Add(new BStringView("OutputLabelView", "Result:"))
.Add(fExpressionOutput)
.End()
.AddGroup(B_HORIZONTAL, 4.0f)
.AddGlue()
.Add((fEvaluateButton = new BButton("Evaluate",
new BMessage(MSG_EVALUATE_EXPRESSION))))
.End();
fExpressionInput->SetTarget(this);
fEvaluateButton->SetTarget(this);
fEvaluateButton->MakeDefault(true);
fExpressionInput->TextView()->MakeFocus(true);
}
void
ExpressionEvaluationWindow::ExpressionEvaluated(ExpressionInfo* info,
status_t result, ExpressionResult* value)
{
BMessage message(MSG_EXPRESSION_EVALUATED);
message.AddInt32("result", result);
BReference<ExpressionResult> reference;
if (value != NULL) {
message.AddPointer("value", value);
reference.SetTo(value);
}
if (PostMessage(&message) == B_OK)
reference.Detach();
}
void
ExpressionEvaluationWindow::Show()
{
CenterOnScreen();
BWindow::Show();
}
bool
ExpressionEvaluationWindow::QuitRequested()
{
BMessenger messenger(fCloseTarget);
messenger.SendMessage(MSG_EXPRESSION_WINDOW_CLOSED);
return BWindow::QuitRequested();
}
void
ExpressionEvaluationWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_EVALUATE_EXPRESSION:
{
if (fExpressionInput->TextView()->TextLength() == 0)
break;
fExpressionInfo->SetTo(fExpressionInput->Text());
fListener->ExpressionEvaluationRequested(fLanguage,
fExpressionInfo, fStackFrame, fThread);
break;
}
case MSG_EXPRESSION_EVALUATED:
{
ExpressionResult* value = NULL;
BReference<ExpressionResult> reference;
if (message->FindPointer("value",
reinterpret_cast<void**>(&value)) == B_OK) {
reference.SetTo(value, true);
}
BString outputText;
if (value != NULL) {
if (value->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
Value* primitive = value->PrimitiveValue();
if (dynamic_cast<IntegerValue*>(primitive) != NULL) {
BVariant variantValue;
primitive->ToVariant(variantValue);
primitive->ToString(outputText);
outputText.SetToFormat("%#" B_PRIx64 " (%s)",
variantValue.ToUInt64(), outputText.String());
} else
primitive->ToString(outputText);
} else {
outputText.SetToFormat("Unsupported result type: %d",
value->Kind());
}
} else {
status_t result;
if (message->FindInt32("result", &result) != B_OK)
result = B_ERROR;
outputText.SetToFormat("Failed to evaluate expression: %s",
strerror(result));
}
fExpressionOutput->SetText(outputText);
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}

View File

@ -1,69 +0,0 @@
/*
* Copyright 2014, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef EXPRESSION_EVALUATION_WINDOW_H
#define EXPRESSION_EVALUATION_WINDOW_H
#include <Window.h>
#include "ExpressionInfo.h"
class BButton;
class BStringView;
class BTextControl;
class Thread;
class SourceLanguage;
class StackFrame;
class UserInterfaceListener;
class ExpressionEvaluationWindow : public BWindow,
private ExpressionInfo::Listener
{
public:
ExpressionEvaluationWindow(
SourceLanguage* language,
StackFrame* frame,
::Thread* thread,
UserInterfaceListener* listener,
BHandler* target);
~ExpressionEvaluationWindow();
static ExpressionEvaluationWindow* Create(
SourceLanguage* language,
StackFrame* frame,
::Thread* thread,
UserInterfaceListener* listener,
BHandler* target);
// throws
virtual void MessageReceived(BMessage* message);
virtual void Show();
virtual bool QuitRequested();
private:
void _Init();
// ExpressionInfo::Listener
virtual void ExpressionEvaluated(ExpressionInfo* info,
status_t result, ExpressionResult* value);
private:
SourceLanguage* fLanguage;
ExpressionInfo* fExpressionInfo;
BTextControl* fExpressionInput;
BStringView* fExpressionOutput;
BButton* fEvaluateButton;
UserInterfaceListener* fListener;
StackFrame* fStackFrame;
::Thread* fThread;
BHandler* fCloseTarget;
};
#endif // EXPRESSION_EVALUATION_WINDOW_H

View File

@ -13,15 +13,16 @@
ExpressionPromptWindow::ExpressionPromptWindow(BHandler* addTarget,
BHandler* closeTarget)
BHandler* closeTarget, bool isPersistent)
:
BWindow(BRect(), "Add Expression", B_FLOATING_WINDOW,
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
BWindow(BRect(), isPersistent ? "Add Expression" : "Evaluate Expression",
B_FLOATING_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fExpressionInput(NULL),
fCancelButton(NULL),
fAddButton(NULL),
fAddTarget(addTarget),
fCloseTarget(closeTarget)
fCloseTarget(closeTarget),
fPersistentExpression(isPersistent)
{
}
@ -32,10 +33,11 @@ ExpressionPromptWindow::~ExpressionPromptWindow()
ExpressionPromptWindow*
ExpressionPromptWindow::Create(BHandler* addTarget, BHandler* closeTarget)
ExpressionPromptWindow::Create(BHandler* addTarget, BHandler* closeTarget,
bool isPersistent)
{
ExpressionPromptWindow* self = new ExpressionPromptWindow(addTarget,
closeTarget);
closeTarget, isPersistent);
try {
self->_Init();
@ -108,6 +110,7 @@ ExpressionPromptWindow::MessageReceived(BMessage* message)
{
BMessage addMessage(MSG_EXPRESSION_PROMPT_WINDOW_CLOSED);
addMessage.AddString("expression", fExpressionInput->Text());
addMessage.AddBool("persistent", fPersistentExpression);
addMessage.AddMessenger("target", BMessenger(fAddTarget));
BMessenger(fCloseTarget).SendMessage(&addMessage);

View File

@ -17,12 +17,13 @@ class ExpressionPromptWindow : public BWindow
{
public:
ExpressionPromptWindow(BHandler* addTarget,
BHandler* closeTarget);
BHandler* closeTarget, bool isPersistent);
~ExpressionPromptWindow();
static ExpressionPromptWindow* Create(BHandler* addTarget,
BHandler* closeTarget);
BHandler* closeTarget,
bool isPersistent);
// throws
@ -40,6 +41,7 @@ private:
BButton* fAddButton;
BHandler* fAddTarget;
BHandler* fCloseTarget;
bool fPersistentExpression;
};
#endif // EXPRESSION_PROMPT_WINDOW_H

View File

@ -41,7 +41,6 @@
#include "CpuState.h"
#include "DisassembledCode.h"
#include "BreakpointEditWindow.h"
#include "ExpressionEvaluationWindow.h"
#include "ExpressionPromptWindow.h"
#include "FileSourceCode.h"
#include "GuiSettingsUtils.h"
@ -142,7 +141,6 @@ TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* listener)
fBreakConditionConfigWindow(NULL),
fBreakpointEditWindow(NULL),
fInspectorWindow(NULL),
fExpressionWindow(NULL),
fExpressionPromptWindow(NULL),
fFilePanel(NULL),
fActiveSourceWorker(-1)
@ -170,9 +168,9 @@ TeamWindow::~TeamWindow()
if (fInspectorWindow->Lock())
fInspectorWindow->Quit();
}
if (fExpressionWindow != NULL) {
if (fExpressionWindow->Lock())
fExpressionWindow->Quit();
if (fExpressionPromptWindow != NULL) {
if (fExpressionPromptWindow->Lock())
fExpressionPromptWindow->Quit();
}
fTeam->RemoveListener(this);
@ -348,39 +346,12 @@ TeamWindow::MessageReceived(BMessage* message)
}
case MSG_SHOW_EXPRESSION_WINDOW:
{
if (fExpressionWindow != NULL) {
AutoLocker<BWindow> lock(fExpressionWindow);
if (lock.IsLocked())
fExpressionWindow->Activate(true);
} else {
try {
SourceLanguage* language = NULL;
if (_GetActiveSourceLanguage(language) != B_OK)
break;
BReference<SourceLanguage> languageReference(language,
true);
fExpressionWindow = ExpressionEvaluationWindow::Create(
language, fActiveStackFrame, fActiveThread, fListener,
this);
if (fExpressionWindow != NULL)
fExpressionWindow->Show();
} catch (...) {
// TODO: notify user
}
}
break;
}
case MSG_EXPRESSION_WINDOW_CLOSED:
{
fExpressionWindow = NULL;
break;
}
case MSG_SHOW_EXPRESSION_PROMPT_WINDOW:
{
BHandler* addTarget;
if (message->FindPointer("target",
if (message->what == MSG_SHOW_EXPRESSION_WINDOW)
addTarget = fVariablesView;
else if (message->FindPointer("target",
reinterpret_cast<void**>(&addTarget)) != B_OK) {
break;
}
@ -391,8 +362,13 @@ TeamWindow::MessageReceived(BMessage* message)
fExpressionPromptWindow->Activate(true);
} else {
try {
// if the request was initiated via the evaluate
// expression top level menu item, then this evaluation
// should not be persisted.
bool persistentExpression =
message->what == MSG_SHOW_EXPRESSION_PROMPT_WINDOW;
fExpressionPromptWindow = ExpressionPromptWindow::Create(
addTarget, this);
addTarget, this, persistentExpression);
if (fExpressionPromptWindow != NULL)
fExpressionPromptWindow->Show();
} catch (...) {
@ -401,6 +377,7 @@ TeamWindow::MessageReceived(BMessage* message)
}
break;
}
case MSG_EXPRESSION_WINDOW_CLOSED:
case MSG_EXPRESSION_PROMPT_WINDOW_CLOSED:
{
fExpressionPromptWindow = NULL;
@ -410,8 +387,11 @@ TeamWindow::MessageReceived(BMessage* message)
if (message->FindString("expression", &expression) == B_OK
&& message->FindMessenger("target", &targetMessenger)
== B_OK) {
BMessage addMessage(MSG_ADD_NEW_EXPRESSION);
addMessage.AddString("expression", expression);
addMessage.AddBool("persistent", message->FindBool(
"persistent"));
targetMessenger.SendMessage(&addMessage);
}

View File

@ -34,7 +34,6 @@ class BTabView;
class ConsoleOutputView;
class BreakConditionConfigWindow;
class BreakpointEditWindow;
class ExpressionEvaluationWindow;
class ExpressionPromptWindow;
class Image;
class InspectorWindow;
@ -231,7 +230,6 @@ private:
BreakConditionConfigWindow* fBreakConditionConfigWindow;
BreakpointEditWindow* fBreakpointEditWindow;
InspectorWindow* fInspectorWindow;
ExpressionEvaluationWindow* fExpressionWindow;
ExpressionPromptWindow* fExpressionPromptWindow;
GuiTeamUiSettings fUiSettings;
BFilePanel* fFilePanel;

View File

@ -1740,6 +1740,7 @@ VariablesView::VariablesView(Listener* listener)
fExpressionChildren(10, false),
fTableCellContextMenuTracker(NULL),
fPendingTypecastInfo(NULL),
fTemporaryExpression(NULL),
fFrameClearPending(false),
fListener(listener)
{
@ -1764,6 +1765,9 @@ VariablesView::~VariablesView()
delete fContainerListener;
if (fPendingTypecastInfo != NULL)
fPendingTypecastInfo->ReleaseReference();
if (fTemporaryExpression != NULL)
fTemporaryExpression->ReleaseReference();
}
@ -2060,8 +2064,11 @@ VariablesView::MessageReceived(BMessage* message)
if (message->FindString("expression", &expression) != B_OK)
break;
bool persistentExpression = message->FindBool("persistent");
ExpressionInfo* info;
status_t error = _AddExpression(expression, info);
status_t error = _AddExpression(expression, persistentExpression,
info);
if (error != B_OK) {
// TODO: notify user of failure
break;
@ -2096,8 +2103,13 @@ VariablesView::MessageReceived(BMessage* message)
fPendingTypecastInfo->ReleaseReference();
fPendingTypecastInfo = NULL;
}
} else
} else {
_AddExpressionNode(info, result, value);
if (info == fTemporaryExpression) {
info->ReleaseReference();
fTemporaryExpression = NULL;
}
}
break;
}
@ -2828,29 +2840,33 @@ VariablesView::_CopyVariableValueToClipboard()
status_t
VariablesView::_AddExpression(const char* expression, ExpressionInfo*& _info)
VariablesView::_AddExpression(const char* expression,
bool persistentExpression, ExpressionInfo*& _info)
{
// if our stack frame doesn't have an associated function,
// we can't add an expression
FunctionInstance* function = fStackFrame->Function();
if (function == NULL)
return B_NOT_ALLOWED;
ExpressionInfoEntry* entry = NULL;
if (persistentExpression) {
// if our stack frame doesn't have an associated function,
// we can't add an expression
FunctionInstance* function = fStackFrame->Function();
if (function == NULL)
return B_NOT_ALLOWED;
FunctionID* id = function->GetFunctionID();
if (id == NULL)
return B_NO_MEMORY;
BReference<FunctionID> idReference(id, true);
ExpressionInfoEntry* entry = fExpressions->Lookup(FunctionKey(id));
if (entry == NULL) {
entry = new(std::nothrow) ExpressionInfoEntry(id);
if (entry == NULL)
FunctionID* id = function->GetFunctionID();
if (id == NULL)
return B_NO_MEMORY;
status_t error = fExpressions->Insert(entry);
if (error != B_OK) {
delete entry;
return error;
BReference<FunctionID> idReference(id, true);
entry = fExpressions->Lookup(FunctionKey(id));
if (entry == NULL) {
entry = new(std::nothrow) ExpressionInfoEntry(id);
if (entry == NULL)
return B_NO_MEMORY;
status_t error = fExpressions->Insert(entry);
if (error != B_OK) {
delete entry;
return error;
}
}
}
@ -2861,8 +2877,11 @@ VariablesView::_AddExpression(const char* expression, ExpressionInfo*& _info)
BReference<ExpressionInfo> infoReference(info, true);
if (!entry->AddItem(info))
return B_NO_MEMORY;
if (persistentExpression) {
if (!entry->AddItem(info))
return B_NO_MEMORY;
} else
fTemporaryExpression = info;
info->AddListener(this);
infoReference.Detach();
@ -2926,6 +2945,7 @@ void
VariablesView::_AddExpressionNode(ExpressionInfo* info, status_t result,
ExpressionResult* value)
{
bool temporaryExpression = (info == fTemporaryExpression);
Variable* variable = NULL;
BReference<Variable> variableReference;
BVariant valueData;
@ -2990,9 +3010,12 @@ VariablesView::_AddExpressionNode(ExpressionInfo* info, status_t result,
child->Node()->SetLocationAndValue(NULL, explicitValue, B_OK);
}
if (fExpressionChildren.AddItem(child)) {
if (temporaryExpression || fExpressionChildren.AddItem(child)) {
child->AcquireReference();
if (temporaryExpression)
return;
// attempt to restore our newly added node's view state,
// if applicable.
FunctionID* functionID = fStackFrame->Function()

View File

@ -114,6 +114,7 @@ private:
void _CopyVariableValueToClipboard();
status_t _AddExpression(const char* expression,
bool persistentExpression,
ExpressionInfo*& _info);
void _RemoveExpression(ModelNode* node);
@ -140,6 +141,7 @@ private:
ExpressionChildList fExpressionChildren;
TableCellContextMenuTracker* fTableCellContextMenuTracker;
VariablesExpressionInfo* fPendingTypecastInfo;
ExpressionInfo* fTemporaryExpression;
bool fFrameClearPending;
Listener* fListener;
};