Beispiel #1
0
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 CompilerType& compiler_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 = compiler_type.GetTypeClass();
    if (partial_path.empty())
    {
        if (compiler_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 (compiler_type.GetNumChildren (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);
                
                if (variable_list)
                {
                    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("*"),
                                     compiler_type,
                                     matches,
                                     word_complete);
            }
            break;

        case '&':
            if (prefix_path.empty())
            {
                PrivateAutoComplete (frame,
                                     partial_path.substr(1),
                                     std::string("&"),
                                     compiler_type,
                                     matches,
                                     word_complete);
            }
            break;

        case '-':
            if (partial_path[1] == '>' && !prefix_path.empty())
            {
                switch (type_class)
                {
                    case lldb::eTypeClassPointer:
                        {
                            CompilerType pointee_type(compiler_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);                            
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            break;
            
        case '.':
            if (compiler_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 + ".",
                                                 compiler_type,
                                                 matches,
                                                 word_complete);
                            
                        }
                        else
                        {
                            // Nothing after the ".", so list all members
                            PrivateAutoCompleteMembers (frame,
                                                        std::string(),
                                                        partial_path,
                                                        prefix_path + ".",
                                                        compiler_type,
                                                        matches,
                                                        word_complete);
                        }
                        break;
                    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 (compiler_type.IsValid())
                {
                    PrivateAutoCompleteMembers (frame,
                                                token,
                                                remaining_partial_path,
                                                prefix_path,
                                                compiler_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);
                    
                    if (!variable_list)
                        break;
                    
                    const size_t num_variables = variable_list->GetSize();
                    for (size_t i=0; i<num_variables; ++i)
                    {
                        Variable *variable = variable_list->GetVariableAtIndex(i).get();
                        
                        if (!variable)
                            continue;
                        
                        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)
                                {
                                    CompilerType variable_compiler_type (variable_type->GetForwardCompilerType ());
                                    PrivateAutoComplete (frame,
                                                         remaining_partial_path,
                                                         prefix_path + token, // Anything that has been resolved already will be in here
                                                         variable_compiler_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;
        }
    }
}
Beispiel #2
0
void FormatManager::GetPossibleMatches(
    ValueObject &valobj, CompilerType compiler_type, uint32_t reason,
    lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries,
    bool did_strip_ptr, bool did_strip_ref, bool did_strip_typedef,
    bool root_level) {
  compiler_type = compiler_type.GetTypeForFormatters();
  ConstString type_name(compiler_type.GetConstTypeName());
  if (valobj.GetBitfieldBitSize() > 0) {
    StreamString sstring;
    sstring.Printf("%s:%d", type_name.AsCString(), valobj.GetBitfieldBitSize());
    ConstString bitfieldname(sstring.GetString());
    entries.push_back(
        {bitfieldname, 0, did_strip_ptr, did_strip_ref, did_strip_typedef});
    reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
  }

  if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) {
    entries.push_back(
        {type_name, reason, did_strip_ptr, did_strip_ref, did_strip_typedef});

    ConstString display_type_name(compiler_type.GetDisplayTypeName());
    if (display_type_name != type_name)
      entries.push_back({display_type_name, reason, did_strip_ptr,
                         did_strip_ref, did_strip_typedef});
  }

  for (bool is_rvalue_ref = true, j = true;
       j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) {
    CompilerType non_ref_type = compiler_type.GetNonReferenceType();
    GetPossibleMatches(
        valobj, non_ref_type,
        reason |
            lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
        use_dynamic, entries, did_strip_ptr, true, did_strip_typedef);
    if (non_ref_type.IsTypedefType()) {
      CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType();
      deffed_referenced_type =
          is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType()
                        : deffed_referenced_type.GetLValueReferenceType();
      GetPossibleMatches(
          valobj, deffed_referenced_type,
          reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
          use_dynamic, entries, did_strip_ptr, did_strip_ref,
          true); // this is not exactly the usual meaning of stripping typedefs
    }
  }

  if (compiler_type.IsPointerType()) {
    CompilerType non_ptr_type = compiler_type.GetPointeeType();
    GetPossibleMatches(
        valobj, non_ptr_type,
        reason |
            lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
        use_dynamic, entries, true, did_strip_ref, did_strip_typedef);
    if (non_ptr_type.IsTypedefType()) {
      CompilerType deffed_pointed_type =
          non_ptr_type.GetTypedefedType().GetPointerType();
      GetPossibleMatches(
          valobj, deffed_pointed_type,
          reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
          use_dynamic, entries, did_strip_ptr, did_strip_ref,
          true); // this is not exactly the usual meaning of stripping typedefs
    }
  }

  for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) {
    if (Language *language = Language::FindPlugin(language_type)) {
      for (ConstString candidate :
           language->GetPossibleFormattersMatches(valobj, use_dynamic)) {
        entries.push_back(
            {candidate,
             reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin,
             did_strip_ptr, did_strip_ref, did_strip_typedef});
      }
    }
  }

  // try to strip typedef chains
  if (compiler_type.IsTypedefType()) {
    CompilerType deffed_type = compiler_type.GetTypedefedType();
    GetPossibleMatches(
        valobj, deffed_type,
        reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
        use_dynamic, entries, did_strip_ptr, did_strip_ref, true);
  }

  if (root_level) {
    do {
      if (!compiler_type.IsValid())
        break;

      CompilerType unqual_compiler_ast_type =
          compiler_type.GetFullyUnqualifiedType();
      if (!unqual_compiler_ast_type.IsValid())
        break;
      if (unqual_compiler_ast_type.GetOpaqueQualType() !=
          compiler_type.GetOpaqueQualType())
        GetPossibleMatches(valobj, unqual_compiler_ast_type, reason,
                           use_dynamic, entries, did_strip_ptr, did_strip_ref,
                           did_strip_typedef);
    } while (false);

    // if all else fails, go to static type
    if (valobj.IsDynamic()) {
      lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
      if (static_value_sp)
        GetPossibleMatches(
            *static_value_sp.get(), static_value_sp->GetCompilerType(),
            reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue,
            use_dynamic, entries, did_strip_ptr, did_strip_ref,
            did_strip_typedef, true);
    }
  }
}