<rdar://problem/12523238> Commit 1 of 3

This commit enables the new HasChildren() feature for synthetic children providers
Namely, it hooks up the required bits and pieces so that individual synthetic children providers can implement a new (optional) has_children call
Default implementations have been provided where necessary so that any existing providers continue to work and behave correctly

Next steps are:
2) writing smart implementations of has_children for our providers whenever possible
3) make a test case

llvm-svn: 166495
This commit is contained in:
Enrico Granata
2012-10-23 19:54:09 +00:00
parent bdcebd323a
commit adaf282c76
9 changed files with 253 additions and 90 deletions

View File

@@ -418,12 +418,76 @@ LLDBSwigPythonCreateSyntheticProvider
Py_RETURN_NONE;
}
/*
these four calls below are meant to support
Python-based synthetic children providers
they essentially mimic the four pure virtual
method calls provided by the frontend class
*/
// wrapper that calls an optional instance member of an object taking no arguments
static PyObject*
LLDBSwigPython_CallOptionalMember
(
PyObject* self,
char* callee_name,
PyObject* ret_if_not_found = Py_None,
bool* was_found = NULL
)
{
if (self == NULL || self == Py_None)
{
if (was_found)
*was_found = false;
Py_XINCREF(ret_if_not_found);
return ret_if_not_found;
}
PyObject* pmeth = PyObject_GetAttrString(self, callee_name);
if (PyErr_Occurred())
{
PyErr_Clear();
}
if (pmeth == NULL || pmeth == Py_None)
{
if (was_found)
*was_found = false;
Py_XDECREF(pmeth);
Py_XINCREF(ret_if_not_found);
return ret_if_not_found;
}
if (PyCallable_Check(pmeth) == 0)
{
if (PyErr_Occurred())
{
PyErr_Clear();
}
Py_XDECREF(pmeth);
if (was_found)
*was_found = false;
Py_XINCREF(ret_if_not_found);
return ret_if_not_found;
}
if (was_found)
*was_found = true;
if (PyErr_Occurred())
{
PyErr_Clear();
}
Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
PyObject* py_return = PyObject_CallMethod(self, callee_name, NULL);
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
return py_return;
}
SWIGEXPORT uint32_t
LLDBSwigPython_CalculateNumChildren
@@ -431,33 +495,27 @@ LLDBSwigPython_CalculateNumChildren
PyObject *implementor
)
{
uint32_t ret_val = UINT32_MAX;
static char callee_name[] = "num_children";
if (implementor == NULL || implementor == Py_None)
return 0;
PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, NULL);
if (py_return == NULL || py_return == Py_None)
{
Py_XDECREF(py_return);
return UINT32_MAX;
}
long retval = PyInt_AsLong(py_return);
Py_DECREF(py_return);
if (retval >= 0)
return (uint32_t)retval;
if (!py_return)
return ret_val;
if (PyInt_Check(py_return))
ret_val = PyInt_AsLong(py_return);
Py_XDECREF(py_return);
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
return 0;
return ret_val;
}
SWIGEXPORT PyObject*
@@ -542,64 +600,38 @@ LLDBSwigPython_UpdateSynthProviderInstance
PyObject *implementor
)
{
bool ret_val = false;
static char callee_name[] = "update";
if (implementor == NULL || implementor == Py_None)
return ret_val;
PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name);
// all this code is here because update is optional, so we don't want to bother trying to call it unless it's been def:ined for us
// other synth provider calls are mandatory, so we want to fail in a very obvious way if they are missing!
PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
if (PyErr_Occurred())
{
PyErr_Clear();
}
if (pmeth == NULL || pmeth == Py_None)
{
Py_XDECREF(pmeth);
return ret_val;
}
if (PyCallable_Check(pmeth) == 0)
{
if (PyErr_Occurred())
{
PyErr_Clear();
}
Py_XDECREF(pmeth);
return ret_val;
}
if (PyErr_Occurred())
{
PyErr_Clear();
}
Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
if (py_return == Py_True)
ret_val = true;
Py_XDECREF(py_return);
return ret_val;
}
SWIGEXPORT bool
LLDBSwigPython_MightHaveChildrenSynthProviderInstance
(
PyObject *implementor
)
{
bool ret_val = false;
static char callee_name[] = "has_children";
PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_True);
if (py_return == Py_True)
ret_val = true;
Py_XDECREF(py_return);
return ret_val;
}
SWIGEXPORT void*