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. |
56 | 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. |
63 | 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. |
70 | 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) |
80 | : m_type_name(name), m_script_interpreter(script_interpreter), |
81 | m_type(type), m_flags(flags) {} |
82 | |
83 | ~FormattersMatchCandidate() = default; |
84 | |
85 | ConstString GetTypeName() const { return m_type_name; } |
86 | |
87 | TypeImpl GetType() const { return m_type; } |
88 | |
89 | ScriptInterpreter *GetScriptInterpreter() const { |
90 | return m_script_interpreter; |
91 | } |
92 | |
93 | bool DidStripPointer() const { return m_flags.stripped_pointer; } |
94 | |
95 | bool DidStripReference() const { return m_flags.stripped_reference; } |
96 | |
97 | bool DidStripTypedef() const { return m_flags.stripped_typedef; } |
98 | |
99 | template <class Formatter> |
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 | |
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. |
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 | |
165 | TypeNameSpecifierImpl(CompilerType type) |
166 | : m_match_type(lldb::eFormatterMatchExact) { |
167 | if (type.IsValid()) { |
168 | m_type.m_type_name.assign(s: type.GetTypeName().GetCString()); |
169 | m_type.m_compiler_type = type; |
170 | } |
171 | } |
172 | |
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 | |
179 | CompilerType GetCompilerType() { |
180 | if (m_type.m_compiler_type.IsValid()) |
181 | return m_type.m_compiler_type; |
182 | return CompilerType(); |
183 | } |
184 | |
185 | lldb::FormatterMatchType GetMatchType() { return m_match_type; } |
186 | |
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 | |