diff --git a/lldb/bindings/interface/SBCommandInterpreter.i b/lldb/bindings/interface/SBCommandInterpreter.i --- a/lldb/bindings/interface/SBCommandInterpreter.i +++ b/lldb/bindings/interface/SBCommandInterpreter.i @@ -169,6 +169,9 @@ bool CommandExists (const char *cmd); + bool + UserCommandExists (const char *cmd); + bool AliasExists (const char *cmd); diff --git a/lldb/include/lldb/API/SBCommandInterpreter.h b/lldb/include/lldb/API/SBCommandInterpreter.h --- a/lldb/include/lldb/API/SBCommandInterpreter.h +++ b/lldb/include/lldb/API/SBCommandInterpreter.h @@ -91,8 +91,28 @@ bool IsValid() const; + /// Determine whether a command exists in this CommandInterpreter. + /// + /// For commands registered using the LLDB API, see UserCommandExists + /// + /// \param[in] cmd + /// The command to look up. + /// + /// \return + /// \b true if the provided command exists, \b false otherwise. bool CommandExists(const char *cmd); + /// Determine whether a user command exists in this CommandInterpreter. + /// Users commands are the ones registered using the LLDB API and are not + /// provided by default in LLDB. + /// + /// \param[in] cmd + /// The command to look up. + /// + /// \return + /// \b true if the provided command exists, \b false otherwise. + bool UserCommandExists(const char *cmd); + bool AliasExists(const char *cmd); lldb::SBBroadcaster GetBroadcaster(); diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -216,6 +216,14 @@ : false); } +bool SBCommandInterpreter::UserCommandExists(const char *cmd) { + LLDB_RECORD_METHOD(bool, SBCommandInterpreter, UserCommandExists, + (const char *), cmd); + + return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->UserCommandExists(cmd) + : false); +} + bool SBCommandInterpreter::AliasExists(const char *cmd) { LLDB_RECORD_METHOD(bool, SBCommandInterpreter, AliasExists, (const char *), cmd); @@ -874,6 +882,8 @@ LLDB_REGISTER_METHOD_CONST(bool, SBCommandInterpreter, operator bool, ()); LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, CommandExists, (const char *)); + LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, UserCommandExists, + (const char *)); LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, AliasExists, (const char *)); LLDB_REGISTER_METHOD(bool, SBCommandInterpreter, IsActive, ()); diff --git a/lldb/unittests/Interpreter/CMakeLists.txt b/lldb/unittests/Interpreter/CMakeLists.txt --- a/lldb/unittests/Interpreter/CMakeLists.txt +++ b/lldb/unittests/Interpreter/CMakeLists.txt @@ -1,8 +1,10 @@ add_lldb_unittest(InterpreterTests TestCompletion.cpp TestOptionArgParser.cpp + TestUserCommand.cpp LINK_LIBS + liblldb lldbInterpreter lldbUtilityHelpers ) diff --git a/lldb/unittests/Interpreter/TestUserCommand.cpp b/lldb/unittests/Interpreter/TestUserCommand.cpp new file mode 100644 --- /dev/null +++ b/lldb/unittests/Interpreter/TestUserCommand.cpp @@ -0,0 +1,45 @@ +//===-- TestUserCommand.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===/ + +#include "gtest/gtest.h" + +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBDebugger.h" + +#include +#include +#include + +using namespace lldb; + +class DummyCommand : public SBCommandPluginInterface { +public: + bool DoExecute(SBDebugger dbg, char **command, + SBCommandReturnObject &result) { + result.PutCString("It works"); + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } +}; + +TEST(TestUserCommand, TestSimpleCommand) { + SBDebugger::Initialize(); + SBDebugger dbg = SBDebugger::Create(false /*source_init_files*/); + SBCommandInterpreter interp = dbg.GetCommandInterpreter(); + + DummyCommand command; + interp.AddCommand("dummy", &command, nullptr /*help*/); + + EXPECT_TRUE(interp.UserCommandExists("dummy")); + + SBCommandReturnObject result; + interp.HandleCommand("dummy", result, true /*add_to_history*/); + EXPECT_TRUE(result.Succeeded()); + EXPECT_STREQ(result.GetOutput(), "It works\n"); +}