Skip to content

Commit 776dc6d

Browse files
committed
[lldb] Expose language plugin commands based based on language of current frame
1 parent cd6a614 commit 776dc6d

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

lldb/include/lldb/Interpreter/CommandInterpreter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,12 @@ class CommandInterpreter : public Broadcaster,
730730
bool EchoCommandNonInteractive(llvm::StringRef line,
731731
const Flags &io_handler_flags) const;
732732

733+
/// Return the language specific command object for the current frame.
734+
///
735+
/// For example, when stopped on a C++ frame, this returns the command object
736+
/// for "language cplusplus" (`CommandObjectMultiwordItaniumABI`).
737+
lldb::CommandObjectSP GetFrameLanguageCommand() const;
738+
733739
// A very simple state machine which models the command handling transitions
734740
enum class CommandHandlingState {
735741
eIdle,

lldb/source/Interpreter/CommandInterpreter.cpp

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,26 @@ CommandInterpreter::VerifyUserMultiwordCmdPath(Args &path, bool leaf_is_command,
10181018
return cur_as_multi;
10191019
}
10201020

1021+
CommandObjectSP CommandInterpreter::GetFrameLanguageCommand() const {
1022+
if (auto frame_sp = GetExecutionContext().GetFrameSP()) {
1023+
auto frame_language = Language::GetPrimaryLanguage(
1024+
frame_sp->GuessLanguage().AsLanguageType());
1025+
1026+
auto it = m_command_dict.find("language");
1027+
if (it != m_command_dict.end()) {
1028+
// The root "language" command.
1029+
CommandObjectSP language_cmd_sp = it->second;
1030+
1031+
if (auto *plugin = Language::FindPlugin(frame_language)) {
1032+
// "cplusplus", "objc", etc.
1033+
auto lang_name = plugin->GetPluginName();
1034+
return language_cmd_sp->GetSubcommandSPExact(lang_name);
1035+
}
1036+
}
1037+
}
1038+
return {};
1039+
}
1040+
10211041
CommandObjectSP
10221042
CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases,
10231043
bool exact, StringList *matches,
@@ -1050,11 +1070,20 @@ CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases,
10501070
command_sp = pos->second;
10511071
}
10521072

1073+
// The `language` subcommand ("language objc", "language cplusplus", etc).
1074+
CommandObjectMultiword *lang_subcmd = nullptr;
1075+
if (!command_sp) {
1076+
if (auto subcmd_sp = GetFrameLanguageCommand()) {
1077+
lang_subcmd = subcmd_sp->GetAsMultiwordCommand();
1078+
command_sp = subcmd_sp->GetSubcommandSPExact(cmd_str);
1079+
}
1080+
}
1081+
10531082
if (!exact && !command_sp) {
10541083
// We will only get into here if we didn't find any exact matches.
10551084

10561085
CommandObjectSP user_match_sp, user_mw_match_sp, alias_match_sp,
1057-
real_match_sp;
1086+
real_match_sp, lang_match_sp;
10581087

10591088
StringList local_matches;
10601089
if (matches == nullptr)
@@ -1064,6 +1093,7 @@ CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases,
10641093
unsigned int num_alias_matches = 0;
10651094
unsigned int num_user_matches = 0;
10661095
unsigned int num_user_mw_matches = 0;
1096+
unsigned int num_lang_matches = 0;
10671097

10681098
// Look through the command dictionaries one by one, and if we get only one
10691099
// match from any of them in toto, then return that, otherwise return an
@@ -1121,20 +1151,39 @@ CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases,
11211151
user_mw_match_sp = pos->second;
11221152
}
11231153

1154+
if (lang_subcmd) {
1155+
num_lang_matches =
1156+
AddNamesMatchingPartialString(lang_subcmd->GetSubcommandDictionary(),
1157+
cmd_str, *matches, descriptions);
1158+
}
1159+
1160+
if (num_lang_matches == 1) {
1161+
cmd.assign(matches->GetStringAtIndex(num_cmd_matches + num_alias_matches +
1162+
num_user_matches +
1163+
num_user_mw_matches));
1164+
1165+
auto &lang_dict = lang_subcmd->GetSubcommandDictionary();
1166+
auto pos = lang_dict.find(cmd);
1167+
if (pos != lang_dict.end())
1168+
lang_match_sp = pos->second;
1169+
}
1170+
11241171
// If we got exactly one match, return that, otherwise return the match
11251172
// list.
11261173

11271174
if (num_user_matches + num_user_mw_matches + num_cmd_matches +
1128-
num_alias_matches ==
1175+
num_alias_matches + num_lang_matches ==
11291176
1) {
11301177
if (num_cmd_matches)
11311178
return real_match_sp;
11321179
else if (num_alias_matches)
11331180
return alias_match_sp;
11341181
else if (num_user_mw_matches)
11351182
return user_mw_match_sp;
1136-
else
1183+
else if (num_user_matches)
11371184
return user_match_sp;
1185+
else
1186+
return lang_match_sp;
11381187
}
11391188
} else if (matches && command_sp) {
11401189
matches->AppendString(cmd_str);

0 commit comments

Comments
 (0)