diff --git a/lldb/bindings/headers.swig b/lldb/bindings/headers.swig index c0dde905f986b..5e7c54d1eb839 100644 --- a/lldb/bindings/headers.swig +++ b/lldb/bindings/headers.swig @@ -52,6 +52,7 @@ #include "lldb/API/SBProcess.h" #include "lldb/API/SBProcessInfo.h" #include "lldb/API/SBProcessInfoList.h" +#include "lldb/API/SBProgress.h" #include "lldb/API/SBQueue.h" #include "lldb/API/SBQueueItem.h" #include "lldb/API/SBReproducer.h" diff --git a/lldb/bindings/interface/SBProgressDocstrings.i b/lldb/bindings/interface/SBProgressDocstrings.i new file mode 100644 index 0000000000000..2997fe619fcc7 --- /dev/null +++ b/lldb/bindings/interface/SBProgressDocstrings.i @@ -0,0 +1,14 @@ +%feature("docstring", +"A Progress indicator helper class. + +Any potentially long running sections of code in LLDB should report +progress so that clients are aware of delays that might appear during +debugging. Delays commonly include indexing debug information, parsing +symbol tables for object files, downloading symbols from remote +repositories, and many more things. + +The Progress class helps make sure that progress is correctly reported +and will always send an initial progress update, updates when +Progress::Increment() is called, and also will make sure that a progress +completed update is reported even if the user doesn't explicitly cause one +to be sent.") lldb::SBProgress; diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig index 8a6fed95f0b72..08df9a1a8d539 100644 --- a/lldb/bindings/interfaces.swig +++ b/lldb/bindings/interfaces.swig @@ -54,6 +54,7 @@ %include "./interface/SBPlatformDocstrings.i" %include "./interface/SBProcessDocstrings.i" %include "./interface/SBProcessInfoDocstrings.i" +%include "./interface/SBProgressDocstrings.i" %include "./interface/SBQueueDocstrings.i" %include "./interface/SBQueueItemDocstrings.i" %include "./interface/SBReproducerDocstrings.i" @@ -133,6 +134,7 @@ %include "lldb/API/SBProcess.h" %include "lldb/API/SBProcessInfo.h" %include "lldb/API/SBProcessInfoList.h" +%include "lldb/API/SBProgress.h" %include "lldb/API/SBQueue.h" %include "lldb/API/SBQueueItem.h" %include "lldb/API/SBReproducer.h" diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 787bd040dd15b..eb371e33c4951 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -203,7 +203,7 @@ class LLDB_API SBDebugger { lldb::SBCommandInterpreter GetCommandInterpreter(); void HandleCommand(const char *command); - + void RequestInterrupt(); void CancelInterruptRequest(); bool InterruptRequested(); @@ -517,6 +517,7 @@ class LLDB_API SBDebugger { friend class SBPlatform; friend class SBTarget; friend class SBTrace; + friend class SBProgress; lldb::SBTarget FindTargetWithLLDBProcess(const lldb::ProcessSP &processSP); diff --git a/lldb/include/lldb/API/SBProgress.h b/lldb/include/lldb/API/SBProgress.h new file mode 100644 index 0000000000000..d2eaf0a743cb3 --- /dev/null +++ b/lldb/include/lldb/API/SBProgress.h @@ -0,0 +1,66 @@ +//===-- SBProgress.h --------------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_API_SBPROGRESS_H +#define LLDB_API_SBPROGRESS_H + +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBDefines.h" + +namespace lldb { + +/// A Progress indicator helper class. +/// +/// Any potentially long running sections of code in LLDB should report +/// progress so that clients are aware of delays that might appear during +/// debugging. Delays commonly include indexing debug information, parsing +/// symbol tables for object files, downloading symbols from remote +/// repositories, and many more things. +/// +/// The Progress class helps make sure that progress is correctly reported +/// and will always send an initial progress update, updates when +/// Progress::Increment() is called, and also will make sure that a progress +/// completed update is reported even if the user doesn't explicitly cause one +/// to be sent. +class LLDB_API SBProgress { +public: + /// Construct a progress object with a title, details and a given debugger. + /// \param title + /// The title of the progress object. + /// \param details + /// The details of the progress object. + /// \param debugger + /// The debugger for this progress object to report to. + SBProgress(const char *title, const char *details, SBDebugger &debugger); + + /// Construct a progress object with a title, details, the total units of work + /// to be done, and a given debugger. + /// \param title + /// The title of the progress object. + /// \param details + /// The details of the progress object. + /// \param total_units + /// The total number of units of work to be done. + /// \param debugger + /// The debugger for this progress object to report to. + SBProgress(const char *title, const char *details, uint64_t total_units, + SBDebugger &debugger); + + ~SBProgress(); + + void Increment(uint64_t amount, const char *description = nullptr); + +protected: + lldb_private::Progress &ref() const; + +private: + std::unique_ptr m_opaque_up; +}; // SBProgress +} // namespace lldb + +#endif // LLDB_API_SBPROGRESS_H diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index d09edeeccaff1..fc7456a4b9a32 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -233,6 +233,7 @@ class Symtab; class SyntheticChildren; class SyntheticChildrenFrontEnd; class SystemRuntime; +class Progress; class Target; class TargetList; class TargetProperties; diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index d8308841c05db..147b30f3b0026 100644 --- a/lldb/source/API/CMakeLists.txt +++ b/lldb/source/API/CMakeLists.txt @@ -83,6 +83,7 @@ add_lldb_library(liblldb SHARED ${option_framework} SBModule.cpp SBModuleSpec.cpp SBPlatform.cpp + SBProgress.cpp SBProcess.cpp SBProcessInfo.cpp SBProcessInfoList.cpp diff --git a/lldb/source/API/SBProgress.cpp b/lldb/source/API/SBProgress.cpp new file mode 100644 index 0000000000000..d6ed5f0d15fc9 --- /dev/null +++ b/lldb/source/API/SBProgress.cpp @@ -0,0 +1,43 @@ +//===-- SBProgress.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 "lldb/API/SBProgress.h" +#include "lldb/Core/Progress.h" +#include "lldb/Utility/Instrumentation.h" + +using namespace lldb; + +SBProgress::SBProgress(const char *title, const char *details, + SBDebugger &debugger) { + LLDB_INSTRUMENT_VA(this, title, details, debugger); + + m_opaque_up = std::make_unique( + title, details, /*total=*/std::nullopt, debugger.get(), + /*minimum_report_time=*/std::nullopt, + lldb_private::Progress::Origin::eExternal); +} + +SBProgress::SBProgress(const char *title, const char *details, + uint64_t total_units, SBDebugger &debugger) { + LLDB_INSTRUMENT_VA(this, title, details, total_units, debugger); + + m_opaque_up = std::make_unique( + title, details, total_units, debugger.get(), + /*minimum_report_time=*/std::nullopt, + lldb_private::Progress::Origin::eExternal); +} + +SBProgress::~SBProgress() = default; + +void SBProgress::Increment(uint64_t amount, const char *description) { + LLDB_INSTRUMENT_VA(amount, description); + + m_opaque_up->Increment(amount, description); +} + +lldb_private::Progress &SBProgress::ref() const { return *m_opaque_up; } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 6ceb209269c9e..2df2aeb20aa26 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1952,7 +1952,8 @@ lldb::thread_result_t Debugger::DefaultEventHandler() { listener_sp->StartListeningForEvents( &m_broadcaster, lldb::eBroadcastBitProgress | lldb::eBroadcastBitWarning | lldb::eBroadcastBitError | - lldb::eBroadcastSymbolChange); + lldb::eBroadcastSymbolChange | + lldb::eBroadcastBitExternalProgress); // Let the thread that spawned us know that we have started up and that we // are now listening to all required events so no events get missed diff --git a/lldb/test/API/python_api/sbprogress/TestSBProgress.py b/lldb/test/API/python_api/sbprogress/TestSBProgress.py new file mode 100644 index 0000000000000..c456247da80c6 --- /dev/null +++ b/lldb/test/API/python_api/sbprogress/TestSBProgress.py @@ -0,0 +1,35 @@ +"""Test the SBProgress API.""" + +import lldb +from lldbsuite.test.lldbtest import * + + +class SBProgressTestCase(TestBase): + def test_with_external_bit_set(self): + """Test SBProgress events are listened to when the external bit is set.""" + + progress = lldb.SBProgress("Test SBProgress", "Test progress", self.dbg) + listener = lldb.SBListener("Test listener") + broadcaster = self.dbg.GetBroadcaster() + broadcaster.AddListener(listener, lldb.eBroadcastBitExternalProgress) + event = lldb.SBEvent() + + expected_string = "Test progress first increment" + progress.Increment(1, expected_string) + self.assertTrue(listener.PeekAtNextEvent(event)) + stream = lldb.SBStream() + event.GetDescription(stream) + self.assertIn(expected_string, stream.GetData()) + + def test_without_external_bit_set(self): + """Test SBProgress events are not listened to on the internal progress bit.""" + + progress = lldb.SBProgress("Test SBProgress", "Test progress", self.dbg) + listener = lldb.SBListener("Test listener") + broadcaster = self.dbg.GetBroadcaster() + broadcaster.AddListener(listener, lldb.eBroadcastBitProgress) + event = lldb.SBEvent() + + expected_string = "Test progress first increment" + progress.Increment(1, expected_string) + self.assertFalse(listener.PeekAtNextEvent(event))