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 FormattersMatchCandidate(ConstString name,ScriptInterpreter * script_interpreter,TypeImpl type,Flags flags)77 FormattersMatchCandidate(ConstString name, 78 ScriptInterpreter *script_interpreter, TypeImpl type, 79 Flags flags) 80 : m_type_name(name), m_script_interpreter(script_interpreter), 81 m_type(type), m_flags(flags) {} 82 83 ~FormattersMatchCandidate() = default; 84 GetTypeName()85 ConstString GetTypeName() const { return m_type_name; } 86 GetType()87 TypeImpl GetType() const { return m_type; } 88 GetScriptInterpreter()89 ScriptInterpreter *GetScriptInterpreter() const { 90 return m_script_interpreter; 91 } 92 DidStripPointer()93 bool DidStripPointer() const { return m_flags.stripped_pointer; } 94 DidStripReference()95 bool DidStripReference() const { return m_flags.stripped_reference; } 96 DidStripTypedef()97 bool DidStripTypedef() const { return m_flags.stripped_typedef; } 98 99 template <class Formatter> IsMatch(const std::shared_ptr<Formatter> & formatter_sp)100 bool IsMatch(const std::shared_ptr<Formatter> &formatter_sp) const { 101 if (!formatter_sp) 102 return false; 103 if (formatter_sp->Cascades() == false && DidStripTypedef()) 104 return false; 105 if (formatter_sp->SkipsPointers() && DidStripPointer()) 106 return false; 107 if (formatter_sp->SkipsReferences() && DidStripReference()) 108 return false; 109 return true; 110 } 111 112 private: 113 ConstString m_type_name; 114 // If a formatter provides a matching callback function, we need the script 115 // interpreter and the type object (as an argument to the callback). 116 ScriptInterpreter *m_script_interpreter; 117 TypeImpl m_type; 118 Flags m_flags; 119 }; 120 121 typedef std::vector<FormattersMatchCandidate> FormattersMatchVector; 122 typedef std::vector<lldb::LanguageType> CandidateLanguagesVector; 123 124 class FormattersMatchData { 125 public: 126 FormattersMatchData(ValueObject &, lldb::DynamicValueType); 127 128 FormattersMatchVector GetMatchesVector(); 129 130 ConstString GetTypeForCache(); 131 132 CandidateLanguagesVector GetCandidateLanguages(); 133 134 ValueObject &GetValueObject(); 135 136 lldb::DynamicValueType GetDynamicValueType(); 137 138 private: 139 ValueObject &m_valobj; 140 lldb::DynamicValueType m_dynamic_value_type; 141 std::pair<FormattersMatchVector, bool> m_formatters_match_vector; 142 ConstString m_type_for_cache; 143 CandidateLanguagesVector m_candidate_languages; 144 }; 145 146 class TypeNameSpecifierImpl { 147 public: 148 TypeNameSpecifierImpl() = default; 149 TypeNameSpecifierImpl(llvm::StringRef name,lldb::FormatterMatchType match_type)150 TypeNameSpecifierImpl(llvm::StringRef name, 151 lldb::FormatterMatchType match_type) 152 : m_match_type(match_type) { 153 m_type.m_type_name = std::string(name); 154 } 155 156 // if constructing with a given type, we consider that a case of exact match. TypeNameSpecifierImpl(lldb::TypeSP type)157 TypeNameSpecifierImpl(lldb::TypeSP type) 158 : m_match_type(lldb::eFormatterMatchExact) { 159 if (type) { 160 m_type.m_type_name = std::string(type->GetName().GetStringRef()); 161 m_type.m_compiler_type = type->GetForwardCompilerType(); 162 } 163 } 164 TypeNameSpecifierImpl(CompilerType type)165 TypeNameSpecifierImpl(CompilerType type) 166 : m_match_type(lldb::eFormatterMatchExact) { 167 if (type.IsValid()) { 168 m_type.m_type_name.assign(type.GetTypeName().GetCString()); 169 m_type.m_compiler_type = type; 170 } 171 } 172 GetName()173 const char *GetName() { 174 if (m_type.m_type_name.size()) 175 return m_type.m_type_name.c_str(); 176 return nullptr; 177 } 178 GetCompilerType()179 CompilerType GetCompilerType() { 180 if (m_type.m_compiler_type.IsValid()) 181 return m_type.m_compiler_type; 182 return CompilerType(); 183 } 184 GetMatchType()185 lldb::FormatterMatchType GetMatchType() { return m_match_type; } 186 IsRegex()187 bool IsRegex() { return m_match_type == lldb::eFormatterMatchRegex; } 188 189 private: 190 lldb::FormatterMatchType m_match_type = lldb::eFormatterMatchExact; 191 // TODO: Replace this with TypeAndOrName. 192 struct TypeOrName { 193 std::string m_type_name; 194 CompilerType m_compiler_type; 195 }; 196 TypeOrName m_type; 197 198 TypeNameSpecifierImpl(const TypeNameSpecifierImpl &) = delete; 199 const TypeNameSpecifierImpl & 200 operator=(const TypeNameSpecifierImpl &) = delete; 201 }; 202 203 } // namespace lldb_private 204 205 #endif // LLDB_DATAFORMATTERS_FORMATCLASSES_H 206