Debugger: Cleanups.

SourceLanguage and friends:
- Remove ParseTypeExpression from SourceLanguage, as its functionality
  can now properly be subsumed by the general expression parser, and
  simply becomes another result type thereof.

CLanguageFamily/CLanguage/CppLanguage:
- Remove IsModifierValid() hook, as this is all now handled internally
  in the expression parser.

VariablesView:
- Refactor to handle typecast requests via expression evaluation. Since
  this is done asynchronously, rework the logic to handle recognizing
  expression evaluation results that correspond to a requested cast,
  and handle accordingly.
This commit is contained in:
Rene Gollent
2014-12-11 22:17:35 -05:00
parent 194d85f4a3
commit db1df758b8
10 changed files with 117 additions and 206 deletions
@@ -20,14 +20,6 @@ SourceLanguage::GetSyntaxHighlighter() const
} }
status_t
SourceLanguage::ParseTypeExpression(const BString& expression,
TeamTypeInformation* info, Type*& _resultType) const
{
return B_NOT_SUPPORTED;
}
status_t status_t
SourceLanguage::EvaluateExpression(const BString& expression, SourceLanguage::EvaluateExpression(const BString& expression,
ValueNodeManager* manager, TeamTypeInformation* info, ValueNodeManager* manager, TeamTypeInformation* info,
@@ -29,10 +29,6 @@ public:
// returns a reference, // returns a reference,
// may return NULL, if not available // may return NULL, if not available
virtual status_t ParseTypeExpression(const BString& expression,
TeamTypeInformation* info,
Type*& _resultType) const;
virtual status_t EvaluateExpression(const BString& expression, virtual status_t EvaluateExpression(const BString& expression,
ValueNodeManager* manager, ValueNodeManager* manager,
TeamTypeInformation* info, TeamTypeInformation* info,
@@ -23,13 +23,3 @@ CLanguage::Name() const
{ {
return "C"; return "C";
} }
bool
CLanguage::IsModifierValid(char modifier) const
{
if (modifier == '*')
return true;
return false;
}
@@ -15,9 +15,6 @@ public:
virtual ~CLanguage(); virtual ~CLanguage();
virtual const char* Name() const; virtual const char* Name() const;
protected:
virtual bool IsModifierValid(char modifier) const;
}; };
@@ -40,133 +40,6 @@ CLanguageFamily::GetSyntaxHighlighter() const
} }
status_t
CLanguageFamily::ParseTypeExpression(const BString& expression,
TeamTypeInformation* info, Type*& _resultType) const
{
status_t result = B_OK;
Type* baseType = NULL;
BString parsedName = expression;
BString baseTypeName;
BString arraySpecifier;
parsedName.RemoveAll(" ");
int32 modifierIndex = -1;
modifierIndex = parsedName.FindFirst('*');
if (modifierIndex == -1)
modifierIndex = parsedName.FindFirst('&');
if (modifierIndex == -1)
modifierIndex = parsedName.FindFirst('[');
if (modifierIndex == -1)
modifierIndex = parsedName.Length();
parsedName.MoveInto(baseTypeName, 0, modifierIndex);
modifierIndex = parsedName.FindFirst('[');
if (modifierIndex >= 0) {
parsedName.MoveInto(arraySpecifier, modifierIndex,
parsedName.Length() - modifierIndex);
}
result = info->LookupTypeByName(baseTypeName, TypeLookupConstraints(),
baseType);
if (result != B_OK)
return result;
BReference<Type> typeRef;
typeRef.SetTo(baseType, true);
if (!parsedName.IsEmpty()) {
AddressType* derivedType = NULL;
// walk the list of modifiers trying to add each.
for (int32 i = 0; i < parsedName.Length(); i++) {
if (!IsModifierValid(parsedName[i]))
return B_BAD_VALUE;
address_type_kind typeKind;
switch (parsedName[i]) {
case '*':
{
typeKind = DERIVED_TYPE_POINTER;
break;
}
case '&':
{
typeKind = DERIVED_TYPE_REFERENCE;
break;
}
default:
{
return B_BAD_VALUE;
}
}
if (derivedType == NULL) {
result = baseType->CreateDerivedAddressType(typeKind,
derivedType);
} else {
result = derivedType->CreateDerivedAddressType(typeKind,
derivedType);
}
if (result != B_OK)
return result;
typeRef.SetTo(derivedType, true);
}
_resultType = derivedType;
} else
_resultType = baseType;
if (!arraySpecifier.IsEmpty()) {
ArrayType* arrayType = NULL;
int32 startIndex = 1;
do {
int32 size = strtoul(arraySpecifier.String() + startIndex,
NULL, 10);
if (size < 0)
return B_ERROR;
if (arrayType == NULL) {
result = _resultType->CreateDerivedArrayType(0, size, true,
arrayType);
} else {
result = arrayType->CreateDerivedArrayType(0, size, true,
arrayType);
}
if (result != B_OK)
return result;
typeRef.SetTo(arrayType, true);
startIndex = arraySpecifier.FindFirst('[', startIndex + 1);
} while (startIndex >= 0);
// since a C/C++ array is essentially pointer math,
// the resulting array has to be wrapped in a pointer to
// ensure the element addresses wind up being against the
// correct address.
AddressType* addressType = NULL;
result = arrayType->CreateDerivedAddressType(DERIVED_TYPE_POINTER,
addressType);
if (result != B_OK)
return result;
_resultType = addressType;
}
typeRef.Detach();
return result;
}
status_t status_t
CLanguageFamily::EvaluateExpression(const BString& expression, CLanguageFamily::EvaluateExpression(const BString& expression,
ValueNodeManager* manager, TeamTypeInformation* info, ValueNodeManager* manager, TeamTypeInformation* info,
@@ -17,18 +17,11 @@ public:
virtual SyntaxHighlighter* GetSyntaxHighlighter() const; virtual SyntaxHighlighter* GetSyntaxHighlighter() const;
virtual status_t ParseTypeExpression(const BString& expression,
TeamTypeInformation* lookup,
Type*& _resultType) const;
virtual status_t EvaluateExpression(const BString& expression, virtual status_t EvaluateExpression(const BString& expression,
ValueNodeManager* manager, ValueNodeManager* manager,
TeamTypeInformation* info, TeamTypeInformation* info,
ExpressionResult*& _output, ExpressionResult*& _output,
ValueNode*& _neededNode); ValueNode*& _neededNode);
protected:
virtual bool IsModifierValid(char modifier) const = 0;
}; };
@@ -23,13 +23,3 @@ CppLanguage::Name() const
{ {
return "C++"; return "C++";
} }
bool
CppLanguage::IsModifierValid(char modifier) const
{
if (modifier == '*' || modifier == '&')
return true;
return false;
}
@@ -15,9 +15,6 @@ public:
virtual ~CppLanguage(); virtual ~CppLanguage();
virtual const char* Name() const; virtual const char* Name() const;
protected:
virtual bool IsModifierValid(char modifier) const;
}; };
@@ -544,6 +544,34 @@ public:
}; };
// #pragma mark - VariablesExpressionInfo
class VariablesView::VariablesExpressionInfo : public ExpressionInfo {
public:
VariablesExpressionInfo(const BString& expression, ModelNode* node)
:
ExpressionInfo(expression),
fTargetNode(node)
{
fTargetNode->AcquireReference();
}
virtual ~VariablesExpressionInfo()
{
fTargetNode->ReleaseReference();
}
inline ModelNode* TargetNode() const
{
return fTargetNode;
}
private:
ModelNode* fTargetNode;
};
// #pragma mark - VariableValueColumn // #pragma mark - VariableValueColumn
@@ -1708,6 +1736,7 @@ VariablesView::VariablesView(Listener* listener)
fExpressions(NULL), fExpressions(NULL),
fExpressionChildren(10, false), fExpressionChildren(10, false),
fTableCellContextMenuTracker(NULL), fTableCellContextMenuTracker(NULL),
fPendingTypecastInfo(NULL),
fFrameClearPending(false), fFrameClearPending(false),
fListener(listener) fListener(listener)
{ {
@@ -1730,6 +1759,8 @@ VariablesView::~VariablesView()
} }
delete fContainerListener; delete fContainerListener;
if (fPendingTypecastInfo != NULL)
fPendingTypecastInfo->ReleaseReference();
} }
@@ -1848,44 +1879,27 @@ VariablesView::MessageReceived(BMessage* message)
break; break;
} }
Type* type = NULL; BString typeExpression;
BString typeExpression = message->FindString("text"); if (message->FindString("text", &typeExpression) == B_OK) {
if (typeExpression.Length() == 0) if (typeExpression.IsEmpty())
break; break;
FileSourceCode* code = fStackFrame->Function()->GetFunction() if (fPendingTypecastInfo != NULL)
->GetSourceCode(); fPendingTypecastInfo->ReleaseReference();
if (code == NULL)
break;
SourceLanguage* language = code->GetSourceLanguage(); fPendingTypecastInfo = new(std::nothrow)
if (language == NULL) VariablesExpressionInfo(typeExpression, node);
break; if (fPendingTypecastInfo == NULL) {
// TODO: notify user
break;
}
if (language->ParseTypeExpression(typeExpression, fPendingTypecastInfo->AddListener(this);
fThread->GetTeam()->DebugInfo(), type) != B_OK) { fListener->ExpressionEvaluationRequested(fPendingTypecastInfo,
BString errorMessage; fStackFrame, fThread);
errorMessage.SetToFormat("Failed to resolve type %s",
typeExpression.String());
BAlert* alert = new(std::nothrow) BAlert("Error",
errorMessage.String(), "Close");
if (alert != NULL)
alert->Go();
break; break;
} } else
BReference<Type> typeRef(type, true);
ValueNode* valueNode = NULL;
if (TypeHandlerRoster::Default()->CreateValueNode(
node->NodeChild(), type, valueNode) != B_OK) {
break; break;
}
typeRef.Detach();
node->NodeChild()->SetNode(valueNode);
node->SetCastedType(type);
fVariableTableModel->NotifyNodeChanged(node);
break;
} }
case MSG_TYPECAST_TO_ARRAY: case MSG_TYPECAST_TO_ARRAY:
{ {
@@ -2071,7 +2085,17 @@ VariablesView::MessageReceived(BMessage* message)
valueReference.SetTo(value, true); valueReference.SetTo(value, true);
} }
_AddExpressionNode(info, result, value); VariablesExpressionInfo* variableInfo
= dynamic_cast<VariablesExpressionInfo*>(info);
if (variableInfo != NULL) {
if (fPendingTypecastInfo == variableInfo) {
_HandleTypecastResult(result, value);
fPendingTypecastInfo->ReleaseReference();
fPendingTypecastInfo = NULL;
}
} else
_AddExpressionNode(info, result, value);
break; break;
} }
case MSG_VALUE_NODE_CHANGED: case MSG_VALUE_NODE_CHANGED:
@@ -2985,6 +3009,60 @@ VariablesView::_AddExpressionNode(ExpressionInfo* info, status_t result,
} }
void
VariablesView::_HandleTypecastResult(status_t result, ExpressionResult* value)
{
BString errorMessage;
if (value == NULL) {
errorMessage.SetToFormat("Failed to evaluate expression \"%s\": %s (%"
B_PRId32 ")", fPendingTypecastInfo->Expression().String(),
strerror(result), result);
} else if (result != B_OK) {
BVariant valueData;
value->PrimitiveValue()->ToVariant(valueData);
// usually, the evaluation can give us back an error message to
// specifically indicate why it failed. If it did, simply use
// the message directly, otherwise fall back to generating an error
// message based on the error code
if (valueData.Type() == B_STRING_TYPE)
errorMessage = valueData.ToString();
else {
errorMessage.SetToFormat("Failed to evaluate expression \"%s\":"
" %s (%" B_PRId32 ")",
fPendingTypecastInfo->Expression().String(), strerror(result),
result);
}
} else if (value->Kind() != EXPRESSION_RESULT_KIND_TYPE) {
errorMessage.SetToFormat("Expression \"%s\" does not evaluate to a"
" type.", fPendingTypecastInfo->Expression().String());
}
if (!errorMessage.IsEmpty()) {
BAlert* alert = new(std::nothrow) BAlert("Typecast error",
errorMessage, "Close");
if (alert != NULL)
alert->Go();
return;
}
Type* type = value->GetType();
BReference<Type> typeRef(type);
ValueNode* valueNode = NULL;
ModelNode* node = fPendingTypecastInfo->TargetNode();
if (TypeHandlerRoster::Default()->CreateValueNode(node->NodeChild(), type,
valueNode) != B_OK) {
return;
}
node->NodeChild()->SetNode(valueNode);
node->SetCastedType(type);
fVariableTableModel->NotifyNodeChanged(node);
}
status_t status_t
VariablesView::_GetTypeForTypeCode(int32 type, Type*& _resultType) const VariablesView::_GetTypeForTypeCode(int32 type, Type*& _resultType) const
{ {
@@ -77,6 +77,7 @@ private:
class VariableTableModel; class VariableTableModel;
class ContextMenu; class ContextMenu;
class TableCellContextMenuTracker; class TableCellContextMenuTracker;
class VariablesExpressionInfo;
typedef BObjectList<ActionMenuItem> ContextActionList; typedef BObjectList<ActionMenuItem> ContextActionList;
typedef BObjectList<ExpressionInfo> ExpressionInfoList; typedef BObjectList<ExpressionInfo> ExpressionInfoList;
typedef BObjectList<ValueNodeChild> ExpressionChildList; typedef BObjectList<ValueNodeChild> ExpressionChildList;
@@ -121,6 +122,9 @@ private:
void _AddExpressionNode(ExpressionInfo* info, void _AddExpressionNode(ExpressionInfo* info,
status_t result, ExpressionResult* value); status_t result, ExpressionResult* value);
void _HandleTypecastResult(status_t result,
ExpressionResult* value);
status_t _GetTypeForTypeCode(int32 typeCode, status_t _GetTypeForTypeCode(int32 typeCode,
Type*& _resultType) const; Type*& _resultType) const;
@@ -135,6 +139,7 @@ private:
ExpressionInfoTable* fExpressions; ExpressionInfoTable* fExpressions;
ExpressionChildList fExpressionChildren; ExpressionChildList fExpressionChildren;
TableCellContextMenuTracker* fTableCellContextMenuTracker; TableCellContextMenuTracker* fTableCellContextMenuTracker;
VariablesExpressionInfo* fPendingTypecastInfo;
bool fFrameClearPending; bool fFrameClearPending;
Listener* fListener; Listener* fListener;
}; };