//===-- SBTypeCategory.cpp ----------------------------------------*- C++ //-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "lldb/API/SBTypeCategory.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBTypeFilter.h" #include "lldb/API/SBTypeFormat.h" #include "lldb/API/SBTypeNameSpecifier.h" #include "lldb/API/SBTypeSummary.h" #include "lldb/API/SBTypeSynthetic.h" #include "lldb/Core/Debugger.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/ScriptInterpreter.h" using namespace lldb; using namespace lldb_private; typedef std::pair ImplType; SBTypeCategory::SBTypeCategory() : m_opaque_sp() {} SBTypeCategory::SBTypeCategory(const char *name) : m_opaque_sp() { DataVisualization::Categories::GetCategory(ConstString(name), m_opaque_sp); } SBTypeCategory::SBTypeCategory(const lldb::SBTypeCategory &rhs) : m_opaque_sp(rhs.m_opaque_sp) {} SBTypeCategory::~SBTypeCategory() {} bool SBTypeCategory::IsValid() const { return (m_opaque_sp.get() != NULL); } bool SBTypeCategory::GetEnabled() { if (!IsValid()) return false; return m_opaque_sp->IsEnabled(); } void SBTypeCategory::SetEnabled(bool enabled) { if (!IsValid()) return; if (enabled) DataVisualization::Categories::Enable(m_opaque_sp); else DataVisualization::Categories::Disable(m_opaque_sp); } const char *SBTypeCategory::GetName() { if (!IsValid()) return NULL; return m_opaque_sp->GetName(); } lldb::LanguageType SBTypeCategory::GetLanguageAtIndex(uint32_t idx) { if (IsValid()) return m_opaque_sp->GetLanguageAtIndex(idx); return lldb::eLanguageTypeUnknown; } uint32_t SBTypeCategory::GetNumLanguages() { if (IsValid()) return m_opaque_sp->GetNumLanguages(); return 0; } void SBTypeCategory::AddLanguage(lldb::LanguageType language) { if (IsValid()) m_opaque_sp->AddLanguage(language); } uint32_t SBTypeCategory::GetNumFormats() { if (!IsValid()) return 0; return m_opaque_sp->GetTypeFormatsContainer()->GetCount() + m_opaque_sp->GetRegexTypeFormatsContainer()->GetCount(); } uint32_t SBTypeCategory::GetNumSummaries() { if (!IsValid()) return 0; return m_opaque_sp->GetTypeSummariesContainer()->GetCount() + m_opaque_sp->GetRegexTypeSummariesContainer()->GetCount(); } uint32_t SBTypeCategory::GetNumFilters() { if (!IsValid()) return 0; return m_opaque_sp->GetTypeFiltersContainer()->GetCount() + m_opaque_sp->GetRegexTypeFiltersContainer()->GetCount(); } #ifndef LLDB_DISABLE_PYTHON uint32_t SBTypeCategory::GetNumSynthetics() { if (!IsValid()) return 0; return m_opaque_sp->GetTypeSyntheticsContainer()->GetCount() + m_opaque_sp->GetRegexTypeSyntheticsContainer()->GetCount(); } #endif lldb::SBTypeNameSpecifier SBTypeCategory::GetTypeNameSpecifierForFilterAtIndex(uint32_t index) { if (!IsValid()) return SBTypeNameSpecifier(); return SBTypeNameSpecifier( m_opaque_sp->GetTypeNameSpecifierForFilterAtIndex(index)); } lldb::SBTypeNameSpecifier SBTypeCategory::GetTypeNameSpecifierForFormatAtIndex(uint32_t index) { if (!IsValid()) return SBTypeNameSpecifier(); return SBTypeNameSpecifier( m_opaque_sp->GetTypeNameSpecifierForFormatAtIndex(index)); } lldb::SBTypeNameSpecifier SBTypeCategory::GetTypeNameSpecifierForSummaryAtIndex(uint32_t index) { if (!IsValid()) return SBTypeNameSpecifier(); return SBTypeNameSpecifier( m_opaque_sp->GetTypeNameSpecifierForSummaryAtIndex(index)); } #ifndef LLDB_DISABLE_PYTHON lldb::SBTypeNameSpecifier SBTypeCategory::GetTypeNameSpecifierForSyntheticAtIndex(uint32_t index) { if (!IsValid()) return SBTypeNameSpecifier(); return SBTypeNameSpecifier( m_opaque_sp->GetTypeNameSpecifierForSyntheticAtIndex(index)); } #endif SBTypeFilter SBTypeCategory::GetFilterForType(SBTypeNameSpecifier spec) { if (!IsValid()) return SBTypeFilter(); if (!spec.IsValid()) return SBTypeFilter(); lldb::TypeFilterImplSP children_sp; if (spec.IsRegex()) m_opaque_sp->GetRegexTypeFiltersContainer()->GetExact( ConstString(spec.GetName()), children_sp); else m_opaque_sp->GetTypeFiltersContainer()->GetExact( ConstString(spec.GetName()), children_sp); if (!children_sp) return lldb::SBTypeFilter(); TypeFilterImplSP filter_sp = std::static_pointer_cast(children_sp); return lldb::SBTypeFilter(filter_sp); } SBTypeFormat SBTypeCategory::GetFormatForType(SBTypeNameSpecifier spec) { if (!IsValid()) return SBTypeFormat(); if (!spec.IsValid()) return SBTypeFormat(); lldb::TypeFormatImplSP format_sp; if (spec.IsRegex()) m_opaque_sp->GetRegexTypeFormatsContainer()->GetExact( ConstString(spec.GetName()), format_sp); else m_opaque_sp->GetTypeFormatsContainer()->GetExact( ConstString(spec.GetName()), format_sp); if (!format_sp) return lldb::SBTypeFormat(); return lldb::SBTypeFormat(format_sp); } #ifndef LLDB_DISABLE_PYTHON SBTypeSummary SBTypeCategory::GetSummaryForType(SBTypeNameSpecifier spec) { if (!IsValid()) return SBTypeSummary(); if (!spec.IsValid()) return SBTypeSummary(); lldb::TypeSummaryImplSP summary_sp; if (spec.IsRegex()) m_opaque_sp->GetRegexTypeSummariesContainer()->GetExact( ConstString(spec.GetName()), summary_sp); else m_opaque_sp->GetTypeSummariesContainer()->GetExact( ConstString(spec.GetName()), summary_sp); if (!summary_sp) return lldb::SBTypeSummary(); return lldb::SBTypeSummary(summary_sp); } #endif // LLDB_DISABLE_PYTHON #ifndef LLDB_DISABLE_PYTHON SBTypeSynthetic SBTypeCategory::GetSyntheticForType(SBTypeNameSpecifier spec) { if (!IsValid()) return SBTypeSynthetic(); if (!spec.IsValid()) return SBTypeSynthetic(); lldb::SyntheticChildrenSP children_sp; if (spec.IsRegex()) m_opaque_sp->GetRegexTypeSyntheticsContainer()->GetExact( ConstString(spec.GetName()), children_sp); else m_opaque_sp->GetTypeSyntheticsContainer()->GetExact( ConstString(spec.GetName()), children_sp); if (!children_sp) return lldb::SBTypeSynthetic(); ScriptedSyntheticChildrenSP synth_sp = std::static_pointer_cast(children_sp); return lldb::SBTypeSynthetic(synth_sp); } #endif #ifndef LLDB_DISABLE_PYTHON SBTypeFilter SBTypeCategory::GetFilterAtIndex(uint32_t index) { if (!IsValid()) return SBTypeFilter(); lldb::SyntheticChildrenSP children_sp = m_opaque_sp->GetSyntheticAtIndex((index)); if (!children_sp.get()) return lldb::SBTypeFilter(); TypeFilterImplSP filter_sp = std::static_pointer_cast(children_sp); return lldb::SBTypeFilter(filter_sp); } #endif SBTypeFormat SBTypeCategory::GetFormatAtIndex(uint32_t index) { if (!IsValid()) return SBTypeFormat(); return SBTypeFormat(m_opaque_sp->GetFormatAtIndex((index))); } #ifndef LLDB_DISABLE_PYTHON SBTypeSummary SBTypeCategory::GetSummaryAtIndex(uint32_t index) { if (!IsValid()) return SBTypeSummary(); return SBTypeSummary(m_opaque_sp->GetSummaryAtIndex((index))); } #endif #ifndef LLDB_DISABLE_PYTHON SBTypeSynthetic SBTypeCategory::GetSyntheticAtIndex(uint32_t index) { if (!IsValid()) return SBTypeSynthetic(); lldb::SyntheticChildrenSP children_sp = m_opaque_sp->GetSyntheticAtIndex((index)); if (!children_sp.get()) return lldb::SBTypeSynthetic(); ScriptedSyntheticChildrenSP synth_sp = std::static_pointer_cast(children_sp); return lldb::SBTypeSynthetic(synth_sp); } #endif bool SBTypeCategory::AddTypeFormat(SBTypeNameSpecifier type_name, SBTypeFormat format) { if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (!format.IsValid()) return false; if (type_name.IsRegex()) m_opaque_sp->GetRegexTypeFormatsContainer()->Add( lldb::RegularExpressionSP(new RegularExpression( llvm::StringRef::withNullAsEmpty(type_name.GetName()))), format.GetSP()); else m_opaque_sp->GetTypeFormatsContainer()->Add( ConstString(type_name.GetName()), format.GetSP()); return true; } bool SBTypeCategory::DeleteTypeFormat(SBTypeNameSpecifier type_name) { if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (type_name.IsRegex()) return m_opaque_sp->GetRegexTypeFormatsContainer()->Delete( ConstString(type_name.GetName())); else return m_opaque_sp->GetTypeFormatsContainer()->Delete( ConstString(type_name.GetName())); } #ifndef LLDB_DISABLE_PYTHON bool SBTypeCategory::AddTypeSummary(SBTypeNameSpecifier type_name, SBTypeSummary summary) { if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (!summary.IsValid()) return false; // FIXME: we need to iterate over all the Debugger objects and have each of // them contain a copy of the function // since we currently have formatters live in a global space, while Python // code lives in a specific Debugger-related environment this should // eventually be fixed by deciding a final location in the LLDB object space // for formatters if (summary.IsFunctionCode()) { const void *name_token = (const void *)ConstString(type_name.GetName()).GetCString(); const char *script = summary.GetData(); StringList input; input.SplitIntoLines(script, strlen(script)); uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers(); bool need_set = true; for (uint32_t j = 0; j < num_debuggers; j++) { DebuggerSP debugger_sp = lldb_private::Debugger::GetDebuggerAtIndex(j); if (debugger_sp) { ScriptInterpreter *interpreter_ptr = debugger_sp->GetCommandInterpreter().GetScriptInterpreter(); if (interpreter_ptr) { std::string output; if (interpreter_ptr->GenerateTypeScriptFunction(input, output, name_token) && !output.empty()) { if (need_set) { need_set = false; summary.SetFunctionName(output.c_str()); } } } } } } if (type_name.IsRegex()) m_opaque_sp->GetRegexTypeSummariesContainer()->Add( lldb::RegularExpressionSP(new RegularExpression( llvm::StringRef::withNullAsEmpty(type_name.GetName()))), summary.GetSP()); else m_opaque_sp->GetTypeSummariesContainer()->Add( ConstString(type_name.GetName()), summary.GetSP()); return true; } #endif bool SBTypeCategory::DeleteTypeSummary(SBTypeNameSpecifier type_name) { if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (type_name.IsRegex()) return m_opaque_sp->GetRegexTypeSummariesContainer()->Delete( ConstString(type_name.GetName())); else return m_opaque_sp->GetTypeSummariesContainer()->Delete( ConstString(type_name.GetName())); } bool SBTypeCategory::AddTypeFilter(SBTypeNameSpecifier type_name, SBTypeFilter filter) { if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (!filter.IsValid()) return false; if (type_name.IsRegex()) m_opaque_sp->GetRegexTypeFiltersContainer()->Add( lldb::RegularExpressionSP(new RegularExpression( llvm::StringRef::withNullAsEmpty(type_name.GetName()))), filter.GetSP()); else m_opaque_sp->GetTypeFiltersContainer()->Add( ConstString(type_name.GetName()), filter.GetSP()); return true; } bool SBTypeCategory::DeleteTypeFilter(SBTypeNameSpecifier type_name) { if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (type_name.IsRegex()) return m_opaque_sp->GetRegexTypeFiltersContainer()->Delete( ConstString(type_name.GetName())); else return m_opaque_sp->GetTypeFiltersContainer()->Delete( ConstString(type_name.GetName())); } #ifndef LLDB_DISABLE_PYTHON bool SBTypeCategory::AddTypeSynthetic(SBTypeNameSpecifier type_name, SBTypeSynthetic synth) { if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (!synth.IsValid()) return false; // FIXME: we need to iterate over all the Debugger objects and have each of // them contain a copy of the function // since we currently have formatters live in a global space, while Python // code lives in a specific Debugger-related environment this should // eventually be fixed by deciding a final location in the LLDB object space // for formatters if (synth.IsClassCode()) { const void *name_token = (const void *)ConstString(type_name.GetName()).GetCString(); const char *script = synth.GetData(); StringList input; input.SplitIntoLines(script, strlen(script)); uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers(); bool need_set = true; for (uint32_t j = 0; j < num_debuggers; j++) { DebuggerSP debugger_sp = lldb_private::Debugger::GetDebuggerAtIndex(j); if (debugger_sp) { ScriptInterpreter *interpreter_ptr = debugger_sp->GetCommandInterpreter().GetScriptInterpreter(); if (interpreter_ptr) { std::string output; if (interpreter_ptr->GenerateTypeSynthClass(input, output, name_token) && !output.empty()) { if (need_set) { need_set = false; synth.SetClassName(output.c_str()); } } } } } } if (type_name.IsRegex()) m_opaque_sp->GetRegexTypeSyntheticsContainer()->Add( lldb::RegularExpressionSP(new RegularExpression( llvm::StringRef::withNullAsEmpty(type_name.GetName()))), synth.GetSP()); else m_opaque_sp->GetTypeSyntheticsContainer()->Add( ConstString(type_name.GetName()), synth.GetSP()); return true; } bool SBTypeCategory::DeleteTypeSynthetic(SBTypeNameSpecifier type_name) { if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (type_name.IsRegex()) return m_opaque_sp->GetRegexTypeSyntheticsContainer()->Delete( ConstString(type_name.GetName())); else return m_opaque_sp->GetTypeSyntheticsContainer()->Delete( ConstString(type_name.GetName())); } #endif // LLDB_DISABLE_PYTHON bool SBTypeCategory::GetDescription(lldb::SBStream &description, lldb::DescriptionLevel description_level) { if (!IsValid()) return false; description.Printf("Category name: %s\n", GetName()); return true; } lldb::SBTypeCategory &SBTypeCategory:: operator=(const lldb::SBTypeCategory &rhs) { if (this != &rhs) { m_opaque_sp = rhs.m_opaque_sp; } return *this; } bool SBTypeCategory::operator==(lldb::SBTypeCategory &rhs) { if (!IsValid()) return !rhs.IsValid(); return m_opaque_sp.get() == rhs.m_opaque_sp.get(); } bool SBTypeCategory::operator!=(lldb::SBTypeCategory &rhs) { if (!IsValid()) return rhs.IsValid(); return m_opaque_sp.get() != rhs.m_opaque_sp.get(); } lldb::TypeCategoryImplSP SBTypeCategory::GetSP() { if (!IsValid()) return lldb::TypeCategoryImplSP(); return m_opaque_sp; } void SBTypeCategory::SetSP( const lldb::TypeCategoryImplSP &typecategory_impl_sp) { m_opaque_sp = typecategory_impl_sp; } SBTypeCategory::SBTypeCategory( const lldb::TypeCategoryImplSP &typecategory_impl_sp) : m_opaque_sp(typecategory_impl_sp) {} bool SBTypeCategory::IsDefaultCategory() { if (!IsValid()) return false; return (strcmp(m_opaque_sp->GetName(), "default") == 0); }