10b57cec5SDimitry Andric //===-- FormatClasses.h -----------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLDB_DATAFORMATTERS_FORMATCLASSES_H
105ffd83dbSDimitry Andric #define LLDB_DATAFORMATTERS_FORMATCLASSES_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include <functional>
130b57cec5SDimitry Andric #include <memory>
140b57cec5SDimitry Andric #include <string>
150b57cec5SDimitry Andric #include <vector>
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeFormat.h"
180b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h"
190b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeSynthetic.h"
20bdd1243dSDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
210b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
220b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
230b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h"
240b57cec5SDimitry Andric #include "lldb/lldb-public.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace lldb_private {
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric class HardcodedFormatters {
290b57cec5SDimitry Andric public:
300b57cec5SDimitry Andric   template <typename FormatterType>
310b57cec5SDimitry Andric   using HardcodedFormatterFinder =
320b57cec5SDimitry Andric       std::function<typename FormatterType::SharedPointer(
330b57cec5SDimitry Andric           lldb_private::ValueObject &, lldb::DynamicValueType,
340b57cec5SDimitry Andric           FormatManager &)>;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   template <typename FormatterType>
370b57cec5SDimitry Andric   using HardcodedFormatterFinders =
380b57cec5SDimitry Andric       std::vector<HardcodedFormatterFinder<FormatterType>>;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   typedef HardcodedFormatterFinders<TypeFormatImpl> HardcodedFormatFinder;
410b57cec5SDimitry Andric   typedef HardcodedFormatterFinders<TypeSummaryImpl> HardcodedSummaryFinder;
420b57cec5SDimitry Andric   typedef HardcodedFormatterFinders<SyntheticChildren> HardcodedSyntheticFinder;
430b57cec5SDimitry Andric };
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric class FormattersMatchCandidate {
460b57cec5SDimitry Andric public:
47bdd1243dSDimitry Andric   // Contains flags to indicate how this candidate was generated (e.g. if
48bdd1243dSDimitry Andric   // typedefs were stripped, or pointers were skipped). These are later compared
49bdd1243dSDimitry Andric   // to flags in formatters to confirm a string match.
50bdd1243dSDimitry Andric   struct Flags {
51bdd1243dSDimitry Andric     bool stripped_pointer = false;
52bdd1243dSDimitry Andric     bool stripped_reference = false;
53bdd1243dSDimitry Andric     bool stripped_typedef = false;
54bdd1243dSDimitry Andric 
55bdd1243dSDimitry Andric     // Returns a copy of this with the "stripped pointer" flag set.
WithStrippedPointerFlags56bdd1243dSDimitry Andric     Flags WithStrippedPointer() {
57bdd1243dSDimitry Andric       Flags result(*this);
58bdd1243dSDimitry Andric       result.stripped_pointer = true;
59bdd1243dSDimitry Andric       return result;
60bdd1243dSDimitry Andric     }
61bdd1243dSDimitry Andric 
62bdd1243dSDimitry Andric     // Returns a copy of this with the "stripped reference" flag set.
WithStrippedReferenceFlags63bdd1243dSDimitry Andric     Flags WithStrippedReference() {
64bdd1243dSDimitry Andric       Flags result(*this);
65bdd1243dSDimitry Andric       result.stripped_reference = true;
66bdd1243dSDimitry Andric       return result;
67bdd1243dSDimitry Andric     }
68bdd1243dSDimitry Andric 
69bdd1243dSDimitry Andric     // Returns a copy of this with the "stripped typedef" flag set.
WithStrippedTypedefFlags70bdd1243dSDimitry Andric     Flags WithStrippedTypedef() {
71bdd1243dSDimitry Andric       Flags result(*this);
72bdd1243dSDimitry Andric       result.stripped_typedef = true;
73bdd1243dSDimitry Andric       return result;
74bdd1243dSDimitry Andric     }
75bdd1243dSDimitry Andric   };
76bdd1243dSDimitry Andric 
FormattersMatchCandidate(ConstString name,ScriptInterpreter * script_interpreter,TypeImpl type,Flags flags)77bdd1243dSDimitry Andric   FormattersMatchCandidate(ConstString name,
78bdd1243dSDimitry Andric                            ScriptInterpreter *script_interpreter, TypeImpl type,
79bdd1243dSDimitry Andric                            Flags flags)
80bdd1243dSDimitry Andric       : m_type_name(name), m_script_interpreter(script_interpreter),
81bdd1243dSDimitry Andric         m_type(type), m_flags(flags) {}
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   ~FormattersMatchCandidate() = default;
840b57cec5SDimitry Andric 
GetTypeName()850b57cec5SDimitry Andric   ConstString GetTypeName() const { return m_type_name; }
860b57cec5SDimitry Andric 
GetType()87bdd1243dSDimitry Andric   TypeImpl GetType() const { return m_type; }
880b57cec5SDimitry Andric 
GetScriptInterpreter()89bdd1243dSDimitry Andric   ScriptInterpreter *GetScriptInterpreter() const {
90bdd1243dSDimitry Andric     return m_script_interpreter;
91bdd1243dSDimitry Andric   }
920b57cec5SDimitry Andric 
DidStripPointer()93bdd1243dSDimitry Andric   bool DidStripPointer() const { return m_flags.stripped_pointer; }
94bdd1243dSDimitry Andric 
DidStripReference()95bdd1243dSDimitry Andric   bool DidStripReference() const { return m_flags.stripped_reference; }
96bdd1243dSDimitry Andric 
DidStripTypedef()97bdd1243dSDimitry Andric   bool DidStripTypedef() const { return m_flags.stripped_typedef; }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   template <class Formatter>
IsMatch(const std::shared_ptr<Formatter> & formatter_sp)1000b57cec5SDimitry Andric   bool IsMatch(const std::shared_ptr<Formatter> &formatter_sp) const {
1010b57cec5SDimitry Andric     if (!formatter_sp)
1020b57cec5SDimitry Andric       return false;
1030b57cec5SDimitry Andric     if (formatter_sp->Cascades() == false && DidStripTypedef())
1040b57cec5SDimitry Andric       return false;
1050b57cec5SDimitry Andric     if (formatter_sp->SkipsPointers() && DidStripPointer())
1060b57cec5SDimitry Andric       return false;
1070b57cec5SDimitry Andric     if (formatter_sp->SkipsReferences() && DidStripReference())
1080b57cec5SDimitry Andric       return false;
1090b57cec5SDimitry Andric     return true;
1100b57cec5SDimitry Andric   }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric private:
1130b57cec5SDimitry Andric   ConstString m_type_name;
114bdd1243dSDimitry Andric   // If a formatter provides a matching callback function, we need the script
115bdd1243dSDimitry Andric   // interpreter and the type object (as an argument to the callback).
116bdd1243dSDimitry Andric   ScriptInterpreter *m_script_interpreter;
117bdd1243dSDimitry Andric   TypeImpl m_type;
118bdd1243dSDimitry Andric   Flags m_flags;
1190b57cec5SDimitry Andric };
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric typedef std::vector<FormattersMatchCandidate> FormattersMatchVector;
1220b57cec5SDimitry Andric typedef std::vector<lldb::LanguageType> CandidateLanguagesVector;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric class FormattersMatchData {
1250b57cec5SDimitry Andric public:
1260b57cec5SDimitry Andric   FormattersMatchData(ValueObject &, lldb::DynamicValueType);
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   FormattersMatchVector GetMatchesVector();
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   ConstString GetTypeForCache();
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   CandidateLanguagesVector GetCandidateLanguages();
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   ValueObject &GetValueObject();
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   lldb::DynamicValueType GetDynamicValueType();
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric private:
1390b57cec5SDimitry Andric   ValueObject &m_valobj;
1400b57cec5SDimitry Andric   lldb::DynamicValueType m_dynamic_value_type;
1410b57cec5SDimitry Andric   std::pair<FormattersMatchVector, bool> m_formatters_match_vector;
1420b57cec5SDimitry Andric   ConstString m_type_for_cache;
1430b57cec5SDimitry Andric   CandidateLanguagesVector m_candidate_languages;
1440b57cec5SDimitry Andric };
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric class TypeNameSpecifierImpl {
1470b57cec5SDimitry Andric public:
14881ad6265SDimitry Andric   TypeNameSpecifierImpl() = default;
1490b57cec5SDimitry Andric 
TypeNameSpecifierImpl(llvm::StringRef name,lldb::FormatterMatchType match_type)150bdd1243dSDimitry Andric   TypeNameSpecifierImpl(llvm::StringRef name,
151bdd1243dSDimitry Andric                         lldb::FormatterMatchType match_type)
152bdd1243dSDimitry Andric       : m_match_type(match_type) {
1535ffd83dbSDimitry Andric     m_type.m_type_name = std::string(name);
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
156bdd1243dSDimitry Andric   // if constructing with a given type, we consider that a case of exact match.
TypeNameSpecifierImpl(lldb::TypeSP type)157bdd1243dSDimitry Andric   TypeNameSpecifierImpl(lldb::TypeSP type)
158bdd1243dSDimitry Andric       : m_match_type(lldb::eFormatterMatchExact) {
1590b57cec5SDimitry Andric     if (type) {
1605ffd83dbSDimitry Andric       m_type.m_type_name = std::string(type->GetName().GetStringRef());
1610b57cec5SDimitry Andric       m_type.m_compiler_type = type->GetForwardCompilerType();
1620b57cec5SDimitry Andric     }
1630b57cec5SDimitry Andric   }
1640b57cec5SDimitry Andric 
TypeNameSpecifierImpl(CompilerType type)165bdd1243dSDimitry Andric   TypeNameSpecifierImpl(CompilerType type)
166bdd1243dSDimitry Andric       : m_match_type(lldb::eFormatterMatchExact) {
1670b57cec5SDimitry Andric     if (type.IsValid()) {
1685ffd83dbSDimitry Andric       m_type.m_type_name.assign(type.GetTypeName().GetCString());
1690b57cec5SDimitry Andric       m_type.m_compiler_type = type;
1700b57cec5SDimitry Andric     }
1710b57cec5SDimitry Andric   }
1720b57cec5SDimitry Andric 
GetName()1730b57cec5SDimitry Andric   const char *GetName() {
1740b57cec5SDimitry Andric     if (m_type.m_type_name.size())
1750b57cec5SDimitry Andric       return m_type.m_type_name.c_str();
1760b57cec5SDimitry Andric     return nullptr;
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric 
GetCompilerType()1790b57cec5SDimitry Andric   CompilerType GetCompilerType() {
1800b57cec5SDimitry Andric     if (m_type.m_compiler_type.IsValid())
1810b57cec5SDimitry Andric       return m_type.m_compiler_type;
1820b57cec5SDimitry Andric     return CompilerType();
1830b57cec5SDimitry Andric   }
1840b57cec5SDimitry Andric 
GetMatchType()185bdd1243dSDimitry Andric   lldb::FormatterMatchType GetMatchType() { return m_match_type; }
186bdd1243dSDimitry Andric 
IsRegex()187bdd1243dSDimitry Andric   bool IsRegex() { return m_match_type == lldb::eFormatterMatchRegex; }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric private:
190bdd1243dSDimitry Andric   lldb::FormatterMatchType m_match_type = lldb::eFormatterMatchExact;
1910b57cec5SDimitry Andric   // TODO: Replace this with TypeAndOrName.
1920b57cec5SDimitry Andric   struct TypeOrName {
1930b57cec5SDimitry Andric     std::string m_type_name;
1940b57cec5SDimitry Andric     CompilerType m_compiler_type;
1950b57cec5SDimitry Andric   };
1960b57cec5SDimitry Andric   TypeOrName m_type;
1970b57cec5SDimitry Andric 
1985ffd83dbSDimitry Andric   TypeNameSpecifierImpl(const TypeNameSpecifierImpl &) = delete;
1995ffd83dbSDimitry Andric   const TypeNameSpecifierImpl &
2005ffd83dbSDimitry Andric   operator=(const TypeNameSpecifierImpl &) = delete;
2010b57cec5SDimitry Andric };
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric } // namespace lldb_private
2040b57cec5SDimitry Andric 
2055ffd83dbSDimitry Andric #endif // LLDB_DATAFORMATTERS_FORMATCLASSES_H
206