diff --git a/lldb/include/lldb/Utility/Stream.h b/lldb/include/lldb/Utility/Stream.h index 82774d56922a9..13455552131da 100644 --- a/lldb/include/lldb/Utility/Stream.h +++ b/lldb/include/lldb/Utility/Stream.h @@ -300,6 +300,12 @@ class Stream { /// The current indentation level. unsigned GetIndentLevel() const; + /// Set the current indentation level. + /// + /// \param[in] level + /// The new indentation level. + void SetIndentLevel(unsigned level); + /// Indent the current line in the stream. /// /// Indent the current line using the current indentation level and print an @@ -315,6 +321,20 @@ class Stream { /// Increment the current indentation level. void IndentMore(unsigned amount = 2); + struct IndentScope { + IndentScope(Stream &stream) + : m_stream(stream), m_original_indent_level(stream.GetIndentLevel()) {} + ~IndentScope() { m_stream.SetIndentLevel(m_original_indent_level); } + + private: + Stream &m_stream; + unsigned m_original_indent_level; + }; + + /// Create an indentation scope that restores the original indent level when + /// the object goes out of scope (RAII). + IndentScope MakeIndentScope(unsigned indent_amount = 2); + /// Output an offset value. /// /// Put an offset \a uval out to the stream using the printf format in \a @@ -364,12 +384,6 @@ class Stream { /// address and pointer values. void SetAddressByteSize(uint32_t addr_size); - /// Set the current indentation level. - /// - /// \param[in] level - /// The new indentation level. - void SetIndentLevel(unsigned level); - /// Output a SLEB128 number to the stream. /// /// Put an SLEB128 \a uval out to the stream using the printf format in \a diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index d070c3d953d4a..0f3b826fad95f 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -3961,9 +3961,7 @@ void Target::StopHook::GetDescription(Stream &s, return; } - unsigned indent_level = s.GetIndentLevel(); - - s.SetIndentLevel(indent_level + 2); + auto indent_scope = s.MakeIndentScope(); s.Printf("Hook: %" PRIu64 "\n", GetID()); if (m_active) @@ -3977,19 +3975,17 @@ void Target::StopHook::GetDescription(Stream &s, if (m_specifier_sp) { s.Indent(); s.PutCString("Specifier:\n"); - s.SetIndentLevel(indent_level + 4); + auto indent_scope = s.MakeIndentScope(); m_specifier_sp->GetDescription(&s, level); - s.SetIndentLevel(indent_level + 2); } if (m_thread_spec_up) { StreamString tmp; s.Indent("Thread:\n"); m_thread_spec_up->GetDescription(&tmp, level); - s.SetIndentLevel(indent_level + 4); + auto indent_scope = s.MakeIndentScope(); s.Indent(tmp.GetString()); s.PutCString("\n"); - s.SetIndentLevel(indent_level + 2); } GetSubclassDescription(s, level); } @@ -4002,14 +3998,13 @@ void Target::StopHookCommandLine::GetSubclassDescription( s.PutCString(m_commands.GetStringAtIndex(0)); return; } - s.Indent("Commands: \n"); - s.SetIndentLevel(s.GetIndentLevel() + 4); + s.Indent("Commands:\n"); + auto indent_scope = s.MakeIndentScope(4); uint32_t num_commands = m_commands.GetSize(); for (uint32_t i = 0; i < num_commands; i++) { s.Indent(m_commands.GetStringAtIndex(i)); s.PutCString("\n"); } - s.SetIndentLevel(s.GetIndentLevel() - 4); } // Target::StopHookCommandLine @@ -4144,7 +4139,7 @@ void Target::StopHookScripted::GetSubclassDescription( return; s.Indent("Args:\n"); - s.SetIndentLevel(s.GetIndentLevel() + 4); + auto indent_scope = s.MakeIndentScope(4); auto print_one_element = [&s](llvm::StringRef key, StructuredData::Object *object) { @@ -4154,8 +4149,6 @@ void Target::StopHookScripted::GetSubclassDescription( }; as_dict->ForEach(print_one_element); - - s.SetIndentLevel(s.GetIndentLevel() - 4); } static constexpr OptionEnumValueElement g_dynamic_value_types[] = { diff --git a/lldb/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp index 89dce9fb0e1f7..e9632c3e1fc1f 100644 --- a/lldb/source/Utility/Stream.cpp +++ b/lldb/source/Utility/Stream.cpp @@ -202,6 +202,14 @@ void Stream::IndentLess(unsigned amount) { m_indent_level = 0; } +// Create an indentation scope that restores the original indent level when the +// object goes out of scope (RAII). +Stream::IndentScope Stream::MakeIndentScope(unsigned indent_amount) { + IndentScope indent_scope(*this); + IndentMore(indent_amount); + return indent_scope; +} + // Get the address size in bytes uint32_t Stream::GetAddressByteSize() const { return m_addr_size; } diff --git a/lldb/test/Shell/ExecControl/StopHook/stop-hook-list-format.test b/lldb/test/Shell/ExecControl/StopHook/stop-hook-list-format.test new file mode 100644 index 0000000000000..a9557801cc134 --- /dev/null +++ b/lldb/test/Shell/ExecControl/StopHook/stop-hook-list-format.test @@ -0,0 +1,36 @@ +# Test format (e.g., indentation) when printing the list of stop hooks. +# +# RUN: %lldb -b -s %s | FileCheck %s --match-full-lines --strict-whitespace + +# Create some stop hooks +target stop-hook add -o 'print "Hello"' --auto-continue true --at-initial-stop true +target stop-hook add -o 'print "world,"' -o 'print "nice"' --file 'my_file' +target stop-hook add -o 'print "weather!"' --classname 'MyClass' --thread-name 'my_thread' + +# Print hooks +target stop-hook list + +# CHECK:(lldb) target stop-hook list +# CHECK:Hook: 1 +# CHECK: State: enabled +# CHECK: AutoContinue on +# CHECK: Commands: +# CHECK: print "Hello" +# CHECK-EMPTY: +# CHECK:Hook: 2 +# CHECK: State: enabled +# CHECK: Specifier: +# CHECK: File: my_file. +# CHECK: Commands: +# CHECK: print "world," +# CHECK: print "nice" +# CHECK-EMPTY: +# CHECK:Hook: 3 +# CHECK: State: enabled +# CHECK: Specifier: +# CHECK: Class name: MyClass. +# CHECK: Thread: +# CHECK: thread name: "my_thread" +# CHECK: Commands: +# CHECK: print "weather!" +# CHECK-EMPTY: