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
SourceLanguage::EvaluateExpression(const BString& expression,
ValueNodeManager* manager, TeamTypeInformation* info,
@@ -29,10 +29,6 @@ public:
// returns a reference,
// 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,
ValueNodeManager* manager,
TeamTypeInformation* info,
@@ -23,13 +23,3 @@ CLanguage::Name() const
{
return "C";
}
bool
CLanguage::IsModifierValid(char modifier) const
{
if (modifier == '*')
return true;
return false;
}
@@ -15,9 +15,6 @@ public:
virtual ~CLanguage();
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
CLanguageFamily::EvaluateExpression(const BString& expression,
ValueNodeManager* manager, TeamTypeInformation* info,
@@ -17,18 +17,11 @@ public:
virtual SyntaxHighlighter* GetSyntaxHighlighter() const;
virtual status_t ParseTypeExpression(const BString& expression,
TeamTypeInformation* lookup,
Type*& _resultType) const;
virtual status_t EvaluateExpression(const BString& expression,
ValueNodeManager* manager,
TeamTypeInformation* info,
ExpressionResult*& _output,
ValueNode*& _neededNode);
protected:
virtual bool IsModifierValid(char modifier) const = 0;
};
@@ -23,13 +23,3 @@ CppLanguage::Name() const
{
return "C++";
}
bool
CppLanguage::IsModifierValid(char modifier) const
{
if (modifier == '*' || modifier == '&')
return true;
return false;
}
@@ -15,9 +15,6 @@ public:
virtual ~CppLanguage();
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
@@ -1708,6 +1736,7 @@ VariablesView::VariablesView(Listener* listener)
fExpressions(NULL),
fExpressionChildren(10, false),
fTableCellContextMenuTracker(NULL),
fPendingTypecastInfo(NULL),
fFrameClearPending(false),
fListener(listener)
{
@@ -1730,6 +1759,8 @@ VariablesView::~VariablesView()
}
delete fContainerListener;
if (fPendingTypecastInfo != NULL)
fPendingTypecastInfo->ReleaseReference();
}
@@ -1848,44 +1879,27 @@ VariablesView::MessageReceived(BMessage* message)
break;
}
Type* type = NULL;
BString typeExpression = message->FindString("text");
if (typeExpression.Length() == 0)
break;
BString typeExpression;
if (message->FindString("text", &typeExpression) == B_OK) {
if (typeExpression.IsEmpty())
break;
FileSourceCode* code = fStackFrame->Function()->GetFunction()
->GetSourceCode();
if (code == NULL)
break;
if (fPendingTypecastInfo != NULL)
fPendingTypecastInfo->ReleaseReference();
SourceLanguage* language = code->GetSourceLanguage();
if (language == NULL)
break;
fPendingTypecastInfo = new(std::nothrow)
VariablesExpressionInfo(typeExpression, node);
if (fPendingTypecastInfo == NULL) {
// TODO: notify user
break;
}
if (language->ParseTypeExpression(typeExpression,
fThread->GetTeam()->DebugInfo(), type) != B_OK) {
BString errorMessage;
errorMessage.SetToFormat("Failed to resolve type %s",
typeExpression.String());
BAlert* alert = new(std::nothrow) BAlert("Error",
errorMessage.String(), "Close");
if (alert != NULL)
alert->Go();
fPendingTypecastInfo->AddListener(this);
fListener->ExpressionEvaluationRequested(fPendingTypecastInfo,
fStackFrame, fThread);
break;
}
BReference<Type> typeRef(type, true);
ValueNode* valueNode = NULL;
if (TypeHandlerRoster::Default()->CreateValueNode(
node->NodeChild(), type, valueNode) != B_OK) {
} else
break;
}
typeRef.Detach();
node->NodeChild()->SetNode(valueNode);
node->SetCastedType(type);
fVariableTableModel->NotifyNodeChanged(node);
break;
}
case MSG_TYPECAST_TO_ARRAY:
{
@@ -2071,7 +2085,17 @@ VariablesView::MessageReceived(BMessage* message)
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;
}
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
VariablesView::_GetTypeForTypeCode(int32 type, Type*& _resultType) const
{
@@ -77,6 +77,7 @@ private:
class VariableTableModel;
class ContextMenu;
class TableCellContextMenuTracker;
class VariablesExpressionInfo;
typedef BObjectList<ActionMenuItem> ContextActionList;
typedef BObjectList<ExpressionInfo> ExpressionInfoList;
typedef BObjectList<ValueNodeChild> ExpressionChildList;
@@ -121,6 +122,9 @@ private:
void _AddExpressionNode(ExpressionInfo* info,
status_t result, ExpressionResult* value);
void _HandleTypecastResult(status_t result,
ExpressionResult* value);
status_t _GetTypeForTypeCode(int32 typeCode,
Type*& _resultType) const;
@@ -135,6 +139,7 @@ private:
ExpressionInfoTable* fExpressions;
ExpressionChildList fExpressionChildren;
TableCellContextMenuTracker* fTableCellContextMenuTracker;
VariablesExpressionInfo* fPendingTypecastInfo;
bool fFrameClearPending;
Listener* fListener;
};