Handle aliasing a non-top-level command.
authorJim Ingham <jingham@apple.com>
Wed, 9 Nov 2022 18:11:16 +0000 (10:11 -0800)
committerJim Ingham <jingham@apple.com>
Wed, 9 Nov 2022 18:11:16 +0000 (10:11 -0800)
This didn't work previously because we had to check whether the incoming
command was an alias command, but if it wasn't we still used the result
of that lookup - which was by the command's node name.  That fails for
non-top-level commands.  In this case, the resolution is pretty simple since
we already have the node's CommandObject, so all we needed to do was turn
it into a shared pointer, for which I added enable_shared_from_this to the
CommandObject.

Differential Revision: https://reviews.llvm.org/D137662

lldb/include/lldb/Interpreter/CommandObject.h
lldb/source/Commands/CommandObjectCommands.cpp
lldb/test/API/commands/command/container/TestContainerCommands.py

index ad5884e..fc058eb 100644 (file)
@@ -10,6 +10,7 @@
 #define LLDB_INTERPRETER_COMMANDOBJECT_H
 
 #include <map>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -64,7 +65,7 @@ size_t FindLongestCommandWord(std::map<std::string, ValueType> &dict) {
   return max_len;
 }
 
-class CommandObject {
+class CommandObject : public std::enable_shared_from_this<CommandObject> {
 public:
   typedef llvm::StringRef(ArgumentHelpCallbackFunction)();
 
index 3d4893d..9bf07f3 100644 (file)
@@ -485,29 +485,31 @@ protected:
         OptionArgVectorSP(new OptionArgVector);
 
     const bool include_aliases = true;
-    if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact(
-            cmd_obj.GetCommandName(), include_aliases)) {
-      if (m_interpreter.AliasExists(alias_command) ||
-          m_interpreter.UserCommandExists(alias_command)) {
-        result.AppendWarningWithFormat(
-            "Overwriting existing definition for '%s'.\n",
-            alias_command.str().c_str());
-      }
-      if (CommandAlias *alias = m_interpreter.AddAlias(
-              alias_command, cmd_obj_sp, raw_command_string)) {
-        if (m_command_options.m_help.OptionWasSet())
-          alias->SetHelp(m_command_options.m_help.GetCurrentValue());
-        if (m_command_options.m_long_help.OptionWasSet())
-          alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
-        result.SetStatus(eReturnStatusSuccessFinishNoResult);
-      } else {
-        result.AppendError("Unable to create requested alias.\n");
-      }
+    // Look up the command using command's name first.  This is to resolve
+    // aliases when you are making nested aliases.  But if you don't find
+    // it that way, then it wasn't an alias and we can just use the object
+    // we were passed in.
+    CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact(
+            cmd_obj.GetCommandName(), include_aliases);
+    if (!cmd_obj_sp)
+      cmd_obj_sp = cmd_obj.shared_from_this();
 
+    if (m_interpreter.AliasExists(alias_command) ||
+        m_interpreter.UserCommandExists(alias_command)) {
+      result.AppendWarningWithFormat(
+          "Overwriting existing definition for '%s'.\n",
+          alias_command.str().c_str());
+    }
+    if (CommandAlias *alias = m_interpreter.AddAlias(
+            alias_command, cmd_obj_sp, raw_command_string)) {
+      if (m_command_options.m_help.OptionWasSet())
+        alias->SetHelp(m_command_options.m_help.GetCurrentValue());
+      if (m_command_options.m_long_help.OptionWasSet())
+        alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
+      result.SetStatus(eReturnStatusSuccessFinishNoResult);
     } else {
       result.AppendError("Unable to create requested alias.\n");
     }
-
     return result.Succeeded();
   }
 
index 2267b35..76f981c 100644 (file)
@@ -55,6 +55,12 @@ class TestCmdContainer(TestBase):
         self.expect("test-multi test-multi-sub welcome friend", "Test command works",
                     substrs=["Hello friend, welcome to LLDB"])
 
+        # Make sure we can make an alias to this:
+        self.runCmd("command alias my-welcome test-multi test-multi-sub welcome", "We can make an alias to multi-word")
+        self.expect("my-welcome friend", "Test command works",
+                    substrs=["Hello friend, welcome to LLDB"])
+        self.runCmd("command unalias my-welcome")
+        
         # Make sure overwriting works on the leaf command.  First using the
         # explicit option so we should not be able to remove extant commands by default: