Debugger: Save/restore expression node values.
- This allows expression results to be highlighted for value changes as we already do for regular variable values.
This commit is contained in:
@@ -2470,6 +2470,14 @@ VariablesView::_SaveViewState() const
|
|||||||
if (values->Init() != B_OK)
|
if (values->Init() != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ExpressionValues* expressionValues = new(std::nothrow) ExpressionValues;
|
||||||
|
if (expressionValues == NULL)
|
||||||
|
return;
|
||||||
|
BReference<ExpressionValues> expressionReference(expressionValues, true);
|
||||||
|
|
||||||
|
if (expressionValues->Init() != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
// create an empty view state
|
// create an empty view state
|
||||||
VariablesViewState* viewState = new(std::nothrow) VariablesViewState;
|
VariablesViewState* viewState = new(std::nothrow) VariablesViewState;
|
||||||
if (viewState == NULL)
|
if (viewState == NULL)
|
||||||
@@ -2480,6 +2488,7 @@ VariablesView::_SaveViewState() const
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
viewState->SetValues(values);
|
viewState->SetValues(values);
|
||||||
|
viewState->SetExpressionValues(expressionValues);
|
||||||
|
|
||||||
// populate it
|
// populate it
|
||||||
TreeTablePath path;
|
TreeTablePath path;
|
||||||
@@ -2546,33 +2555,47 @@ VariablesView::_AddViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
|||||||
nodeInfo.SetRendererSettings(settings->Message());
|
nodeInfo.SetRendererSettings(settings->Message());
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable* variable = node->GetVariable();
|
|
||||||
if (variable == NULL) {
|
|
||||||
// ignore synthetic nodes
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectID* id = variable->ID();
|
|
||||||
TypeComponentPath* componentPath = node->GetPath();
|
|
||||||
|
|
||||||
status_t error = viewState->SetNodeInfo(id, componentPath, nodeInfo);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
Value* value = node->GetValue();
|
Value* value = node->GetValue();
|
||||||
if (value != NULL) {
|
Variable* variable = node->GetVariable();
|
||||||
BVariant variableValueData;
|
if (variable != NULL) {
|
||||||
if (value->ToVariant(variableValueData))
|
TypeComponentPath* componentPath = node->GetPath();
|
||||||
error = viewState->Values()->SetValue(id, componentPath,
|
ObjectID* id = variable->ID();
|
||||||
variableValueData);
|
|
||||||
|
status_t error = viewState->SetNodeInfo(id, componentPath, nodeInfo);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
|
|
||||||
// recurse
|
if (value != NULL) {
|
||||||
error = _AddViewStateDescendentNodeInfos(viewState, node, path);
|
BVariant variableValueData;
|
||||||
if (error != B_OK)
|
if (value->ToVariant(variableValueData))
|
||||||
return error;
|
error = viewState->Values()->SetValue(id, componentPath,
|
||||||
|
variableValueData);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recurse
|
||||||
|
error = _AddViewStateDescendentNodeInfos(viewState, node, path);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
} else {
|
||||||
|
ExpressionValueNodeChild* child
|
||||||
|
= dynamic_cast<ExpressionValueNodeChild*>(node->NodeChild());
|
||||||
|
if (child != NULL && value != NULL) {
|
||||||
|
BVariant variableValueData;
|
||||||
|
if (value->ToVariant(variableValueData)) {
|
||||||
|
FunctionID* id = fStackFrame->Function()->GetFunctionID();
|
||||||
|
if (id == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
BReference<FunctionID> functionReference(id, true);
|
||||||
|
status_t error = viewState->GetExpressionValues()
|
||||||
|
->SetValue(id, fThread, child->GetExpression(),
|
||||||
|
variableValueData);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
path.RemoveLastComponent();
|
path.RemoveLastComponent();
|
||||||
}
|
}
|
||||||
@@ -2593,49 +2616,62 @@ VariablesView::_ApplyViewStateDescendentNodeInfos(VariablesViewState* viewState,
|
|||||||
|
|
||||||
// apply the node's info, if any
|
// apply the node's info, if any
|
||||||
Variable* variable = node->GetVariable();
|
Variable* variable = node->GetVariable();
|
||||||
if (variable == NULL) {
|
if (variable != NULL) {
|
||||||
// ignore synthetic nodes
|
ObjectID* objectID = node->GetVariable()->ID();
|
||||||
return B_OK;
|
TypeComponentPath* componentPath = node->GetPath();
|
||||||
}
|
const VariablesViewNodeInfo* nodeInfo = viewState->GetNodeInfo(
|
||||||
ObjectID* objectID = node->GetVariable()->ID();
|
objectID, componentPath);
|
||||||
TypeComponentPath* componentPath = node->GetPath();
|
if (nodeInfo != NULL) {
|
||||||
const VariablesViewNodeInfo* nodeInfo = viewState->GetNodeInfo(
|
// NB: if the node info indicates that the node in question
|
||||||
objectID, componentPath);
|
// was being cast to a different type, this *must* be applied
|
||||||
if (nodeInfo != NULL) {
|
// before any other view state restoration, since it
|
||||||
// NB: if the node info indicates that the node in question
|
// potentially changes the child hierarchy under that node.
|
||||||
// was being cast to a different type, this *must* be applied
|
Type* type = nodeInfo->GetCastedType();
|
||||||
// before any other view state restoration, since it potentially
|
if (type != NULL) {
|
||||||
// changes the child hierarchy under that node.
|
ValueNode* valueNode = NULL;
|
||||||
Type* type = nodeInfo->GetCastedType();
|
if (TypeHandlerRoster::Default()->CreateValueNode(
|
||||||
if (type != NULL) {
|
node->NodeChild(), type, valueNode) == B_OK) {
|
||||||
ValueNode* valueNode = NULL;
|
node->NodeChild()->SetNode(valueNode);
|
||||||
if (TypeHandlerRoster::Default()->CreateValueNode(
|
node->SetCastedType(type);
|
||||||
node->NodeChild(), type, valueNode) == B_OK) {
|
}
|
||||||
node->NodeChild()->SetNode(valueNode);
|
}
|
||||||
node->SetCastedType(type);
|
|
||||||
|
// we don't have a renderer yet so we can't apply the settings
|
||||||
|
// at this stage. Store them on the model node so we can lazily
|
||||||
|
// apply them once the value is retrieved.
|
||||||
|
node->SetLastRendererSettings(nodeInfo->GetRendererSettings());
|
||||||
|
|
||||||
|
fVariableTable->SetNodeExpanded(path,
|
||||||
|
nodeInfo->IsNodeExpanded());
|
||||||
|
|
||||||
|
BVariant previousValue;
|
||||||
|
if (viewState->Values()->GetValue(objectID, componentPath,
|
||||||
|
previousValue)) {
|
||||||
|
node->SetPreviousValue(previousValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// we don't have a renderer yet so we can't apply the settings
|
ExpressionValueNodeChild* child
|
||||||
// at this stage. Store them on the model node so we can lazily
|
= dynamic_cast<ExpressionValueNodeChild*>(node->NodeChild());
|
||||||
// apply them once the value is retrieved.
|
if (child != NULL) {
|
||||||
node->SetLastRendererSettings(nodeInfo->GetRendererSettings());
|
BVariant previousValue;
|
||||||
|
FunctionID* id = fStackFrame->Function()->GetFunctionID();
|
||||||
fVariableTable->SetNodeExpanded(path, nodeInfo->IsNodeExpanded());
|
if (id == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
BVariant previousValue;
|
BReference<FunctionID> idReference(id, true);
|
||||||
if (viewState->Values()->GetValue(objectID, componentPath,
|
if (viewState->GetExpressionValues()->GetValue(id, fThread,
|
||||||
previousValue)) {
|
child->GetExpression(), previousValue)) {
|
||||||
node->SetPreviousValue(previousValue);
|
node->SetPreviousValue(previousValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recurse
|
|
||||||
status_t error = _ApplyViewStateDescendentNodeInfos(viewState, node,
|
|
||||||
path);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recurse
|
||||||
|
status_t error = _ApplyViewStateDescendentNodeInfos(viewState, node,
|
||||||
|
path);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
path.RemoveLastComponent();
|
path.RemoveLastComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user