xref: /freebsd/contrib/llvm-project/lldb/include/lldb/DataFormatters/FormatClasses.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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