1 //===-- FormatClasses.h -----------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_DATAFORMATTERS_FORMATCLASSES_H 10 #define LLDB_DATAFORMATTERS_FORMATCLASSES_H 11 12 #include <functional> 13 #include <memory> 14 #include <string> 15 #include <vector> 16 17 #include "lldb/DataFormatters/TypeFormat.h" 18 #include "lldb/DataFormatters/TypeSummary.h" 19 #include "lldb/DataFormatters/TypeSynthetic.h" 20 #include "lldb/Interpreter/ScriptInterpreter.h" 21 #include "lldb/Symbol/CompilerType.h" 22 #include "lldb/Symbol/Type.h" 23 #include "lldb/lldb-enumerations.h" 24 #include "lldb/lldb-public.h" 25 26 namespace lldb_private { 27 28 class HardcodedFormatters { 29 public: 30 template <typename FormatterType> 31 using HardcodedFormatterFinder = 32 std::function<typename FormatterType::SharedPointer( 33 lldb_private::ValueObject &, lldb::DynamicValueType, 34 FormatManager &)>; 35 36 template <typename FormatterType> 37 using HardcodedFormatterFinders = 38 std::vector<HardcodedFormatterFinder<FormatterType>>; 39 40 typedef HardcodedFormatterFinders<TypeFormatImpl> HardcodedFormatFinder; 41 typedef HardcodedFormatterFinders<TypeSummaryImpl> HardcodedSummaryFinder; 42 typedef HardcodedFormatterFinders<SyntheticChildren> HardcodedSyntheticFinder; 43 }; 44 45 class FormattersMatchCandidate { 46 public: 47 // Contains flags to indicate how this candidate was generated (e.g. if 48 // typedefs were stripped, or pointers were skipped). These are later compared 49 // to flags in formatters to confirm a string match. 50 struct Flags { 51 bool stripped_pointer = false; 52 bool stripped_reference = false; 53 bool stripped_typedef = false; 54 55 // Returns a copy of this with the "stripped pointer" flag set. WithStrippedPointerFlags56 Flags WithStrippedPointer() { 57 Flags result(*this); 58 result.stripped_pointer = true; 59 return result; 60 } 61 62 // Returns a copy of this with the "stripped reference" flag set. WithStrippedReferenceFlags63 Flags WithStrippedReference() { 64 Flags result(*this); 65 result.stripped_reference = true; 66 return result; 67 } 68 69 // Returns a copy of this with the "stripped typedef" flag set. WithStrippedTypedefFlags70 Flags WithStrippedTypedef() { 71 Flags result(*this); 72 result.stripped_typedef = true; 73 return result; 74 } 75 }; 76 77 FormattersMatchCandidate(ConstString name, 78 ScriptInterpreter *script_interpreter, TypeImpl type, 79 Flags flags, uint32_t ptr_stripped_depth = 0) m_type_name(name)80 : m_type_name(name), m_script_interpreter(script_interpreter), 81 m_type(type), m_flags(flags), m_ptr_stripped_depth(ptr_stripped_depth) { 82 } 83 84 ~FormattersMatchCandidate() = default; 85 GetTypeName()86 ConstString GetTypeName() const { return m_type_name; } 87 GetType()88 TypeImpl GetType() const { return m_type; } 89 GetScriptInterpreter()90 ScriptInterpreter *GetScriptInterpreter() const { 91 return m_script_interpreter; 92 } 93 DidStripPointer()94 bool DidStripPointer() const { return m_flags.stripped_pointer; } 95 DidStripReference()96 bool DidStripReference() const { return m_flags.stripped_reference; } 97 DidStripTypedef()98 bool DidStripTypedef() const { return m_flags.stripped_typedef; } 99 GetPtrStrippedDepth()100 uint32_t GetPtrStrippedDepth() const { return m_ptr_stripped_depth; } 101 102 template <class Formatter> IsMatch(const std::shared_ptr<Formatter> & formatter_sp)103 bool IsMatch(const std::shared_ptr<Formatter> &formatter_sp) const { 104 if (!formatter_sp) 105 return false; 106 if (formatter_sp->Cascades() == false && DidStripTypedef()) 107 return false; 108 if (formatter_sp->SkipsPointers() && DidStripPointer()) 109 return false; 110 if (formatter_sp->GetPtrMatchDepth() < GetPtrStrippedDepth()) 111 return false; 112 if (formatter_sp->SkipsReferences() && DidStripReference()) 113 return false; 114 return true; 115 } 116 117 private: 118 ConstString m_type_name; 119 // If a formatter provides a matching callback function, we need the script 120 // interpreter and the type object (as an argument to the callback). 121 ScriptInterpreter *m_script_interpreter; 122 TypeImpl m_type; 123 Flags m_flags; 124 uint32_t m_ptr_stripped_depth; 125 }; 126 127 typedef std::vector<FormattersMatchCandidate> FormattersMatchVector; 128 typedef std::vector<lldb::LanguageType> CandidateLanguagesVector; 129 130 class FormattersMatchData { 131 public: 132 FormattersMatchData(ValueObject &, lldb::DynamicValueType); 133 134 FormattersMatchVector GetMatchesVector(); 135 136 ConstString GetTypeForCache(); 137 138 CandidateLanguagesVector GetCandidateLanguages(); 139 140 ValueObject &GetValueObject(); 141 142 lldb::DynamicValueType GetDynamicValueType(); 143 144 private: 145 ValueObject &m_valobj; 146 lldb::DynamicValueType m_dynamic_value_type; 147 std::pair<FormattersMatchVector, bool> m_formatters_match_vector; 148 ConstString m_type_for_cache; 149 CandidateLanguagesVector m_candidate_languages; 150 }; 151 152 class TypeNameSpecifierImpl { 153 public: 154 TypeNameSpecifierImpl() = default; 155 TypeNameSpecifierImpl(llvm::StringRef name,lldb::FormatterMatchType match_type)156 TypeNameSpecifierImpl(llvm::StringRef name, 157 lldb::FormatterMatchType match_type) 158 : m_match_type(match_type) { 159 m_type.m_type_name = std::string(name); 160 } 161 162 // if constructing with a given type, we consider that a case of exact match. TypeNameSpecifierImpl(lldb::TypeSP type)163 TypeNameSpecifierImpl(lldb::TypeSP type) 164 : m_match_type(lldb::eFormatterMatchExact) { 165 if (type) { 166 m_type.m_type_name = std::string(type->GetName().GetStringRef()); 167 m_type.m_compiler_type = type->GetForwardCompilerType(); 168 } 169 } 170 TypeNameSpecifierImpl(CompilerType type)171 TypeNameSpecifierImpl(CompilerType type) 172 : m_match_type(lldb::eFormatterMatchExact) { 173 if (type.IsValid()) { 174 m_type.m_type_name.assign(type.GetTypeName().GetCString()); 175 m_type.m_compiler_type = type; 176 } 177 } 178 GetName()179 const char *GetName() { 180 if (m_type.m_type_name.size()) 181 return m_type.m_type_name.c_str(); 182 return nullptr; 183 } 184 GetCompilerType()185 CompilerType GetCompilerType() { 186 if (m_type.m_compiler_type.IsValid()) 187 return m_type.m_compiler_type; 188 return CompilerType(); 189 } 190 GetMatchType()191 lldb::FormatterMatchType GetMatchType() { return m_match_type; } 192 IsRegex()193 bool IsRegex() { return m_match_type == lldb::eFormatterMatchRegex; } 194 195 private: 196 lldb::FormatterMatchType m_match_type = lldb::eFormatterMatchExact; 197 // TODO: Replace this with TypeAndOrName. 198 struct TypeOrName { 199 std::string m_type_name; 200 CompilerType m_compiler_type; 201 }; 202 TypeOrName m_type; 203 204 TypeNameSpecifierImpl(const TypeNameSpecifierImpl &) = delete; 205 const TypeNameSpecifierImpl & 206 operator=(const TypeNameSpecifierImpl &) = delete; 207 }; 208 209 } // namespace lldb_private 210 211 #endif // LLDB_DATAFORMATTERS_FORMATCLASSES_H 212