From 00626f57883cf0fdbbc0ede5a45bffeb536530ad Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sat, 2 Nov 2024 08:52:32 -0700 Subject: [PATCH 1/2] [lldb] Highlight "note:" in CommandReturnObject (#114610) We have helpers to emit warnings and errors. Do the same thing for notes to they stand out more. (cherry picked from commit 79178ca689a8259d19d93320a6299e3d31383ac4) --- .../lldb/Interpreter/CommandReturnObject.h | 10 ++++++++ .../Commands/CommandObjectDWIMPrint.cpp | 15 ++++++------ .../Interpreter/CommandReturnObject.cpp | 24 +++++++++++++++++++ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index d162a31ca585f..5cd5e4aff1feb 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -117,6 +117,11 @@ class CommandReturnObject { void AppendMessageWithFormat(const char *format, ...) __attribute__((format(printf, 2, 3))); + void AppendNote(llvm::StringRef in_string); + + void AppendNoteWithFormat(const char *format, ...) + __attribute__((format(printf, 2, 3))); + void AppendWarning(llvm::StringRef in_string); void AppendWarningWithFormat(const char *format, ...) @@ -134,6 +139,11 @@ class CommandReturnObject { AppendMessage(llvm::formatv(format, std::forward(args)...).str()); } + template + void AppendNoteWithFormatv(const char *format, Args &&...args) { + AppendNote(llvm::formatv(format, std::forward(args)...).str()); + } + template void AppendWarningWithFormatv(const char *format, Args &&... args) { AppendWarning(llvm::formatv(format, std::forward(args)...).str()); diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index 2f8bc24045159..ae7b56ea1e8ab 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -123,10 +123,10 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, if (note_shown) return; - result.GetOutputStream() - << "note: object description requested, but type doesn't implement " - "a custom object description. Consider using \"p\" instead of " - "\"po\" (this note will only be shown once per debug session).\n"; + result.AppendNote( + "object description requested, but type doesn't implement " + "a custom object description. Consider using \"p\" instead of " + "\"po\" (this note will only be shown once per debug session).\n"); note_shown = true; } }; @@ -180,8 +180,8 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, StringRef flags; if (args.HasArgs()) flags = args.GetArgString(); - result.AppendMessageWithFormatv("note: ran `frame variable {0}{1}`", - flags, expr); + result.AppendNoteWithFormatv("ran `frame variable {0}{1}`", flags, + expr); } dump_val_object(*valobj_sp); @@ -280,8 +280,7 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, StringRef flags; if (args.HasArgs()) flags = args.GetArgStringWithDelimiter(); - result.AppendMessageWithFormatv("note: ran `expression {0}{1}`", flags, - expr); + result.AppendNoteWithFormatv("ran `expression {0}{1}`", flags, expr); } if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp index 3cc718511606b..0a2948e8e6ca4 100644 --- a/lldb/source/Interpreter/CommandReturnObject.cpp +++ b/lldb/source/Interpreter/CommandReturnObject.cpp @@ -27,6 +27,12 @@ static llvm::raw_ostream &warning(Stream &strm) { << "warning: "; } +static llvm::raw_ostream ¬e(Stream &strm) { + return llvm::WithColor(strm.AsRawOstream(), llvm::HighlightColor::Note, + llvm::ColorMode::Enable) + << "note: "; +} + static void DumpStringToStreamWithNewline(Stream &strm, const std::string &s) { bool add_newline = false; if (!s.empty()) { @@ -74,6 +80,18 @@ void CommandReturnObject::AppendMessageWithFormat(const char *format, ...) { GetOutputStream() << sstrm.GetString(); } +void CommandReturnObject::AppendNoteWithFormat(const char *format, ...) { + if (!format) + return; + va_list args; + va_start(args, format); + StreamString sstrm; + sstrm.PrintfVarArg(format, args); + va_end(args); + + note(GetOutputStream()) << sstrm.GetString(); +} + void CommandReturnObject::AppendWarningWithFormat(const char *format, ...) { if (!format) return; @@ -92,6 +110,12 @@ void CommandReturnObject::AppendMessage(llvm::StringRef in_string) { GetOutputStream() << in_string.rtrim() << '\n'; } +void CommandReturnObject::AppendNote(llvm::StringRef in_string) { + if (in_string.empty()) + return; + note(GetOutputStream()) << in_string.rtrim() << '\n'; +} + void CommandReturnObject::AppendWarning(llvm::StringRef in_string) { if (in_string.empty()) return; From 3f25aa8efc1520c7689f40c906faf9ea0671a4c7 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 7 Mar 2025 21:57:05 -0800 Subject: [PATCH 2/2] [lldb] Avoid unnecessary regex check in dwim-print (#114608) An (unmeasured) improvement to performance of `dwim-print` when used as `po`. This change lifts the check for `note_shown` to the top of the lambda, to avoid all subsequent work when the hint has already been shown. The main effect is to avoid performing a regex match when the hint is not going to be shown. This change also constructs the `std::regex` only once, by making it static. (cherry picked from commit 61efe360f9ba70736ca27ad289277c5c8268ffc0) --- lldb/source/Commands/CommandObjectDWIMPrint.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index ae7b56ea1e8ab..0778ab7f68f90 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -103,6 +103,10 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, // Add a hint if object description was requested, but no description // function was implemented. auto maybe_add_hint = [&](llvm::StringRef output) { + static bool note_shown = false; + if (note_shown) + return; + // Identify the default output of object description for Swift and // Objective-C // ". The regex is: @@ -112,17 +116,14 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, // - Followed by 5 or more hex digits. // - Followed by ">". // - End with zero or more whitespace characters. - const std::regex swift_class_regex("^<\\S+: 0x[[:xdigit:]]{5,}>\\s*$"); + static const std::regex swift_class_regex( + "^<\\S+: 0x[[:xdigit:]]{5,}>\\s*$"); if (GetDebugger().GetShowDontUsePoHint() && target_ptr && (language == lldb::eLanguageTypeSwift || language == lldb::eLanguageTypeObjC) && std::regex_match(output.data(), swift_class_regex)) { - static bool note_shown = false; - if (note_shown) - return; - result.AppendNote( "object description requested, but type doesn't implement " "a custom object description. Consider using \"p\" instead of "