[Lldb-commits] [lldb] r181850 - A first pass at auto completion for variables and their children. This is currently hooked up for "frame variable" only. With a little work we can also enable it for the "expression" command and also for other things.

Greg Clayton gclayton at apple.com
Tue May 14 16:43:18 PDT 2013


Author: gclayton
Date: Tue May 14 18:43:18 2013
New Revision: 181850

URL: http://llvm.org/viewvc/llvm-project?rev=181850&view=rev
Log:
A first pass at auto completion for variables and their children. This is currently hooked up for "frame variable" only. With a little work we can also enable it for the "expression" command and also for other things.


Modified:
    lldb/trunk/include/lldb/Interpreter/CommandCompletions.h
    lldb/trunk/include/lldb/Symbol/ClangASTType.h
    lldb/trunk/include/lldb/Symbol/Variable.h
    lldb/trunk/source/Commands/CommandCompletions.cpp
    lldb/trunk/source/Commands/CommandObjectFrame.cpp
    lldb/trunk/source/Symbol/ClangASTType.cpp
    lldb/trunk/source/Symbol/Variable.cpp

Modified: lldb/trunk/include/lldb/Interpreter/CommandCompletions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandCompletions.h?rev=181850&r1=181849&r2=181850&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandCompletions.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandCompletions.h Tue May 14 18:43:18 2013
@@ -49,10 +49,11 @@ public:
         eSettingsNameCompletion   = (1u << 5),
         ePlatformPluginCompletion = (1u << 6),
         eArchitectureCompletion   = (1u << 7),
+        eVariablePathCompletion   = (1u << 8),
         // This item serves two purposes.  It is the last element in the enum,
         // so you can add custom enums starting from here in your Option class.
         // Also if you & in this bit the base code will not process the option.
-        eCustomCompletion         = (1u << 8)  
+        eCustomCompletion         = (1u << 9)
 
     } CommonCompletionTypes;
 
@@ -145,7 +146,16 @@ public:
                        SearchFilter *searcher,
                        bool &word_complete,
                        lldb_private::StringList &matches);
-    
+
+    static int
+    VariablePath (CommandInterpreter &interpreter,
+                  const char *partial_file_name,
+                  int match_start_point,
+                  int max_return_elements,
+                  SearchFilter *searcher,
+                  bool &word_complete,
+                  lldb_private::StringList &matches);
+
     //----------------------------------------------------------------------
     // The Completer class is a convenient base class for building searchers
     // that go along with the SearchFilter passed to the standard Completer

Modified: lldb/trunk/include/lldb/Symbol/ClangASTType.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTType.h?rev=181850&r1=181849&r2=181850&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTType.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTType.h Tue May 14 18:43:18 2013
@@ -76,6 +76,15 @@ public:
         return m_ast; 
     }
 
+    static ClangASTType
+    GetCanonicalType (clang::ASTContext *ast, lldb::clang_type_t clang_type);
+
+    ClangASTType
+    GetCanonicalType ()
+    {
+        return GetCanonicalType (GetASTContext(), GetOpaqueQualType());
+    }
+
     ConstString
     GetConstTypeName ();
     
@@ -137,6 +146,12 @@ public:
     GetTypeClass (clang::ASTContext *ast_context, 
                   lldb::clang_type_t clang_type);
 
+    lldb::TypeClass
+    GetTypeClass () const
+    {
+        return GetTypeClass (GetASTContext(), GetOpaqueQualType());
+    }
+
     void
     DumpValue (ExecutionContext *exe_ctx,
                Stream *s,
@@ -310,7 +325,7 @@ public:
                    StreamString &new_value);
 
     lldb::clang_type_t
-    GetPointeeType ();
+    GetPointeeType () const;
 
     static lldb::clang_type_t
     GetPointeeType (lldb::clang_type_t opaque_clang_qual_type);

Modified: lldb/trunk/include/lldb/Symbol/Variable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Variable.h?rev=181850&r1=181849&r2=181850&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/Variable.h (original)
+++ lldb/trunk/include/lldb/Symbol/Variable.h Tue May 14 18:43:18 2013
@@ -157,6 +157,12 @@ public:
                                         VariableList &variable_list,
                                         ValueObjectList &valobj_list);
 
+    static size_t
+    AutoComplete (const ExecutionContext &exe_ctx,
+                  const char *name,
+                  StringList &matches,
+                  bool &word_complete);
+
 protected:
     ConstString m_name;                 // The basename of the variable (no namespaces)
     Mangled m_mangled;                  // The mangled name of the variable

Modified: lldb/trunk/source/Commands/CommandCompletions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandCompletions.cpp?rev=181850&r1=181849&r2=181850&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandCompletions.cpp (original)
+++ lldb/trunk/source/Commands/CommandCompletions.cpp Tue May 14 18:43:18 2013
@@ -27,6 +27,7 @@
 #include "lldb/Interpreter/CommandCompletions.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Variable.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/CleanUp.h"
 
@@ -44,6 +45,7 @@ CommandCompletions::g_common_completions
     {eSettingsNameCompletion,    CommandCompletions::SettingsNames},
     {ePlatformPluginCompletion,  CommandCompletions::PlatformPluginNames},
     {eArchitectureCompletion,    CommandCompletions::ArchitectureNames},
+    {eVariablePathCompletion,    CommandCompletions::VariablePath},
     {eNoCompletion,              NULL}      // This one has to be last in the list.
 };
 
@@ -459,6 +461,19 @@ CommandCompletions::ArchitectureNames (C
 }
 
 
+int
+CommandCompletions::VariablePath (CommandInterpreter &interpreter,
+                                  const char *partial_name,
+                                  int match_start_point,
+                                  int max_return_elements,
+                                  SearchFilter *searcher,
+                                  bool &word_complete,
+                                  lldb_private::StringList &matches)
+{
+    return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
+}
+
+
 CommandCompletions::Completer::Completer 
 (
     CommandInterpreter &interpreter,

Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=181850&r1=181849&r2=181850&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Tue May 14 18:43:18 2013
@@ -345,6 +345,32 @@ public:
     {
         return &m_option_group;
     }
+    
+    
+    virtual int
+    HandleArgumentCompletion (Args &input,
+                              int &cursor_index,
+                              int &cursor_char_position,
+                              OptionElementVector &opt_element_vector,
+                              int match_start_point,
+                              int max_return_elements,
+                              bool &word_complete,
+                              StringList &matches)
+    {
+        // Arguments are the standard source file completer.
+        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+        completion_str.erase (cursor_char_position);
+        
+        CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
+                                                             CommandCompletions::eVariablePathCompletion,
+                                                             completion_str.c_str(),
+                                                             match_start_point,
+                                                             max_return_elements,
+                                                             NULL,
+                                                             word_complete,
+                                                             matches);
+        return matches.GetSize();
+    }
 
 protected:
     virtual bool

Modified: lldb/trunk/source/Symbol/ClangASTType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTType.cpp?rev=181850&r1=181849&r2=181850&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTType.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTType.cpp Tue May 14 18:43:18 2013
@@ -79,6 +79,14 @@ ClangASTType::GetTypeNameForOpaqueQualTy
     return GetTypeNameForQualType (ast, clang::QualType::getFromOpaquePtr(opaque_qual_type));
 }
 
+ClangASTType
+ClangASTType::GetCanonicalType (clang::ASTContext *ast, lldb::clang_type_t opaque_qual_type)
+{
+    if (ast && opaque_qual_type)
+        return ClangASTType (ast,
+                             clang::QualType::getFromOpaquePtr(opaque_qual_type).getCanonicalType().getAsOpaquePtr());
+    return ClangASTType();
+}
 
 ConstString
 ClangASTType::GetConstTypeName ()
@@ -124,7 +132,7 @@ ClangASTType::GetConstTypeName (clang::A
 }
 
 clang_type_t
-ClangASTType::GetPointeeType ()
+ClangASTType::GetPointeeType () const
 {
     return GetPointeeType (m_type);
 }

Modified: lldb/trunk/source/Symbol/Variable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Variable.cpp?rev=181850&r1=181849&r2=181850&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/Variable.cpp (original)
+++ lldb/trunk/source/Symbol/Variable.cpp Tue May 14 18:43:18 2013
@@ -516,6 +516,397 @@ Variable::DumpLocationForAddress (Stream
         }
     }
     return false;
+}
+
+
+static void
+PrivateAutoComplete (StackFrame *frame,
+                     const std::string &partial_path,
+                     const std::string &prefix_path, // Anything that has been resolved already will be in here
+                     const ClangASTType& clang_type,
+                     StringList &matches,
+                     bool &word_complete);
+
+static void
+PrivateAutoCompleteMembers (StackFrame *frame,
+                            const std::string &partial_member_name,
+                            const std::string &partial_path,
+                            const std::string &prefix_path, // Anything that has been resolved already will be in here
+                            const ClangASTType& clang_type,
+                            StringList &matches,
+                            bool &word_complete);
+
+static void
+PrivateAutoCompleteMembers (StackFrame *frame,
+                            const std::string &partial_member_name,
+                            const std::string &partial_path,
+                            const std::string &prefix_path, // Anything that has been resolved already will be in here
+                            const ClangASTType& clang_type,
+                            StringList &matches,
+                            bool &word_complete)
+{
+
+    // We are in a type parsing child members
+    const uint32_t num_bases = ClangASTContext::GetNumDirectBaseClasses(clang_type.GetASTContext(),
+                                                                        clang_type.GetOpaqueQualType());
+    
+    if (num_bases > 0)
+    {
+        for (uint32_t i = 0; i < num_bases; ++i)
+        {
+            ClangASTType base_class_type (clang_type.GetASTContext(),
+                                          ClangASTContext::GetDirectBaseClassAtIndex (clang_type.GetASTContext(),
+                                                                                      clang_type.GetOpaqueQualType(),
+                                                                                      i,
+                                                                                      NULL));
+            
+            PrivateAutoCompleteMembers (frame,
+                                        partial_member_name,
+                                        partial_path,
+                                        prefix_path,
+                                        base_class_type.GetCanonicalType(),
+                                        matches,
+                                        word_complete);
+        }
+    }
+
+    const uint32_t num_vbases = ClangASTContext::GetNumVirtualBaseClasses(clang_type.GetASTContext(),
+                                                                          clang_type.GetOpaqueQualType());
+    
+    if (num_vbases > 0)
+    {
+        for (uint32_t i = 0; i < num_vbases; ++i)
+        {
+            ClangASTType vbase_class_type (clang_type.GetASTContext(),
+                                          ClangASTContext::GetVirtualBaseClassAtIndex(clang_type.GetASTContext(),
+                                                                                      clang_type.GetOpaqueQualType(),
+                                                                                      i,
+                                                                                      NULL));
+            
+            PrivateAutoCompleteMembers (frame,
+                                        partial_member_name,
+                                        partial_path,
+                                        prefix_path,
+                                        vbase_class_type.GetCanonicalType(),
+                                        matches,
+                                        word_complete);
+        }
+    }
+
+    // We are in a type parsing child members
+    const uint32_t num_fields = ClangASTContext::GetNumFields(clang_type.GetASTContext(),
+                                                              clang_type.GetOpaqueQualType());
+    
+    if (num_fields > 0)
+    {
+        for (uint32_t i = 0; i < num_fields; ++i)
+        {
+            std::string member_name;
+            
+            lldb::clang_type_t member_type = ClangASTContext::GetFieldAtIndex (clang_type.GetASTContext(),
+                                                                               clang_type.GetOpaqueQualType(),
+                                                                               i,
+                                                                               member_name,
+                                                                               NULL,
+                                                                               NULL,
+                                                                               NULL);
+            
+            if (partial_member_name.empty() ||
+                member_name.find(partial_member_name) == 0)
+            {
+                if (member_name == partial_member_name)
+                {
+                    ClangASTType member_clang_type (clang_type.GetASTContext(), member_type);
+                    PrivateAutoComplete (frame,
+                                         partial_path,
+                                         prefix_path + member_name, // Anything that has been resolved already will be in here
+                                         member_clang_type.GetCanonicalType(),
+                                         matches,
+                                         word_complete);
+                }
+                else
+                {
+                    matches.AppendString (prefix_path + member_name);
+                }
+            }
+        }
+    }
+}
+
+static void
+PrivateAutoComplete (StackFrame *frame,
+                     const std::string &partial_path,
+                     const std::string &prefix_path, // Anything that has been resolved already will be in here
+                     const ClangASTType& clang_type,
+                     StringList &matches,
+                     bool &word_complete)
+{
+//    printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = '%s'\n", prefix_path.c_str(), partial_path.c_str());
+    std::string remaining_partial_path;
+
+    const lldb::TypeClass type_class = clang_type.GetTypeClass();
+    if (partial_path.empty())
+    {
+        if (clang_type.IsValid())
+        {
+            switch (type_class)
+            {
+                default:
+                case eTypeClassArray:
+                case eTypeClassBlockPointer:
+                case eTypeClassBuiltin:
+                case eTypeClassComplexFloat:
+                case eTypeClassComplexInteger:
+                case eTypeClassEnumeration:
+                case eTypeClassFunction:
+                case eTypeClassMemberPointer:
+                case eTypeClassReference:
+                case eTypeClassTypedef:
+                case eTypeClassVector:
+                    {
+                        matches.AppendString (prefix_path);
+                        word_complete = matches.GetSize() == 1;
+                    }
+                    break;
+                    
+                case eTypeClassClass:
+                case eTypeClassStruct:
+                case eTypeClassUnion:
+                    if (prefix_path.back() != '.')
+                        matches.AppendString (prefix_path + '.');
+                    break;
+
+                case eTypeClassObjCObject:
+                case eTypeClassObjCInterface:
+                    break;
+                case eTypeClassObjCObjectPointer:
+                case eTypeClassPointer:
+                    {
+                        bool omit_empty_base_classes = true;
+                        if (ClangASTContext::GetNumChildren (clang_type.GetASTContext(), clang_type.GetPointeeType(), omit_empty_base_classes) > 0)
+                            matches.AppendString (prefix_path + "->");
+                        else
+                        {
+                            matches.AppendString (prefix_path);
+                            word_complete = true;
+                        }
+                    }
+                    break;
+            }
+        }
+        else
+        {
+            if (frame)
+            {
+                const bool get_file_globals = true;
+                
+                VariableList *variable_list = frame->GetVariableList(get_file_globals);
+                
+                const size_t num_variables = variable_list->GetSize();
+                for (size_t i=0; i<num_variables; ++i)
+                {
+                    Variable *variable = variable_list->GetVariableAtIndex(i).get();
+                    matches.AppendString (variable->GetName().AsCString());
+                }
+            }
+        }
+    }
+    else
+    {
+        const char ch = partial_path[0];
+        switch (ch)
+        {
+        case '*':
+            if (prefix_path.empty())
+            {
+                PrivateAutoComplete (frame,
+                                     partial_path.substr(1),
+                                     std::string("*"),
+                                     clang_type,
+                                     matches,
+                                     word_complete);
+            }
+            break;
+
+        case '&':
+            if (prefix_path.empty())
+            {
+                PrivateAutoComplete (frame,
+                                     partial_path.substr(1),
+                                     std::string("&"),
+                                     clang_type,
+                                     matches,
+                                     word_complete);
+            }
+            break;
+
+        case '-':
+            if (partial_path[1] == '>' && !prefix_path.empty())
+            {
+                switch (type_class)
+                {
+                    case lldb::eTypeClassPointer:
+                        {
+                            ClangASTType pointee_type(clang_type.GetASTContext(), clang_type.GetPointeeType());
+                            if (partial_path[2])
+                            {
+                                // If there is more after the "->", then search deeper
+                                PrivateAutoComplete (frame,
+                                                     partial_path.substr(2),
+                                                     prefix_path + "->",
+                                                     pointee_type.GetCanonicalType(),
+                                                     matches,
+                                                     word_complete);
+                            }
+                            else
+                            {
+                                // Nothing after the "->", so list all members
+                                PrivateAutoCompleteMembers (frame,
+                                                            std::string(),
+                                                            std::string(),
+                                                            prefix_path + "->",
+                                                            pointee_type.GetCanonicalType(),
+                                                            matches,
+                                                            word_complete);                            
+                            }
+                        }
+                    default:
+                        break;
+                }
+            }
+            break;
+            
+        case '.':
+            if (clang_type.IsValid())
+            {
+                switch (type_class)
+                {
+                    case lldb::eTypeClassUnion:
+                    case lldb::eTypeClassStruct:
+                    case lldb::eTypeClassClass:
+                        if (partial_path[1])
+                        {
+                            // If there is more after the ".", then search deeper
+                            PrivateAutoComplete (frame,
+                                                 partial_path.substr(1),
+                                                 prefix_path + ".",
+                                                 clang_type,
+                                                 matches,
+                                                 word_complete);
+                            
+                        }
+                        else
+                        {
+                            // Nothing after the ".", so list all members
+                            PrivateAutoCompleteMembers (frame,
+                                                        std::string(),
+                                                        partial_path,
+                                                        prefix_path + ".",
+                                                        clang_type,
+                                                        matches,
+                                                        word_complete);
+                        }
+                    default:
+                        break;
+                }
+            }
+            break;
+        default:
+            if (isalpha(ch) || ch == '_' || ch == '$')
+            {
+                const size_t partial_path_len = partial_path.size();
+                size_t pos = 1;
+                while (pos < partial_path_len)
+                {
+                    const char curr_ch = partial_path[pos];
+                    if (isalnum(curr_ch) || curr_ch == '_'  || curr_ch == '$')
+                    {
+                        ++pos;
+                        continue;
+                    }
+                    break;
+                }
+
+                std::string token(partial_path, 0, pos);
+                remaining_partial_path = partial_path.substr(pos);
+                
+                if (clang_type.IsValid())
+                {
+                    PrivateAutoCompleteMembers (frame,
+                                                token,
+                                                remaining_partial_path,
+                                                prefix_path,
+                                                clang_type,
+                                                matches,
+                                                word_complete);
+                }
+                else if (frame)
+                {
+                    // We haven't found our variable yet
+                    const bool get_file_globals = true;
+                    
+                    VariableList *variable_list = frame->GetVariableList(get_file_globals);
+                    
+                    const size_t num_variables = variable_list->GetSize();
+                    for (size_t i=0; i<num_variables; ++i)
+                    {
+                        Variable *variable = variable_list->GetVariableAtIndex(i).get();
+                        const char *variable_name = variable->GetName().AsCString();
+                        if (strstr(variable_name, token.c_str()) == variable_name)
+                        {
+                            if (strcmp (variable_name, token.c_str()) == 0)
+                            {
+                                Type *variable_type = variable->GetType();
+                                if (variable_type)
+                                {
+                                    ClangASTType variable_clang_type (variable_type->GetClangAST(), variable_type->GetClangForwardType());
+                                    PrivateAutoComplete (frame,
+                                                         remaining_partial_path,
+                                                         prefix_path + token, // Anything that has been resolved already will be in here
+                                                         variable_clang_type.GetCanonicalType(),
+                                                         matches,
+                                                         word_complete);
+                                }
+                                else
+                                {
+                                    matches.AppendString (prefix_path + variable_name);
+                                }
+                            }
+                            else if (remaining_partial_path.empty())
+                            {
+                                matches.AppendString (prefix_path + variable_name);
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+        }
+    }
+}
+
+
+
+size_t
+Variable::AutoComplete (const ExecutionContext &exe_ctx,
+                        const char *partial_path_cstr,
+                        StringList &matches,
+                        bool &word_complete)
+{
+    word_complete = false;
+    std::string partial_path;
+    std::string prefix_path;
+    ClangASTType clang_type;
+    if (partial_path_cstr && partial_path_cstr[0])
+        partial_path = partial_path_cstr;
+
+    PrivateAutoComplete (exe_ctx.GetFramePtr(),
+                         partial_path,
+                         prefix_path,
+                         clang_type,
+                         matches,
+                         word_complete);
 
+    return matches.GetSize();
 }
 





More information about the lldb-commits mailing list