Debugger: Rework type handlers to allow for custom selection.

TypeHandler:
- Add name field for presentation purposes. Adapt subclasses accordingly.

TypeHandlerRoster:
- Add methods to count and retrieve all type handlers for a given type,
  and adjust CreateValueNode to allow for passing in an explicit handler.
  Adjust callers accordingly.

VariablesViewState:
- Add helpers to store an explicitly chosen type handler for a node.

TypeHandlerMenuItem:
- ActionMenuItem subclass that takes care of reference management
  for its contained type handler.

VariablesView:
- Add context menu for choosing type handlers if applicable. Implement
  support for invoking said type handlers in a similar manner to explicit
  typecasts.
- Adjust saving/restoring the view state so that hidden nodes are taken
  into account as well. This is necessary since it may be the case that
  the handler had to be applied to the hidden child rather than the visible
  node (i.e. the BMessage handler when applied to a pointer to a BMessage).

All together, these changes allow choosing to switch between views of a type
when the Debugger has multiple handlers for it. For example, for BMessages
this allows switching between displaying the raw underlying structure vs
the decoded message content.
This commit is contained in:
Rene Gollent
2018-02-04 14:13:01 -05:00
parent 401fb209ea
commit 770075026c
18 changed files with 466 additions and 63 deletions
+3 -1
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright 2009, Ingo Weinhold, [email protected]. * Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2018, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef TYPE_HANDLER_H #ifndef TYPE_HANDLER_H
@@ -18,7 +19,8 @@ class TypeHandler : public BReferenceable {
public: public:
virtual ~TypeHandler(); virtual ~TypeHandler();
virtual float SupportsType(Type* type) = 0; virtual const char* Name() const = 0;
virtual float SupportsType(Type* type) const = 0;
virtual status_t CreateValueNode(ValueNodeChild* nodeChild, virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
Type* type, ValueNode*& _node) = 0; Type* type, ValueNode*& _node) = 0;
// returns a reference // returns a reference
@@ -1,5 +1,6 @@
/* /*
* Copyright 2009, Ingo Weinhold, [email protected]. * Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2018, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef TYPE_HANDLER_ROSTER_H #ifndef TYPE_HANDLER_ROSTER_H
@@ -31,11 +32,18 @@ public:
status_t Init(); status_t Init();
status_t RegisterDefaultHandlers(); status_t RegisterDefaultHandlers();
status_t FindTypeHandler(ValueNodeChild* nodeChild, int32 CountTypeHandlers(Type* type);
status_t FindBestTypeHandler(ValueNodeChild* nodeChild,
Type* type, TypeHandler*& _handler); Type* type, TypeHandler*& _handler);
// returns a reference // returns a reference
status_t FindTypeHandlers(ValueNodeChild* nodeChild,
Type* type, TypeHandlerList*& _handlers);
// returns list of references
status_t CreateValueNode(ValueNodeChild* nodeChild, status_t CreateValueNode(ValueNodeChild* nodeChild,
Type* type, ValueNode*& _node); Type* type, TypeHandler* handler,
ValueNode*& _node);
// handler can be null if automatic
// search is desired.
// returns a reference // returns a reference
bool RegisterHandler(TypeHandler* handler); bool RegisterHandler(TypeHandler* handler);
+1
View File
@@ -127,6 +127,7 @@ local sources =
StackTraceView.cpp StackTraceView.cpp
TeamWindow.cpp TeamWindow.cpp
ThreadListView.cpp ThreadListView.cpp
TypeHandlerMenuItem.cpp
VariablesView.cpp VariablesView.cpp
# user_interface/gui/team_settings_window # user_interface/gui/team_settings_window
@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2014, Rene Gollent, [email protected]. * Copyright 2013-2018, Rene Gollent, [email protected].
* Copyright 2009, Ingo Weinhold, [email protected]. * Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -14,6 +14,7 @@
#include "StackFrameValues.h" #include "StackFrameValues.h"
#include "Type.h" #include "Type.h"
#include "TypeComponentPath.h" #include "TypeComponentPath.h"
#include "TypeHandler.h"
// #pragma mark - VariablesViewNodeInfo // #pragma mark - VariablesViewNodeInfo
@@ -23,6 +24,7 @@ VariablesViewNodeInfo::VariablesViewNodeInfo()
: :
fNodeExpanded(false), fNodeExpanded(false),
fCastedType(NULL), fCastedType(NULL),
fTypeHandler(NULL),
fRendererSettings() fRendererSettings()
{ {
} }
@@ -32,6 +34,7 @@ VariablesViewNodeInfo::VariablesViewNodeInfo(const VariablesViewNodeInfo& other)
: :
fNodeExpanded(other.fNodeExpanded), fNodeExpanded(other.fNodeExpanded),
fCastedType(other.fCastedType), fCastedType(other.fCastedType),
fTypeHandler(other.fTypeHandler),
fRendererSettings(other.fRendererSettings) fRendererSettings(other.fRendererSettings)
{ {
if (fCastedType != NULL) if (fCastedType != NULL)
@@ -43,6 +46,9 @@ VariablesViewNodeInfo::~VariablesViewNodeInfo()
{ {
if (fCastedType != NULL) if (fCastedType != NULL)
fCastedType->ReleaseReference(); fCastedType->ReleaseReference();
if (fTypeHandler != NULL)
fTypeHandler->ReleaseReference();
} }
@@ -51,6 +57,7 @@ VariablesViewNodeInfo::operator=(const VariablesViewNodeInfo& other)
{ {
fNodeExpanded = other.fNodeExpanded; fNodeExpanded = other.fNodeExpanded;
SetCastedType(other.fCastedType); SetCastedType(other.fCastedType);
SetTypeHandler(other.fTypeHandler);
fRendererSettings = other.fRendererSettings; fRendererSettings = other.fRendererSettings;
return *this; return *this;
@@ -76,6 +83,18 @@ VariablesViewNodeInfo::SetCastedType(Type* type)
} }
void
VariablesViewNodeInfo::SetTypeHandler(TypeHandler* handler)
{
if (fTypeHandler != NULL)
fTypeHandler->ReleaseReference();
fTypeHandler = handler;
if (fTypeHandler != NULL)
fTypeHandler->AcquireReference();
}
void void
VariablesViewNodeInfo::SetRendererSettings(const BMessage& settings) VariablesViewNodeInfo::SetRendererSettings(const BMessage& settings)
{ {
@@ -1,5 +1,5 @@
/* /*
* Copyright 2013-2014, Rene Gollent, [email protected]. * Copyright 2013-2018, Rene Gollent, [email protected].
* Copyright 2009, Ingo Weinhold, [email protected]. * Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -17,6 +17,7 @@ class ObjectID;
class StackFrameValues; class StackFrameValues;
class Type; class Type;
class TypeComponentPath; class TypeComponentPath;
class TypeHandler;
class VariablesViewNodeInfo { class VariablesViewNodeInfo {
@@ -37,6 +38,11 @@ public:
{ return fCastedType; } { return fCastedType; }
void SetCastedType(Type* type); void SetCastedType(Type* type);
TypeHandler* GetTypeHandler() const
{ return fTypeHandler; }
void SetTypeHandler(TypeHandler* handler);
const BMessage& GetRendererSettings() const const BMessage& GetRendererSettings() const
{ return fRendererSettings; } { return fRendererSettings; }
@@ -45,6 +51,7 @@ public:
private: private:
bool fNodeExpanded; bool fNodeExpanded;
Type* fCastedType; Type* fCastedType;
TypeHandler* fTypeHandler;
BMessage fRendererSettings; BMessage fRendererSettings;
}; };
@@ -0,0 +1,47 @@
/*
* Copyright 2018, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TypeHandlerMenuItem.h"
#include "TypeHandler.h"
TypeHandlerMenuItem::TypeHandlerMenuItem(const char* label, BMessage* message,
char shortcut, uint32 modifiers)
:
ActionMenuItem(label, message, shortcut, modifiers),
fTypeHandler(NULL)
{
}
TypeHandlerMenuItem::~TypeHandlerMenuItem()
{
if (fTypeHandler != NULL)
fTypeHandler->ReleaseReference();
}
void
TypeHandlerMenuItem::ItemSelected()
{
// if the item was selected, acquire a reference
// on behalf of the message target, as ours will be released
// when our menu item is freed.
fTypeHandler->AcquireReference();
}
status_t
TypeHandlerMenuItem::SetTypeHandler(TypeHandler* handler)
{
status_t error = Message()->AddPointer("handler", handler);
if (error != B_OK)
return error;
fTypeHandler = handler;
return B_OK;
}
@@ -0,0 +1,32 @@
/*
* Copyright 2018, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef TYPE_HANDLER_MENU_ITEM_H
#define TYPE_HANDLER_MENU_ITEM_H
#include "ActionMenuItem.h"
class TypeHandler;
class TypeHandlerMenuItem : public ActionMenuItem {
public:
TypeHandlerMenuItem(const char* label,
BMessage* message, char shortcut = 0,
uint32 modifiers = 0);
virtual ~TypeHandlerMenuItem();
virtual void ItemSelected();
status_t SetTypeHandler(TypeHandler* handler);
// takes over caller's reference
private:
TypeHandler* fTypeHandler;
};
#endif // TYPE_HANDLER_MENU_ITEM_H
@@ -1,6 +1,6 @@
/* /*
* Copyright 2009, Ingo Weinhold, [email protected]. * Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2011-2016, Rene Gollent, [email protected]. * Copyright 2011-2018, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -51,6 +51,8 @@
#include "Thread.h" #include "Thread.h"
#include "Tracing.h" #include "Tracing.h"
#include "TypeComponentPath.h" #include "TypeComponentPath.h"
#include "TypeHandler.h"
#include "TypeHandlerMenuItem.h"
#include "TypeHandlerRoster.h" #include "TypeHandlerRoster.h"
#include "TypeLookupConstraints.h" #include "TypeLookupConstraints.h"
#include "UiUtils.h" #include "UiUtils.h"
@@ -77,7 +79,9 @@ enum {
MSG_VALUE_NODE_NEEDS_VALUE = 'mvnv', MSG_VALUE_NODE_NEEDS_VALUE = 'mvnv',
MSG_RESTORE_PARTIAL_VIEW_STATE = 'mpvs', MSG_RESTORE_PARTIAL_VIEW_STATE = 'mpvs',
MSG_ADD_WATCH_EXPRESSION = 'awex', MSG_ADD_WATCH_EXPRESSION = 'awex',
MSG_REMOVE_WATCH_EXPRESSION = 'rwex' MSG_REMOVE_WATCH_EXPRESSION = 'rwex',
MSG_USE_AUTOMATIC_HANDLER = 'uaha',
MSG_USE_EXPLICIT_HANDLER = 'ueha'
}; };
@@ -267,6 +271,7 @@ public:
fTableCellRenderer(NULL), fTableCellRenderer(NULL),
fLastRendererSettings(), fLastRendererSettings(),
fCastedType(NULL), fCastedType(NULL),
fTypeHandler(NULL),
fComponentPath(NULL), fComponentPath(NULL),
fIsPresentationNode(isPresentationNode), fIsPresentationNode(isPresentationNode),
fHidden(false), fHidden(false),
@@ -294,6 +299,9 @@ public:
if (fCastedType != NULL) if (fCastedType != NULL)
fCastedType->ReleaseReference(); fCastedType->ReleaseReference();
if (fTypeHandler != NULL)
fTypeHandler->ReleaseReference();
} }
status_t Init() status_t Init()
@@ -396,6 +404,22 @@ public:
fCastedType->AcquireReference(); fCastedType->AcquireReference();
} }
TypeHandler* GetTypeHandler() const
{
return fTypeHandler;
}
void SetTypeHandler(TypeHandler* handler)
{
if (fTypeHandler != NULL)
fTypeHandler->ReleaseReference();
fTypeHandler = handler;
if (fTypeHandler != NULL)
fTypeHandler->AcquireReference();
}
const BMessage& GetLastRendererSettings() const const BMessage& GetLastRendererSettings() const
{ {
return fLastRendererSettings; return fLastRendererSettings;
@@ -544,6 +568,7 @@ private:
TableCellValueRenderer* fTableCellRenderer; TableCellValueRenderer* fTableCellRenderer;
BMessage fLastRendererSettings; BMessage fLastRendererSettings;
Type* fCastedType; Type* fCastedType;
TypeHandler* fTypeHandler;
ChildList fChildren; ChildList fChildren;
TypeComponentPath* fComponentPath; TypeComponentPath* fComponentPath;
bool fIsPresentationNode; bool fIsPresentationNode;
@@ -1599,7 +1624,7 @@ VariablesView::VariableTableModel::AddSyntheticNode(Variable* variable,
error = _child->CreateInternalNode(valueNode); error = _child->CreateInternalNode(valueNode);
else { else {
error = TypeHandlerRoster::Default()->CreateValueNode(_child, error = TypeHandlerRoster::Default()->CreateValueNode(_child,
_child->GetType(), valueNode); _child->GetType(), NULL, valueNode);
} }
if (error != B_OK) if (error != B_OK)
@@ -2025,7 +2050,7 @@ VariablesView::MessageReceived(BMessage* message)
typeRef.SetTo(addressType, true); typeRef.SetTo(addressType, true);
ValueNode* valueNode = NULL; ValueNode* valueNode = NULL;
if (TypeHandlerRoster::Default()->CreateValueNode( if (TypeHandlerRoster::Default()->CreateValueNode(
node->NodeChild(), addressType, valueNode) != B_OK) { node->NodeChild(), addressType, NULL, valueNode) != B_OK) {
break; break;
} }
@@ -2204,6 +2229,34 @@ VariablesView::MessageReceived(BMessage* message)
break; break;
} }
case MSG_USE_AUTOMATIC_HANDLER:
case MSG_USE_EXPLICIT_HANDLER:
{
TypeHandler* handler = NULL;
ModelNode* node = NULL;
if (message->FindPointer("node", reinterpret_cast<void **>(&node))
!= B_OK) {
break;
}
if (message->what == MSG_USE_EXPLICIT_HANDLER
&& message->FindPointer("handler", reinterpret_cast<void**>(
&handler)) != B_OK) {
break;
}
ValueNode* newNode;
ValueNodeChild* child = node->NodeChild();
if (TypeHandlerRoster::Default()->CreateValueNode(child,
child->GetType(), handler, newNode) != B_OK) {
return;
}
node->SetTypeHandler(handler);
child->SetNode(newNode);
_RequestNodeValue(node);
break;
}
case MSG_VALUE_NODE_CHANGED: case MSG_VALUE_NODE_CHANGED:
{ {
ValueNodeChild* nodeChild; ValueNodeChild* nodeChild;
@@ -2607,7 +2660,12 @@ VariablesView::_GetContextActionsForNode(ModelNode* node,
message->AddUInt64("address", location->PieceAt(0).address); message->AddUInt64("address", location->PieceAt(0).address);
} }
ValueNode* valueNode = node->NodeChild()->Node(); ValueNodeChild* child = node->NodeChild();
ValueNode* valueNode = child->Node();
result = _AddTypeHandlerMenuIfNeeded(node, _preActions);
if (result != B_OK)
return result;
if (valueNode != NULL) { if (valueNode != NULL) {
Value* value = valueNode->GetValue(); Value* value = valueNode->GetValue();
@@ -2699,23 +2757,142 @@ status_t
VariablesView::_AddContextAction(const char* action, uint32 what, VariablesView::_AddContextAction(const char* action, uint32 what,
ContextActionList* actions, BMessage*& _message) ContextActionList* actions, BMessage*& _message)
{ {
_message = new(std::nothrow) BMessage(what); ActionMenuItem* item = NULL;
if (_message == NULL) status_t result = _CreateContextAction(action, what, item);
return B_NO_MEMORY; if (result != B_OK)
return result;
ObjectDeleter<BMessage> messageDeleter(_message);
ActionMenuItem* item = new(std::nothrow) ActionMenuItem(action,
_message);
if (item == NULL)
return B_NO_MEMORY;
messageDeleter.Detach();
ObjectDeleter<ActionMenuItem> actionDeleter(item); ObjectDeleter<ActionMenuItem> actionDeleter(item);
if (!actions->AddItem(item)) if (!actions->AddItem(item))
return B_NO_MEMORY; return B_NO_MEMORY;
actionDeleter.Detach(); actionDeleter.Detach();
_message = item->Message();
return B_OK;
}
status_t
VariablesView::_CreateContextAction(const char* action, uint32 what,
ActionMenuItem*& _item)
{
BMessage* message = new(std::nothrow) BMessage(what);
if (message == NULL)
return B_NO_MEMORY;
ObjectDeleter<BMessage> messageDeleter(message);
_item = new(std::nothrow) ActionMenuItem(action,
message);
if (_item == NULL)
return B_NO_MEMORY;
messageDeleter.Detach();
return B_OK;
}
status_t
VariablesView::_AddTypeHandlerMenuIfNeeded(ModelNode* node,
ContextActionList* actions)
{
ValueNodeChild* child = node->NodeChild();
Type* type = child->GetType();
if (node->CountChildren() == 1 && node->ChildAt(0)->IsHidden()) {
node = node->ChildAt(0);
child = node->NodeChild();
type = child->GetType();
}
int32 handlerCount = TypeHandlerRoster::Default()->CountTypeHandlers(
child->GetType());
if (handlerCount > 1) {
TypeHandler* lastHandler = node->GetTypeHandler();
BMenu* handlerMenu = new(std::nothrow) BMenu("Show as");
if (handlerMenu == NULL)
return B_NO_MEMORY;
ObjectDeleter<BMenu> menuDeleter(handlerMenu);
ActionMenuItem* menuItem = new(std::nothrow) ActionMenuItem(
handlerMenu);
if (menuItem == NULL)
return B_NO_MEMORY;
ObjectDeleter<ActionMenuItem> menuItemDeleter(menuItem);
menuDeleter.Detach();
ActionMenuItem* item = NULL;
status_t result = _CreateContextAction("Automatic",
MSG_USE_AUTOMATIC_HANDLER, item);
if (item == NULL)
return B_NO_MEMORY;
item->Message()->AddPointer("node", node);
ObjectDeleter<ActionMenuItem> itemDeleter(item);
if (!handlerMenu->AddItem(item) || !handlerMenu->AddSeparatorItem())
return B_NO_MEMORY;
itemDeleter.Detach();
if (lastHandler == NULL)
item->SetMarked(true);
TypeHandlerList* handlers = NULL;
result = TypeHandlerRoster::Default()->FindTypeHandlers(child,
child->GetType(), handlers);
if (result != B_OK)
return result;
ObjectDeleter<TypeHandlerList> listDeleter(handlers);
while (handlers->CountItems() > 0) {
TypeHandler* handler = handlers->ItemAt(0);
BMessage* message = new(std::nothrow) BMessage(
MSG_USE_EXPLICIT_HANDLER);
if (message == NULL) {
result = B_NO_MEMORY;
break;
}
message->AddPointer("node", node);
TypeHandlerMenuItem* typeItem
= new(std::nothrow) TypeHandlerMenuItem(handler->Name(),
message);
if (typeItem == NULL) {
result = B_NO_MEMORY;
break;
}
ObjectDeleter<TypeHandlerMenuItem> typeItemDeleter(typeItem);
result = typeItem->SetTypeHandler(handler);
if (result != B_OK)
break;
handlers->RemoveItemAt(0);
if (!handlerMenu->AddItem(typeItem)) {
result = B_NO_MEMORY;
break;
}
typeItemDeleter.Detach();
if (handler == lastHandler)
typeItem->SetMarked(true);
}
if (result != B_OK) {
for (int32 i = 0; TypeHandler* handler = handlers->ItemAt(i);
i++) {
handler->ReleaseReference();
}
return result;
}
if (!actions->AddItem(menuItem))
return B_NO_MEMORY;
handlerMenu->SetTargetForItems(this);
menuItemDeleter.Detach();
}
return B_OK; return B_OK;
} }
@@ -2843,9 +3020,14 @@ status_t
VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState, VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
void* parent, TreeTablePath& path, bool updateValues) const void* parent, TreeTablePath& path, bool updateValues) const
{ {
int32 childCount = fVariableTableModel->CountChildren(parent); bool isRoot = parent == fVariableTableModel->Root();
int32 childCount = isRoot ? fVariableTableModel->CountChildren(parent)
: ((ModelNode*)parent)->CountChildren();
for (int32 i = 0; i < childCount; i++) { for (int32 i = 0; i < childCount; i++) {
ModelNode* node = (ModelNode*)fVariableTableModel->ChildAt(parent, i); ModelNode* node = (ModelNode*)(isRoot ? fVariableTableModel->ChildAt(
parent, i)
: ((ModelNode*)parent)->ChildAt(i));
if (!path.AddComponent(i)) if (!path.AddComponent(i))
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -2853,6 +3035,7 @@ VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
VariablesViewNodeInfo nodeInfo; VariablesViewNodeInfo nodeInfo;
nodeInfo.SetNodeExpanded(fVariableTable->IsNodeExpanded(path)); nodeInfo.SetNodeExpanded(fVariableTable->IsNodeExpanded(path));
nodeInfo.SetCastedType(node->GetCastedType()); nodeInfo.SetCastedType(node->GetCastedType());
nodeInfo.SetTypeHandler(node->GetTypeHandler());
TableCellValueRenderer* renderer = node->TableCellRenderer(); TableCellValueRenderer* renderer = node->TableCellRenderer();
if (renderer != NULL) { if (renderer != NULL) {
Settings* settings = renderer->GetSettings(); Settings* settings = renderer->GetSettings();
@@ -2895,9 +3078,13 @@ status_t
VariablesView::_ApplyViewStateDescendentNodeInfos(VariablesViewState* viewState, VariablesView::_ApplyViewStateDescendentNodeInfos(VariablesViewState* viewState,
void* parent, TreeTablePath& path) void* parent, TreeTablePath& path)
{ {
int32 childCount = fVariableTableModel->CountChildren(parent); bool isRoot = parent == fVariableTableModel->Root();
int32 childCount = isRoot ? fVariableTableModel->CountChildren(parent)
: ((ModelNode*)parent)->CountChildren();
for (int32 i = 0; i < childCount; i++) { for (int32 i = 0; i < childCount; i++) {
ModelNode* node = (ModelNode*)fVariableTableModel->ChildAt(parent, i); ModelNode* node = (ModelNode*)(isRoot ? fVariableTableModel->ChildAt(
parent, i)
: ((ModelNode*)parent)->ChildAt(i));
if (!path.AddComponent(i)) if (!path.AddComponent(i))
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -2912,12 +3099,16 @@ VariablesView::_ApplyViewStateDescendentNodeInfos(VariablesViewState* viewState,
// before any other view state restoration, since it // before any other view state restoration, since it
// potentially changes the child hierarchy under that node. // potentially changes the child hierarchy under that node.
Type* type = nodeInfo->GetCastedType(); Type* type = nodeInfo->GetCastedType();
if (type != NULL) { TypeHandler* handler = nodeInfo->GetTypeHandler();
node->SetCastedType(type);
node->SetTypeHandler(handler);
if (type != NULL || handler != NULL) {
if (type == NULL)
type = node->GetType();
ValueNode* valueNode = NULL; ValueNode* valueNode = NULL;
if (TypeHandlerRoster::Default()->CreateValueNode( if (TypeHandlerRoster::Default()->CreateValueNode(
node->NodeChild(), type, valueNode) == B_OK) { node->NodeChild(), type, handler, valueNode) == B_OK) {
node->NodeChild()->SetNode(valueNode); node->NodeChild()->SetNode(valueNode);
node->SetCastedType(type);
} }
} }
@@ -3209,7 +3400,7 @@ VariablesView::_HandleTypecastResult(status_t result, ExpressionResult* value)
ValueNode* valueNode = NULL; ValueNode* valueNode = NULL;
ModelNode* node = fPendingTypecastInfo->TargetNode(); ModelNode* node = fPendingTypecastInfo->TargetNode();
if (TypeHandlerRoster::Default()->CreateValueNode(node->NodeChild(), type, if (TypeHandlerRoster::Default()->CreateValueNode(node->NodeChild(), type,
valueNode) != B_OK) { NULL, valueNode) != B_OK) {
return; return;
} }
@@ -104,6 +104,10 @@ private:
status_t _AddContextAction(const char* action, status_t _AddContextAction(const char* action,
uint32 what, ContextActionList* actions, uint32 what, ContextActionList* actions,
BMessage*& _message); BMessage*& _message);
status_t _CreateContextAction(const char* action,
uint32 what, ActionMenuItem*& _item);
status_t _AddTypeHandlerMenuIfNeeded(ModelNode* node,
ContextActionList* actions);
void _FinishContextMenu(bool force); void _FinishContextMenu(bool force);
void _SaveViewState(bool updateValues) const; void _SaveViewState(bool updateValues) const;
void _RestoreViewState(); void _RestoreViewState();
@@ -112,9 +112,8 @@ ValueNodeManager::ValueNodeChanged(ValueNodeChild* nodeChild,
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode); fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode);
if (oldNode != NULL) if (oldNode != NULL && !newNode->ChildCreationNeedsValue())
newNode->CreateChildren(fThread->GetTeam()->GetTeamTypeInformation()); newNode->CreateChildren(fThread->GetTeam()->GetTeamTypeInformation());
} }
@@ -201,7 +200,7 @@ ValueNodeManager::_CreateValueNode(ValueNodeChild* nodeChild)
error = nodeChild->CreateInternalNode(valueNode); error = nodeChild->CreateInternalNode(valueNode);
} else { } else {
error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild, error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild,
nodeChild->GetType(), valueNode); nodeChild->GetType(), NULL, valueNode);
} }
if (error != B_OK) if (error != B_OK)
@@ -1782,7 +1782,7 @@ CLanguageExpressionEvaluator::_ParseAtom()
ValueNode* newNode = NULL; ValueNode* newNode = NULL;
status_t error = TypeHandlerRoster::Default()->CreateValueNode(child, status_t error = TypeHandlerRoster::Default()->CreateValueNode(child,
castType, newNode); castType, NULL, newNode);
if (error != B_OK) { if (error != B_OK) {
throw ParseException("Unable to create value node for typecast" throw ParseException("Unable to create value node for typecast"
" operation.", token.position); " operation.", token.position);
+87 -18
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2018, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -24,6 +25,14 @@
#include "TypeHandler.h" #include "TypeHandler.h"
static int CompareTypeHandlers(const TypeHandler* a, const TypeHandler* b,
void* state)
{
Type* type = (Type*)state;
return a->SupportsType(type) > b->SupportsType(type) ? 1 : -1;
}
// #pragma mark - BasicTypeHandler // #pragma mark - BasicTypeHandler
@@ -33,7 +42,12 @@ namespace {
template<typename TypeClass, typename NodeClass> template<typename TypeClass, typename NodeClass>
class BasicTypeHandler : public TypeHandler { class BasicTypeHandler : public TypeHandler {
public: public:
virtual float SupportsType(Type* type) virtual const char* Name() const
{
return "Raw";
}
virtual float SupportsType(Type* type) const
{ {
return dynamic_cast<TypeClass*>(type) != NULL ? 0.5f : 0; return dynamic_cast<TypeClass*>(type) != NULL ? 0.5f : 0;
} }
@@ -161,8 +175,23 @@ TypeHandlerRoster::RegisterDefaultHandlers()
} }
int32
TypeHandlerRoster::CountTypeHandlers(Type* type)
{
AutoLocker<BLocker> locker(fLock);
int32 count = 0;
for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) {
if (handler->SupportsType(type) > 0)
++count;
}
return count;
}
status_t status_t
TypeHandlerRoster::FindTypeHandler(ValueNodeChild* nodeChild, Type* type, TypeHandlerRoster::FindBestTypeHandler(ValueNodeChild* nodeChild, Type* type,
TypeHandler*& _handler) TypeHandler*& _handler)
{ {
// find the best-supporting handler // find the best-supporting handler
@@ -189,26 +218,66 @@ TypeHandlerRoster::FindTypeHandler(ValueNodeChild* nodeChild, Type* type,
status_t status_t
TypeHandlerRoster::CreateValueNode(ValueNodeChild* nodeChild, Type* type, TypeHandlerRoster::FindTypeHandlers(ValueNodeChild* nodeChild, Type* type,
ValueNode*& _node) TypeHandlerList*& _handlers)
{ {
// find the best-supporting handler // find the best-supporting handler
while (true) { AutoLocker<BLocker> locker(fLock);
TypeHandler* handler;
status_t error = FindTypeHandler(nodeChild, type, handler); TypeHandlerList* handlers = new(std::nothrow) TypeHandlerList(10, false);
if (error == B_OK) { ObjectDeleter<TypeHandlerList> listDeleter(handlers);
// let the handler create the node if (handlers == NULL)
BReference<TypeHandler> handlerReference(handler, true); return B_NO_MEMORY;
return handler->CreateValueNode(nodeChild, type, _node);
for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) {
if (handler->SupportsType(type) > 0) {
if (!handlers->AddItem(handler))
return B_NO_MEMORY;
} }
// not found yet -- try to strip a modifier/typedef from the type
Type* nextType = type->ResolveRawType(true);
if (nextType == NULL || nextType == type)
return B_UNSUPPORTED;
type = nextType;
} }
if (handlers->CountItems() == 0)
return B_ENTRY_NOT_FOUND;
for (int32 i = 0; TypeHandler* handler = handlers->ItemAt(i); i++)
handler->AcquireReference();
handlers->SortItems(CompareTypeHandlers, type);
_handlers = handlers;
listDeleter.Detach();
return B_OK;
}
status_t
TypeHandlerRoster::CreateValueNode(ValueNodeChild* nodeChild, Type* type,
TypeHandler* handler, ValueNode*& _node)
{
BReference<TypeHandler> handlerReference;
// if the caller doesn't supply us with a handler to use, try to find
// the best match.
if (handler == NULL) {
// find the best-supporting handler
while (true) {
status_t error = FindBestTypeHandler(nodeChild, type, handler);
if (error == B_OK) {
handlerReference.SetTo(handler, true);
break;
}
// not found yet -- try to strip a modifier/typedef from the type
Type* nextType = type->ResolveRawType(true);
if (nextType == NULL || nextType == type)
return B_UNSUPPORTED;
type = nextType;
}
}
return handler->CreateValueNode(nodeChild, type, _node);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2012, Rene Gollent, rene@gollent.com. * Copyright 2012-2018, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -17,8 +17,15 @@ BListTypeHandler::~BListTypeHandler()
} }
const char*
BListTypeHandler::Name() const
{
return "List content";
}
float float
BListTypeHandler::SupportsType(Type* type) BListTypeHandler::SupportsType(Type* type) const
{ {
if (dynamic_cast<CompoundType*>(type) != NULL if (dynamic_cast<CompoundType*>(type) != NULL
&& (type->Name() == "BList" && (type->Name() == "BList"
@@ -1,5 +1,5 @@
/* /*
* Copyright 2012, Rene Gollent, rene@gollent.com. * Copyright 2012-2018, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef BLIST_TYPE_HANDLER_H #ifndef BLIST_TYPE_HANDLER_H
@@ -13,7 +13,8 @@ class BListTypeHandler : public TypeHandler {
public: public:
virtual ~BListTypeHandler(); virtual ~BListTypeHandler();
virtual float SupportsType(Type* type); virtual const char* Name() const;
virtual float SupportsType(Type* type) const;
virtual status_t CreateValueNode(ValueNodeChild* nodeChild, virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
Type* type, ValueNode*& _node); Type* type, ValueNode*& _node);
}; };
@@ -1,5 +1,5 @@
/* /*
* Copyright 2011, Rene Gollent, rene@gollent.com. * Copyright 2011-2018, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -17,8 +17,15 @@ BMessageTypeHandler::~BMessageTypeHandler()
} }
const char*
BMessageTypeHandler::Name() const
{
return "Message content";
}
float float
BMessageTypeHandler::SupportsType(Type* type) BMessageTypeHandler::SupportsType(Type* type) const
{ {
if (dynamic_cast<CompoundType*>(type) != NULL if (dynamic_cast<CompoundType*>(type) != NULL
&& type->Name() == "BMessage") && type->Name() == "BMessage")
@@ -1,5 +1,5 @@
/* /*
* Copyright 2011, Rene Gollent, rene@gollent.com. * Copyright 2011-2018, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef BMESSAGE_TYPE_HANDLER_H #ifndef BMESSAGE_TYPE_HANDLER_H
@@ -13,7 +13,8 @@ class BMessageTypeHandler : public TypeHandler {
public: public:
virtual ~BMessageTypeHandler(); virtual ~BMessageTypeHandler();
virtual float SupportsType(Type* type); virtual const char* Name() const;
virtual float SupportsType(Type* type) const;
virtual status_t CreateValueNode(ValueNodeChild* nodeChild, virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
Type* type, ValueNode*& _node); Type* type, ValueNode*& _node);
}; };
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010, Rene Gollent, rene@gollent.com * Copyright 2010-2018, Rene Gollent, rene@gollent.com
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -19,8 +19,15 @@ CStringTypeHandler::~CStringTypeHandler()
} }
const char*
CStringTypeHandler::Name() const
{
return "String";
}
float float
CStringTypeHandler::SupportsType(Type* type) CStringTypeHandler::SupportsType(Type* type) const
{ {
AddressType* addressType = dynamic_cast<AddressType*>(type); AddressType* addressType = dynamic_cast<AddressType*>(type);
ArrayType* arrayType = dynamic_cast<ArrayType*>(type); ArrayType* arrayType = dynamic_cast<ArrayType*>(type);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010, Rene Gollent, rene@gollent.com * Copyright 2010-2018, Rene Gollent, rene@gollent.com
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef CSTRING_TYPE_HANDLER_H #ifndef CSTRING_TYPE_HANDLER_H
@@ -13,7 +13,8 @@ class CStringTypeHandler : public TypeHandler {
public: public:
virtual ~CStringTypeHandler(); virtual ~CStringTypeHandler();
virtual float SupportsType(Type* type); virtual const char* Name() const;
virtual float SupportsType(Type* type) const;
virtual status_t CreateValueNode(ValueNodeChild* nodeChild, virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
Type* type, ValueNode*& _node); Type* type, ValueNode*& _node);
}; };