diff options
9 files changed, 229 insertions, 11 deletions
diff --git a/lldb/include/lldb/Interpreter/CommandObject.h b/lldb/include/lldb/Interpreter/CommandObject.h index bace3264daf..541a6ef7b5d 100644 --- a/lldb/include/lldb/Interpreter/CommandObject.h +++ b/lldb/include/lldb/Interpreter/CommandObject.h @@ -98,7 +98,7 @@ public: return m_interpreter; } - const char * + virtual const char * GetHelp (); virtual const char * @@ -114,6 +114,9 @@ public: SetHelp (const char * str); void + SetHelp (std::string str); + + void SetHelpLong (const char * str); void diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 213a300ed4d..386919e5e0b 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -614,6 +614,22 @@ public: } virtual bool + GetShortHelpForCommandObject (lldb::ScriptInterpreterObjectSP cmd_obj_sp, + std::string& dest) + { + dest.clear(); + return false; + } + + virtual bool + GetLongHelpForCommandObject (lldb::ScriptInterpreterObjectSP cmd_obj_sp, + std::string& dest) + { + dest.clear(); + return false; + } + + virtual bool CheckObjectExists (const char* name) { return false; diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h index a959d25c9e1..6dc03618900 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -214,6 +214,14 @@ public: GetDocumentationForItem (const char* item, std::string& dest) override; bool + GetShortHelpForCommandObject (lldb::ScriptInterpreterObjectSP cmd_obj_sp, + std::string& dest) override; + + bool + GetLongHelpForCommandObject (lldb::ScriptInterpreterObjectSP cmd_obj_sp, + std::string& dest) override ; + + bool CheckObjectExists (const char* name) override { if (!name || !name[0]) diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index febbfa87383..92e867022c4 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1435,6 +1435,8 @@ class CommandObjectScriptingObject : public CommandObjectRaw private: lldb::ScriptInterpreterObjectSP m_cmd_obj_sp; ScriptedCommandSynchronicity m_synchro; + bool m_fetched_help_short:1; + bool m_fetched_help_long:1; public: @@ -1447,7 +1449,9 @@ public: NULL, NULL), m_cmd_obj_sp(cmd_obj_sp), - m_synchro(synch) + m_synchro(synch), + m_fetched_help_short(false), + m_fetched_help_long(false) { StreamString stream; stream.Printf("For more information run 'help %s'",name.c_str()); @@ -1476,10 +1480,38 @@ public: { return m_synchro; } + + virtual const char * + GetHelp () + { + if (!m_fetched_help_short) + { + ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); + if (scripter) + { + std::string docstring; + m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring); + if (!docstring.empty()) + SetHelp(docstring); + } + } + return CommandObjectRaw::GetHelp(); + } virtual const char * GetHelpLong () { + if (!m_fetched_help_long) + { + ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); + if (scripter) + { + std::string docstring; + m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring); + if (!docstring.empty()) + SetHelpLong(docstring); + } + } return CommandObjectRaw::GetHelpLong(); } diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 021442ed63d..5de3e9da781 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -124,6 +124,12 @@ CommandObject::SetHelp (const char *cstr) } void +CommandObject::SetHelp (std::string str) +{ + m_cmd_help_short = str; +} + +void CommandObject::SetHelpLong (const char *cstr) { m_cmd_help_long = cstr; diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index aab837cc42a..4ef0bbefd54 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -2793,6 +2793,156 @@ ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& } } +bool +ScriptInterpreterPython::GetShortHelpForCommandObject (lldb::ScriptInterpreterObjectSP cmd_obj_sp, + std::string& dest) +{ + bool got_string = false; + dest.clear(); + + Locker py_lock (this, + Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + static char callee_name[] = "get_short_help"; + + if (!cmd_obj_sp) + return false; + + PyObject* implementor = (PyObject*)cmd_obj_sp->GetObject(); + + if (implementor == nullptr || implementor == Py_None) + return false; + + PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); + + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + if (pmeth == nullptr || pmeth == Py_None) + { + Py_XDECREF(pmeth); + return false; + } + + if (PyCallable_Check(pmeth) == 0) + { + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + Py_XDECREF(pmeth); + return false; + } + + 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, nullptr); + + // if it fails, print the error but otherwise go on + if (PyErr_Occurred()) + { + PyErr_Print(); + PyErr_Clear(); + } + + if (py_return != nullptr && py_return != Py_None) + { + if (PyString_Check(py_return)) + { + dest.assign(PyString_AsString(py_return)); + got_string = true; + } + } + Py_XDECREF(py_return); + + return got_string; +} + +bool +ScriptInterpreterPython::GetLongHelpForCommandObject (lldb::ScriptInterpreterObjectSP cmd_obj_sp, + std::string& dest) +{ + bool got_string = false; + dest.clear(); + + Locker py_lock (this, + Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + static char callee_name[] = "get_long_help"; + + if (!cmd_obj_sp) + return false; + + PyObject* implementor = (PyObject*)cmd_obj_sp->GetObject(); + + if (implementor == nullptr || implementor == Py_None) + return false; + + PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); + + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + if (pmeth == nullptr || pmeth == Py_None) + { + Py_XDECREF(pmeth); + return false; + } + + if (PyCallable_Check(pmeth) == 0) + { + if (PyErr_Occurred()) + { + PyErr_Clear(); + } + + Py_XDECREF(pmeth); + return false; + } + + 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, nullptr); + + // if it fails, print the error but otherwise go on + if (PyErr_Occurred()) + { + PyErr_Print(); + PyErr_Clear(); + } + + if (py_return != nullptr && py_return != Py_None) + { + if (PyString_Check(py_return)) + { + dest.assign(PyString_AsString(py_return)); + got_string = true; + } + } + Py_XDECREF(py_return); + + return got_string; +} + std::unique_ptr<ScriptInterpreterLocker> ScriptInterpreterPython::AcquireInterpreterLock () { diff --git a/lldb/test/functionalities/command_script/TestCommandScript.py b/lldb/test/functionalities/command_script/TestCommandScript.py index 9c1183aaa13..b7e466d2403 100644 --- a/lldb/test/functionalities/command_script/TestCommandScript.py +++ b/lldb/test/functionalities/command_script/TestCommandScript.py @@ -119,7 +119,7 @@ class CmdPythonTestCase(TestBase): self.runCmd("command script clear") # Test that re-defining an existing command works - self.runCmd('command script add my_command --function welcome.welcome_impl') + self.runCmd('command script add my_command --class welcome.WelcomeCommand') self.expect('my_command Blah', substrs = ['Hello Blah, welcome to LLDB']) self.runCmd('command script add my_command --function welcome.target_name_impl') diff --git a/lldb/test/functionalities/command_script/py_import b/lldb/test/functionalities/command_script/py_import index afc8c82340e..6150e0239c9 100644 --- a/lldb/test/functionalities/command_script/py_import +++ b/lldb/test/functionalities/command_script/py_import @@ -2,7 +2,7 @@ script import sys, os script sys.path.append(os.path.join(os.getcwd(), os.pardir)) script import welcome script import bug11569 -command script add welcome --function welcome.welcome_impl +command script add welcome --class welcome.WelcomeCommand command script add targetname --function welcome.target_name_impl command script add longwait --function welcome.print_wait_impl command script import mysto.py --allow-reload diff --git a/lldb/test/functionalities/command_script/welcome.py b/lldb/test/functionalities/command_script/welcome.py index c444934012f..90bd0b8f7a9 100644 --- a/lldb/test/functionalities/command_script/welcome.py +++ b/lldb/test/functionalities/command_script/welcome.py @@ -1,12 +1,15 @@ import sys -def welcome_impl(debugger, args, result, dict): - """ - Just a docstring for welcome_impl - A command that says hello to LLDB users - """ - print >>result, ('Hello ' + args + ', welcome to LLDB'); - return None; +class WelcomeCommand(object): + def __init__(self, debugger, session_dict): + pass + + def get_short_help(self): + return "Just a docstring for welcome_impl\nA command that says hello to LLDB users" + + def __call__(self, debugger, args, exe_ctx, result): + print >>result, ('Hello ' + args + ', welcome to LLDB'); + return None; def target_name_impl(debugger, args, result, dict): target = debugger.GetSelectedTarget() |