Skip to content

Commit 5656cdd

Browse files
committed
[lldb][Format] Add new function basename highlight option to FormatEntity
1 parent 842c4ff commit 5656cdd

File tree

6 files changed

+135
-18
lines changed

6 files changed

+135
-18
lines changed

lldb/include/lldb/Core/FormatEntity.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,29 @@ struct Entry {
197197
return true;
198198
}
199199

200+
struct HighlightSettings {
201+
std::string prefix;
202+
std::string suffix;
203+
204+
enum class Kind : uint8_t {
205+
///< Don't highlight.
206+
None,
207+
208+
///< Highlight function basename
209+
///< (i.e., name without Scope and
210+
///< without template arguments).
211+
Basename,
212+
} kind = Kind::None;
213+
};
214+
200215
std::string string;
201216
std::string printf_format;
202217
std::vector<Entry> children;
203218
Type type;
204219
lldb::Format fmt = lldb::eFormatDefault;
205220
lldb::addr_t number = 0;
206221
bool deref = false;
222+
HighlightSettings highlight;
207223
};
208224

209225
bool Format(const Entry &entry, Stream &s, const SymbolContext *sc,

lldb/include/lldb/Target/Language.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,11 @@ class Language : public PluginInterface {
268268
// the reference has never been assigned
269269
virtual bool IsUninitializedReference(ValueObject &valobj);
270270

271-
virtual bool GetFunctionDisplayName(const SymbolContext *sc,
272-
const ExecutionContext *exe_ctx,
273-
FunctionNameRepresentation representation,
274-
Stream &s);
271+
virtual bool
272+
GetFunctionDisplayName(const SymbolContext *sc,
273+
const ExecutionContext *exe_ctx,
274+
FunctionNameRepresentation representation, Stream &s,
275+
const FormatEntity::Entry::HighlightSettings &);
275276

276277
virtual ConstString
277278
GetDemangledFunctionNameWithoutArguments(Mangled mangled) const {

lldb/source/Core/FormatEntity.cpp

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,7 +1654,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
16541654

16551655
if (language_plugin)
16561656
language_plugin_handled = language_plugin->GetFunctionDisplayName(
1657-
sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss);
1657+
sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss,
1658+
entry.highlight);
16581659

16591660
if (language_plugin_handled) {
16601661
s << ss.GetString();
@@ -1690,7 +1691,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
16901691
if (language_plugin)
16911692
language_plugin_handled = language_plugin->GetFunctionDisplayName(
16921693
sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs,
1693-
ss);
1694+
ss, entry.highlight);
16941695

16951696
if (language_plugin_handled) {
16961697
s << ss.GetString();
@@ -1724,7 +1725,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
17241725

17251726
if (language_plugin)
17261727
language_plugin_handled = language_plugin->GetFunctionDisplayName(
1727-
sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss);
1728+
sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss,
1729+
entry.highlight);
17281730

17291731
if (language_plugin_handled) {
17301732
s << ss.GetString();
@@ -2046,6 +2048,54 @@ static const Definition *FindEntry(const llvm::StringRef &format_str,
20462048
return parent;
20472049
}
20482050

2051+
static llvm::Expected<Entry::HighlightSettings>
2052+
ParseHighlightSettings(const Entry &entry) {
2053+
// FIXME: support other function.name-XXX types as well
2054+
if (entry.type != Entry::Type::FunctionNameWithArgs)
2055+
return llvm::createStringError(
2056+
"The 'highlight_basename' format can only be used on "
2057+
"${function.name-with-args}");
2058+
2059+
llvm::StringRef format = entry.printf_format;
2060+
if (!format.consume_front("highlight_"))
2061+
return llvm::createStringError(
2062+
"Expected 'highlight_' prefix not found in: %s.",
2063+
entry.printf_format.c_str());
2064+
2065+
Entry::HighlightSettings settings;
2066+
if (format.consume_front("basename")) {
2067+
settings.kind = Entry::HighlightSettings::Kind::Basename;
2068+
} else {
2069+
return llvm::createStringError(
2070+
"Unsupported highlight kind detected in: %s. "
2071+
"Currently supported: basename",
2072+
entry.printf_format.c_str());
2073+
}
2074+
2075+
llvm::SmallVector<llvm::StringRef, 1> matches;
2076+
// TODO: support ${ansi.XXX} syntax. ExtractVariableInfo needs
2077+
// to be adjusted to support nested '{}'.
2078+
llvm::Regex color_pattern{R"(^\(([a-z\.]+)\)$)"};
2079+
if (!color_pattern.match(format, &matches))
2080+
return llvm::createStringError("Couldn't find valid color variable in: %s. "
2081+
"Expected format: (ansi.some-color)",
2082+
entry.printf_format.c_str());
2083+
2084+
assert(matches.size() == 2);
2085+
2086+
std::string color_format = ("${" + matches[1] + "}").str();
2087+
std::string terminal_code = ansi::FormatAnsiTerminalCodes(color_format);
2088+
if (terminal_code.empty())
2089+
return llvm::createStringError("Invalid color variable '%s' found in: %s",
2090+
color_format.c_str(),
2091+
entry.printf_format.c_str());
2092+
2093+
settings.prefix = std::move(terminal_code);
2094+
settings.suffix = ansi::FormatAnsiTerminalCodes("${ansi.normal}");
2095+
2096+
return settings;
2097+
}
2098+
20492099
static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
20502100
uint32_t depth) {
20512101
Status error;
@@ -2201,6 +2251,7 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
22012251
if (error.Fail())
22022252
return error;
22032253
bool verify_is_thread_id = false;
2254+
bool parse_highlight_settings = false;
22042255
Entry entry;
22052256
if (!variable_format.empty()) {
22062257
entry.printf_format = variable_format.str();
@@ -2266,6 +2317,8 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
22662317
clear_printf = true;
22672318
} else if (entry.printf_format == "tid") {
22682319
verify_is_thread_id = true;
2320+
} else if (entry.printf_format.find("highlight_") == 0) {
2321+
parse_highlight_settings = true;
22692322
} else {
22702323
error = Status::FromErrorStringWithFormat(
22712324
"invalid format: '%s'", entry.printf_format.c_str());
@@ -2307,6 +2360,14 @@ static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
23072360
"the 'tid' format can only be used on "
23082361
"${thread.id} and ${thread.protocol_id}");
23092362
}
2363+
} else if (parse_highlight_settings) {
2364+
auto highlight_or_err = ParseHighlightSettings(entry);
2365+
if (highlight_or_err) {
2366+
entry.highlight = std::move(*highlight_or_err);
2367+
entry.printf_format.clear();
2368+
} else {
2369+
error = Status::FromError(highlight_or_err.takeError());
2370+
}
23102371
}
23112372

23122373
switch (entry.type) {

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ static bool IsTrivialBasename(const llvm::StringRef &basename) {
178178
/// but replaces each argument type with the variable name
179179
/// and the corresponding pretty-printed value
180180
static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream,
181-
char const *full_name,
181+
llvm::StringRef full_name,
182182
ExecutionContextScope *exe_scope,
183183
VariableList const &args) {
184184
CPlusPlusLanguage::MethodName cpp_method{ConstString(full_name)};
@@ -208,6 +208,41 @@ static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream,
208208
return true;
209209
}
210210

211+
static bool PrettyPrintFunctionNameWithArgs(
212+
Stream &out_stream, llvm::StringRef full_name,
213+
ExecutionContextScope *exe_scope, VariableList const &args,
214+
const Mangled::DemangledInfo &demangled_info,
215+
const FormatEntity::Entry::HighlightSettings &settings) {
216+
if (settings.kind == FormatEntity::Entry::HighlightSettings::Kind::None ||
217+
!demangled_info.hasBasename())
218+
return PrettyPrintFunctionNameWithArgs(out_stream, full_name, exe_scope,
219+
args);
220+
221+
auto [base_start, base_end] = demangled_info.BasenameLocs;
222+
223+
// Dump anything before the basename.
224+
out_stream.PutCString(full_name.substr(0, base_start));
225+
226+
// Highlight the basename.
227+
out_stream.PutCString(settings.prefix);
228+
out_stream.PutCString(full_name.substr(base_start, base_end - base_start));
229+
out_stream.PutCString(settings.suffix);
230+
231+
// Dump anything between the basename and the argument list.
232+
if (demangled_info.ArgumentLocs.first > base_end)
233+
out_stream.PutCString(full_name.substr(base_end, demangled_info.ArgumentLocs.first - base_end));
234+
235+
// Dump arguments.
236+
out_stream.PutChar('(');
237+
FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);
238+
out_stream.PutChar(')');
239+
240+
// Dump anything after the argument list.
241+
out_stream.PutCString(full_name.substr(demangled_info.ArgumentLocs.second));
242+
243+
return true;
244+
}
245+
211246
bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
212247
// This method tries to parse simple method definitions which are presumably
213248
// most comman in user programs. Definitions that can be parsed by this
@@ -1699,7 +1734,8 @@ bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
16991734

17001735
bool CPlusPlusLanguage::GetFunctionDisplayName(
17011736
const SymbolContext *sc, const ExecutionContext *exe_ctx,
1702-
FunctionNameRepresentation representation, Stream &s) {
1737+
FunctionNameRepresentation representation, Stream &s,
1738+
const FormatEntity::Entry::HighlightSettings &settings) {
17031739
switch (representation) {
17041740
case FunctionNameRepresentation::eNameWithArgs: {
17051741
// Print the function name with arguments in it
@@ -1738,7 +1774,9 @@ bool CPlusPlusLanguage::GetFunctionDisplayName(
17381774
variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
17391775
args);
17401776
if (args.GetSize() > 0) {
1741-
if (!PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args))
1777+
if (!PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args,
1778+
sc->function->GetDemangledInfo(),
1779+
settings))
17421780
return false;
17431781
} else {
17441782
s.PutCString(cstr);

lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/ADT/StringRef.h"
1616

1717
#include "Plugins/Language/ClangCommon/ClangHighlighter.h"
18+
#include "lldb/Core/FormatEntity.h"
1819
#include "lldb/Target/Language.h"
1920
#include "lldb/Utility/ConstString.h"
2021
#include "lldb/lldb-private.h"
@@ -138,10 +139,10 @@ class CPlusPlusLanguage : public Language {
138139
ConstString
139140
GetDemangledFunctionNameWithoutArguments(Mangled mangled) const override;
140141

141-
bool GetFunctionDisplayName(const SymbolContext *sc,
142-
const ExecutionContext *exe_ctx,
143-
FunctionNameRepresentation representation,
144-
Stream &s) override;
142+
bool GetFunctionDisplayName(
143+
const SymbolContext *sc, const ExecutionContext *exe_ctx,
144+
FunctionNameRepresentation representation, Stream &s,
145+
const FormatEntity::Entry::HighlightSettings &) override;
145146

146147
static bool IsCPPMangledName(llvm::StringRef name);
147148

lldb/source/Target/Language.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,10 +510,10 @@ bool Language::IsNilReference(ValueObject &valobj) { return false; }
510510

511511
bool Language::IsUninitializedReference(ValueObject &valobj) { return false; }
512512

513-
bool Language::GetFunctionDisplayName(const SymbolContext *sc,
514-
const ExecutionContext *exe_ctx,
515-
FunctionNameRepresentation representation,
516-
Stream &s) {
513+
bool Language::GetFunctionDisplayName(
514+
const SymbolContext *sc, const ExecutionContext *exe_ctx,
515+
FunctionNameRepresentation representation, Stream &s,
516+
const FormatEntity::Entry::HighlightSettings &) {
517517
return false;
518518
}
519519

0 commit comments

Comments
 (0)