Hi Jim, Thanks for the encouragement! It's unfortunate that you missed the notifications and couldn't contribute to the code reviews, but I'm glad you think the code looks fine.
Of course I don't mind adding these as a follow-up, it would be a shame if I didn't expose the new feature for CLI users after doing all the work to get to this point. In fact, I was planning to ask about it after landing the change, so thank you for the details about how to proceed next :) On Wed, Oct 19, 2022 at 2:00 PM Jim Ingham <jing...@apple.com> wrote: > Jorge, > > It's great to see you worked your way through this change! > > Something in our mail pipeline is dropping all my lldb-commits and review > comment notifications. Still haven't figured out who is doing that, so I > didn't get a chance to look over the final version. > > The code looks fine, but nobody will know how to use this if they don't > read lldb source code fairly carefully, or browse our tests. > > To finish off the feature, there should be an example to put in the > examples directory, and there should be a paragraph showing how to use it > in lldb/doc/use/formatting.rst. > > It would also be good to add something an option to "type summary add" and > "type synthetic add" to indicate that the name passed is neither a type > name nor a regex but a recognizer function instead. Maybe > -R/--recognizer-function? > > Is it too horrible of me to ask you to do these as a follow-up? Otherwise > I fear you will be the only one to use this feature... > > Jim > > > > On Oct 19, 2022, at 12:54 PM, Jorge Gorbe Moya via lldb-commits < > lldb-commits@lists.llvm.org> wrote: > > > > > > Author: Jorge Gorbe Moya > > Date: 2022-10-19T12:53:38-07:00 > > New Revision: d76566417e592cfac9c710f82575473b1b4a9285 > > > > URL: > https://github.com/llvm/llvm-project/commit/d76566417e592cfac9c710f82575473b1b4a9285 > > DIFF: > https://github.com/llvm/llvm-project/commit/d76566417e592cfac9c710f82575473b1b4a9285.diff > > > > LOG: [lldb] Add matching based on Python callbacks for data formatters. > > > > This patch adds a new matching method for data formatters, in addition > > to the existing exact typename and regex-based matching. The new method > > allows users to specify the name of a Python callback function that > > takes a `SBType` object and decides whether the type is a match or not. > > > > Here is an overview of the changes performed: > > > > - Add a new `eFormatterMatchCallback` matching type, and logic to handle > > it in `TypeMatcher` and `SBTypeNameSpecifier`. > > > > - Extend `FormattersMatchCandidate` instances with a pointer to the > > current `ScriptInterpreter` and the `TypeImpl` corresponding to the > > candidate type, so we can run registered callbacks and pass the type > > to them. All matcher search functions now receive a > > `FormattersMatchCandidate` instead of a type name. > > > > - Add some glue code to ScriptInterpreterPython and the SWIG bindings to > > allow calling a formatter matching callback. Most of this code is > > modeled after the equivalent code for watchpoint callback functions. > > > > - Add an API test for the new callback-based matching feature. > > > > For more context, please check the RFC thread where this feature was > > originally discussed: > > > https://discourse.llvm.org/t/rfc-python-callback-for-data-formatters-type-matching/64204/11 > > > > Differential Revision: https://reviews.llvm.org/D135648 > > > > Added: > > > lldb/test/API/functionalities/data-formatter/callback-matching/Makefile > > > lldb/test/API/functionalities/data-formatter/callback-matching/TestDataFormatterCallbackMatching.py > > > lldb/test/API/functionalities/data-formatter/callback-matching/formatters_with_callback.py > > > lldb/test/API/functionalities/data-formatter/callback-matching/main.cpp > > > > Modified: > > lldb/bindings/python/python-swigsafecast.swig > > lldb/bindings/python/python-wrapper.swig > > lldb/include/lldb/API/SBType.h > > lldb/include/lldb/DataFormatters/DataVisualization.h > > lldb/include/lldb/DataFormatters/FormatClasses.h > > lldb/include/lldb/DataFormatters/FormatManager.h > > lldb/include/lldb/DataFormatters/FormattersContainer.h > > lldb/include/lldb/DataFormatters/TypeCategory.h > > lldb/include/lldb/DataFormatters/TypeCategoryMap.h > > lldb/include/lldb/Interpreter/ScriptInterpreter.h > > lldb/include/lldb/Target/Language.h > > lldb/include/lldb/lldb-enumerations.h > > lldb/source/API/SBTypeNameSpecifier.cpp > > lldb/source/Commands/CommandObjectType.cpp > > lldb/source/DataFormatters/DataVisualization.cpp > > lldb/source/DataFormatters/FormatManager.cpp > > lldb/source/DataFormatters/TypeCategory.cpp > > lldb/source/DataFormatters/TypeCategoryMap.cpp > > lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp > > lldb/source/Plugins/Language/ObjC/ObjCLanguage.h > > lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h > > > lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp > > > lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h > > lldb/source/Target/Language.cpp > > lldb/unittests/DataFormatter/FormattersContainerTest.cpp > > lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp > > > > Removed: > > > > > > > > > ################################################################################ > > diff --git a/lldb/bindings/python/python-swigsafecast.swig > b/lldb/bindings/python/python-swigsafecast.swig > > index eb684133abef..aa5e8e50a2d9 100644 > > --- a/lldb/bindings/python/python-swigsafecast.swig > > +++ b/lldb/bindings/python/python-swigsafecast.swig > > @@ -97,6 +97,10 @@ PythonObject > ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp) { > > SWIGTYPE_p_lldb__SBExecutionContext); > > } > > > > +PythonObject ToSWIGWrapper(lldb::TypeImplSP type_impl_sp) { > > + return ToSWIGHelper(new lldb::SBType(type_impl_sp), > SWIGTYPE_p_lldb__SBType); > > +} > > + > > PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options) { > > return ToSWIGHelper(new lldb::SBTypeSummaryOptions(summary_options), > > SWIGTYPE_p_lldb__SBTypeSummaryOptions); > > > > diff --git a/lldb/bindings/python/python-wrapper.swig > b/lldb/bindings/python/python-wrapper.swig > > index 626fc47bebb9..adac8a405ab9 100644 > > --- a/lldb/bindings/python/python-wrapper.swig > > +++ b/lldb/bindings/python/python-wrapper.swig > > @@ -90,6 +90,32 @@ bool > lldb_private::LLDBSwigPythonWatchpointCallbackFunction( > > return stop_at_watchpoint; > > } > > > > +// This function is called by > > +// ScriptInterpreterPython::FormatterMatchingCallbackFunction and it's > used when > > +// a data formatter provides the name of a callback to inspect a > candidate type > > +// before considering a match. > > +bool lldb_private::LLDBSwigPythonFormatterCallbackFunction( > > + const char *python_function_name, const char > *session_dictionary_name, > > + lldb::TypeImplSP type_impl_sp) { > > + > > + PyErr_Cleaner py_err_cleaner(true); > > + > > + auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>( > > + session_dictionary_name); > > + auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>( > > + python_function_name, dict); > > + > > + if (!pfunc.IsAllocated()) > > + return false; > > + > > + PythonObject result = > > + pfunc(ToSWIGWrapper(type_impl_sp), dict); > > + > > + // Only if everything goes okay and the function returns True we'll > consider > > + // it a match. > > + return result.get() == Py_True; > > +} > > + > > bool lldb_private::LLDBSwigPythonCallTypeScript( > > const char *python_function_name, const void *session_dictionary, > > const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper, > > > > diff --git a/lldb/include/lldb/API/SBType.h > b/lldb/include/lldb/API/SBType.h > > index aa45aeeec476..215e03fad99b 100644 > > --- a/lldb/include/lldb/API/SBType.h > > +++ b/lldb/include/lldb/API/SBType.h > > @@ -106,6 +106,7 @@ class SBType { > > SBType(); > > > > SBType(const lldb::SBType &rhs); > > + SBType(const lldb::TypeImplSP &); > > > > ~SBType(); > > > > @@ -239,7 +240,6 @@ class SBType { > > > > SBType(const lldb_private::CompilerType &); > > SBType(const lldb::TypeSP &); > > - SBType(const lldb::TypeImplSP &); > > }; > > > > class SBTypeList { > > > > diff --git a/lldb/include/lldb/DataFormatters/DataVisualization.h > b/lldb/include/lldb/DataFormatters/DataVisualization.h > > index 7be07d65acdd..5aea29132b8f 100644 > > --- a/lldb/include/lldb/DataFormatters/DataVisualization.h > > +++ b/lldb/include/lldb/DataFormatters/DataVisualization.h > > @@ -51,7 +51,7 @@ class DataVisualization { > > GetSyntheticChildren(ValueObject &valobj, lldb::DynamicValueType > use_dynamic); > > > > static bool > > - AnyMatches(ConstString type_name, > > + AnyMatches(const FormattersMatchCandidate &candidate_type, > > TypeCategoryImpl::FormatCategoryItems items = > > TypeCategoryImpl::ALL_ITEM_TYPES, > > bool only_enabled = true, const char **matching_category = > nullptr, > > > > diff --git a/lldb/include/lldb/DataFormatters/FormatClasses.h > b/lldb/include/lldb/DataFormatters/FormatClasses.h > > index ac2b070a55cd..a6bc3a354253 100644 > > --- a/lldb/include/lldb/DataFormatters/FormatClasses.h > > +++ b/lldb/include/lldb/DataFormatters/FormatClasses.h > > @@ -17,6 +17,7 @@ > > #include "lldb/DataFormatters/TypeFormat.h" > > #include "lldb/DataFormatters/TypeSummary.h" > > #include "lldb/DataFormatters/TypeSynthetic.h" > > +#include "lldb/Interpreter/ScriptInterpreter.h" > > #include "lldb/Symbol/CompilerType.h" > > #include "lldb/Symbol/Type.h" > > #include "lldb/lldb-enumerations.h" > > @@ -73,13 +74,22 @@ class FormattersMatchCandidate { > > } > > }; > > > > - FormattersMatchCandidate(ConstString name, Flags flags) > > - : m_type_name(name), m_flags(flags) {} > > + FormattersMatchCandidate(ConstString name, > > + ScriptInterpreter *script_interpreter, > TypeImpl type, > > + Flags flags) > > + : m_type_name(name), m_script_interpreter(script_interpreter), > > + m_type(type), m_flags(flags) {} > > > > ~FormattersMatchCandidate() = default; > > > > ConstString GetTypeName() const { return m_type_name; } > > > > + TypeImpl GetType() const { return m_type; } > > + > > + ScriptInterpreter *GetScriptInterpreter() const { > > + return m_script_interpreter; > > + } > > + > > bool DidStripPointer() const { return m_flags.stripped_pointer; } > > > > bool DidStripReference() const { return m_flags.stripped_reference; } > > @@ -101,6 +111,10 @@ class FormattersMatchCandidate { > > > > private: > > ConstString m_type_name; > > + // If a formatter provides a matching callback function, we need the > script > > + // interpreter and the type object (as an argument to the callback). > > + ScriptInterpreter *m_script_interpreter; > > + TypeImpl m_type; > > Flags m_flags; > > }; > > > > > > diff --git a/lldb/include/lldb/DataFormatters/FormatManager.h > b/lldb/include/lldb/DataFormatters/FormatManager.h > > index 594addd1f083..295d3b84342a 100644 > > --- a/lldb/include/lldb/DataFormatters/FormatManager.h > > +++ b/lldb/include/lldb/DataFormatters/FormatManager.h > > @@ -128,12 +128,12 @@ class FormatManager : public IFormatChangeListener > { > > GetSyntheticChildren(ValueObject &valobj, lldb::DynamicValueType > use_dynamic); > > > > bool > > - AnyMatches(ConstString type_name, > > + AnyMatches(const FormattersMatchCandidate &candidate_type, > > TypeCategoryImpl::FormatCategoryItems items = > > TypeCategoryImpl::ALL_ITEM_TYPES, > > bool only_enabled = true, const char **matching_category = > nullptr, > > TypeCategoryImpl::FormatCategoryItems *matching_type = > nullptr) { > > - return m_categories_map.AnyMatches(type_name, items, only_enabled, > > + return m_categories_map.AnyMatches(candidate_type, items, > only_enabled, > > matching_category, matching_type); > > } > > > > > > diff --git a/lldb/include/lldb/DataFormatters/FormattersContainer.h > b/lldb/include/lldb/DataFormatters/FormattersContainer.h > > index 8a93c0345cbe..fd046e773b69 100644 > > --- a/lldb/include/lldb/DataFormatters/FormattersContainer.h > > +++ b/lldb/include/lldb/DataFormatters/FormattersContainer.h > > @@ -39,12 +39,16 @@ class IFormatChangeListener { > > > > /// Class for matching type names. > > class TypeMatcher { > > + /// Type name for exact match, or name of the python callback if > m_match_type > > + /// is `eFormatterMatchCallback`. > > + ConstString m_name; > > RegularExpression m_type_name_regex; > > - ConstString m_type_name; > > /// Indicates what kind of matching strategy should be used: > > - /// - eFormatterMatchExact: match the exact type name in m_type_name. > > + /// - eFormatterMatchExact: match the exact type name in m_name. > > /// - eFormatterMatchRegex: match using the RegularExpression object > > /// `m_type_name_regex` instead. > > + /// - eFormatterMatchCallback: run the function in m_name to decide > if a type > > + /// matches or not. > > lldb::FormatterMatchType m_match_type; > > > > // if the user tries to add formatters for, say, "struct Foo" those > will not > > @@ -73,7 +77,7 @@ class TypeMatcher { > > TypeMatcher() = delete; > > /// Creates a matcher that accepts any type with exactly the given > type name. > > TypeMatcher(ConstString type_name) > > - : m_type_name(type_name), > m_match_type(lldb::eFormatterMatchExact) {} > > + : m_name(type_name), m_match_type(lldb::eFormatterMatchExact) {} > > /// Creates a matcher that accepts any type matching the given regex. > > TypeMatcher(RegularExpression regex) > > : m_type_name_regex(std::move(regex)), > > @@ -81,27 +85,44 @@ class TypeMatcher { > > /// Creates a matcher using the matching type and string from the > given type > > /// name specifier. > > TypeMatcher(lldb::TypeNameSpecifierImplSP type_specifier) > > - : m_type_name(type_specifier->GetName()), > > + : m_name(type_specifier->GetName()), > > m_match_type(type_specifier->GetMatchType()) { > > if (m_match_type == lldb::eFormatterMatchRegex) > > m_type_name_regex = RegularExpression(type_specifier->GetName()); > > } > > > > - /// True iff this matches the given type name. > > - bool Matches(ConstString type_name) const { > > - if (m_match_type == lldb::eFormatterMatchRegex) > > + /// True iff this matches the given type. > > + bool Matches(FormattersMatchCandidate candidate_type) const { > > + ConstString type_name = candidate_type.GetTypeName(); > > + switch (m_match_type) { > > + case lldb::eFormatterMatchExact: > > + return m_name == type_name || > > + StripTypeName(m_name) == StripTypeName(type_name); > > + case lldb::eFormatterMatchRegex: > > return m_type_name_regex.Execute(type_name.GetStringRef()); > > - return m_type_name == type_name || > > - StripTypeName(m_type_name) == StripTypeName(type_name); > > + case lldb::eFormatterMatchCallback: > > + // CommandObjectType{Synth,Filter}Add tries to prevent the user > from > > + // creating both a synthetic child provider and a filter for the > same type > > + // in the same category, but we don't have a type object at that > point, so > > + // it creates a dummy candidate without type or script > interpreter. > > + // Skip callback matching in these cases. > > + if (candidate_type.GetScriptInterpreter()) > > + return > candidate_type.GetScriptInterpreter()->FormatterCallbackFunction( > > + m_name.AsCString(), > > + std::make_shared<TypeImpl>(candidate_type.GetType())); > > + } > > + return false; > > } > > > > lldb::FormatterMatchType GetMatchType() const { return m_match_type; } > > > > /// Returns the underlying match string for this TypeMatcher. > > ConstString GetMatchString() const { > > + if (m_match_type == lldb::eFormatterMatchExact) > > + return StripTypeName(m_name); > > if (m_match_type == lldb::eFormatterMatchRegex) > > - return ConstString(m_type_name_regex.GetText()); > > - return StripTypeName(m_type_name); > > + return ConstString(m_type_name_regex.GetText()); > > + return m_name; > > } > > > > /// Returns true if this TypeMatcher and the given one were most > created by > > @@ -155,10 +176,11 @@ template <typename ValueType> class > FormattersContainer { > > return false; > > } > > > > - bool Get(ConstString type, ValueSP &entry) { > > + // Finds the first formatter in the container that matches > `candidate`. > > + bool Get(FormattersMatchCandidate candidate, ValueSP &entry) { > > std::lock_guard<std::recursive_mutex> guard(m_map_mutex); > > for (auto &formatter : llvm::reverse(m_map)) { > > - if (formatter.first.Matches(type)) { > > + if (formatter.first.Matches(candidate)) { > > entry = formatter.second; > > return true; > > } > > @@ -166,9 +188,11 @@ template <typename ValueType> class > FormattersContainer { > > return false; > > } > > > > + // Finds the first match between candidate types in `candidates` and > > + // formatters in this container. > > bool Get(const FormattersMatchVector &candidates, ValueSP &entry) { > > for (const FormattersMatchCandidate &candidate : candidates) { > > - if (Get(candidate.GetTypeName(), entry)) { > > + if (Get(candidate, entry)) { > > if (candidate.IsMatch(entry) == false) { > > entry.reset(); > > continue; > > > > diff --git a/lldb/include/lldb/DataFormatters/TypeCategory.h > b/lldb/include/lldb/DataFormatters/TypeCategory.h > > index bad39aa676af..884a27d76e05 100644 > > --- a/lldb/include/lldb/DataFormatters/TypeCategory.h > > +++ b/lldb/include/lldb/DataFormatters/TypeCategory.h > > @@ -105,10 +105,10 @@ template <typename FormatterImpl> class > TieredFormatterContainer { > > return false; > > } > > > > - bool AnyMatches(ConstString type_name) { > > + bool AnyMatches(const FormattersMatchCandidate &candidate) { > > std::shared_ptr<FormatterImpl> entry; > > for (auto sc : m_subcontainers) { > > - if (sc->Get(type_name, entry)) > > + if (sc->Get(FormattersMatchVector{candidate}, entry)) > > return true; > > } > > return false; > > @@ -346,7 +346,7 @@ class TypeCategoryImpl { > > > > std::string GetDescription(); > > > > - bool AnyMatches(ConstString type_name, > > + bool AnyMatches(const FormattersMatchCandidate &candidate_type, > > FormatCategoryItems items = ALL_ITEM_TYPES, > > bool only_enabled = true, > > const char **matching_category = nullptr, > > > > diff --git a/lldb/include/lldb/DataFormatters/TypeCategoryMap.h > b/lldb/include/lldb/DataFormatters/TypeCategoryMap.h > > index 45dbb306aa75..d4f7634c90b0 100644 > > --- a/lldb/include/lldb/DataFormatters/TypeCategoryMap.h > > +++ b/lldb/include/lldb/DataFormatters/TypeCategoryMap.h > > @@ -17,6 +17,7 @@ > > #include "lldb/lldb-enumerations.h" > > #include "lldb/lldb-public.h" > > > > +#include "lldb/DataFormatters/FormatClasses.h" > > #include "lldb/DataFormatters/FormattersContainer.h" > > #include "lldb/DataFormatters/TypeCategory.h" > > > > @@ -69,7 +70,7 @@ class TypeCategoryMap { > > lldb::TypeCategoryImplSP GetAtIndex(uint32_t); > > > > bool > > - AnyMatches(ConstString type_name, > > + AnyMatches(const FormattersMatchCandidate &candidate_type, > > TypeCategoryImpl::FormatCategoryItems items = > > TypeCategoryImpl::ALL_ITEM_TYPES, > > bool only_enabled = true, const char **matching_category = > nullptr, > > > > diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h > b/lldb/include/lldb/Interpreter/ScriptInterpreter.h > > index cb3cafaf2ed5..f34ce43e946e 100644 > > --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h > > +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h > > @@ -418,6 +418,14 @@ class ScriptInterpreter : public PluginInterface { > > return false; > > } > > > > + // Calls the specified formatter matching Python function and returns > its > > + // result (true if it's a match, false if we should keep looking for a > > + // matching formatter). > > + virtual bool FormatterCallbackFunction(const char *function_name, > > + lldb::TypeImplSP type_impl_sp) > { > > + return true; > > + } > > + > > virtual void Clear() { > > // Clean up any ref counts to SBObjects that might be in global > variables > > } > > > > diff --git a/lldb/include/lldb/Target/Language.h > b/lldb/include/lldb/Target/Language.h > > index fa79aaee0574..89136cc5e0ff 100644 > > --- a/lldb/include/lldb/Target/Language.h > > +++ b/lldb/include/lldb/Target/Language.h > > @@ -175,7 +175,7 @@ class Language : public PluginInterface { > > virtual HardcodedFormatters::HardcodedSyntheticFinder > > GetHardcodedSynthetics(); > > > > - virtual std::vector<ConstString> > > + virtual std::vector<FormattersMatchCandidate> > > GetPossibleFormattersMatches(ValueObject &valobj, > > lldb::DynamicValueType use_dynamic); > > > > > > diff --git a/lldb/include/lldb/lldb-enumerations.h > b/lldb/include/lldb/lldb-enumerations.h > > index 2ac1a74214b4..3ba29a301382 100644 > > --- a/lldb/include/lldb/lldb-enumerations.h > > +++ b/lldb/include/lldb/lldb-enumerations.h > > @@ -835,8 +835,9 @@ enum TemplateArgumentKind { > > enum FormatterMatchType { > > eFormatterMatchExact, > > eFormatterMatchRegex, > > + eFormatterMatchCallback, > > > > - eLastFormatterMatchType = eFormatterMatchRegex, > > + eLastFormatterMatchType = eFormatterMatchCallback, > > }; > > > > /// Options that can be set for a formatter to alter its behavior. Not > > > > diff --git a/lldb/source/API/SBTypeNameSpecifier.cpp > b/lldb/source/API/SBTypeNameSpecifier.cpp > > index d1dc2953c9b9..8a6eb086a9b1 100644 > > --- a/lldb/source/API/SBTypeNameSpecifier.cpp > > +++ b/lldb/source/API/SBTypeNameSpecifier.cpp > > @@ -99,10 +99,14 @@ bool SBTypeNameSpecifier::GetDescription( > > lldb::SBStream &description, lldb::DescriptionLevel > description_level) { > > LLDB_INSTRUMENT_VA(this, description, description_level); > > > > + lldb::FormatterMatchType match_type = GetMatchType(); > > + const char *match_type_str = > > + (match_type == eFormatterMatchExact ? "plain" > > + : match_type == eFormatterMatchRegex ? "regex" > > + : "callback"); > > if (!IsValid()) > > return false; > > - description.Printf("SBTypeNameSpecifier(%s,%s)", GetName(), > > - IsRegex() ? "regex" : "plain"); > > + description.Printf("SBTypeNameSpecifier(%s,%s)", GetName(), > match_type_str); > > return true; > > } > > > > > > diff --git a/lldb/source/Commands/CommandObjectType.cpp > b/lldb/source/Commands/CommandObjectType.cpp > > index 63d3c6979ec3..ccbe7922e65f 100644 > > --- a/lldb/source/Commands/CommandObjectType.cpp > > +++ b/lldb/source/Commands/CommandObjectType.cpp > > @@ -11,6 +11,7 @@ > > #include "lldb/Core/Debugger.h" > > #include "lldb/Core/IOHandler.h" > > #include "lldb/DataFormatters/DataVisualization.h" > > +#include "lldb/DataFormatters/FormatClasses.h" > > #include "lldb/Host/Config.h" > > #include "lldb/Host/OptionParser.h" > > #include "lldb/Interpreter/CommandInterpreter.h" > > @@ -2302,7 +2303,13 @@ bool > CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, > > // an actual type name. Matching a regex string against registered > regexes > > // doesn't work. > > if (type == eRegularSynth) { > > - if (category->AnyMatches(type_name, eFormatCategoryItemFilter, > false)) { > > + // It's not generally possible to get a type object here. For > example, this > > + // command can be run before loading any binaries. Do just a > best-effort > > + // name-based lookup here to try to prevent conflicts. > > + FormattersMatchCandidate candidate_type(type_name, nullptr, > TypeImpl(), > > + > FormattersMatchCandidate::Flags()); > > + if (category->AnyMatches(candidate_type, eFormatCategoryItemFilter, > > + false)) { > > if (error) > > error->SetErrorStringWithFormat("cannot add synthetic for type > %s when " > > "filter is defined in same > category!", > > @@ -2427,7 +2434,14 @@ class CommandObjectTypeFilterAdd : public > CommandObjectParsed { > > // if `type_name` is an actual type name. Matching a regex string > against > > // registered regexes doesn't work. > > if (type == eRegularFilter) { > > - if (category->AnyMatches(type_name, eFormatCategoryItemSynth, > false)) { > > + // It's not generally possible to get a type object here. For > example, > > + // this command can be run before loading any binaries. Do just a > > + // best-effort name-based lookup here to try to prevent conflicts. > > + FormattersMatchCandidate candidate_type( > > + type_name, nullptr, TypeImpl(), > FormattersMatchCandidate::Flags()); > > + lldb::SyntheticChildrenSP entry; > > + if (category->AnyMatches(candidate_type, eFormatCategoryItemSynth, > > + false)) { > > if (error) > > error->SetErrorStringWithFormat("cannot add filter for type %s > when " > > "synthetic is defined in same " > > > > diff --git a/lldb/source/DataFormatters/DataVisualization.cpp > b/lldb/source/DataFormatters/DataVisualization.cpp > > index 53832492aa25..036c9372baf8 100644 > > --- a/lldb/source/DataFormatters/DataVisualization.cpp > > +++ b/lldb/source/DataFormatters/DataVisualization.cpp > > @@ -66,10 +66,11 @@ > DataVisualization::GetSyntheticForType(lldb::TypeNameSpecifierImplSP > type_sp) { > > } > > > > bool DataVisualization::AnyMatches( > > - ConstString type_name, TypeCategoryImpl::FormatCategoryItems items, > > - bool only_enabled, const char **matching_category, > > + const FormattersMatchCandidate &candidate_type, > > + TypeCategoryImpl::FormatCategoryItems items, bool only_enabled, > > + const char **matching_category, > > TypeCategoryImpl::FormatCategoryItems *matching_type) { > > - return GetFormatManager().AnyMatches(type_name, items, only_enabled, > > + return GetFormatManager().AnyMatches(candidate_type, items, > only_enabled, > > matching_category, matching_type); > > } > > > > > > diff --git a/lldb/source/DataFormatters/FormatManager.cpp > b/lldb/source/DataFormatters/FormatManager.cpp > > index db9f6057e842..166264df9933 100644 > > --- a/lldb/source/DataFormatters/FormatManager.cpp > > +++ b/lldb/source/DataFormatters/FormatManager.cpp > > @@ -11,6 +11,7 @@ > > #include "lldb/Core/Debugger.h" > > #include "lldb/DataFormatters/FormattersHelpers.h" > > #include "lldb/DataFormatters/LanguageCategory.h" > > +#include "lldb/Interpreter/ScriptInterpreter.h" > > #include "lldb/Target/ExecutionContext.h" > > #include "lldb/Target/Language.h" > > #include "lldb/Utility/LLDBLog.h" > > @@ -178,19 +179,24 @@ void FormatManager::GetPossibleMatches( > > FormattersMatchCandidate::Flags current_flags, bool root_level) { > > compiler_type = compiler_type.GetTypeForFormatters(); > > ConstString type_name(compiler_type.GetTypeName()); > > + ScriptInterpreter *script_interpreter = > > + valobj.GetTargetSP()->GetDebugger().GetScriptInterpreter(); > > if (valobj.GetBitfieldBitSize() > 0) { > > StreamString sstring; > > sstring.Printf("%s:%d", type_name.AsCString(), > valobj.GetBitfieldBitSize()); > > ConstString bitfieldname(sstring.GetString()); > > - entries.push_back({bitfieldname, current_flags}); > > + entries.push_back({bitfieldname, script_interpreter, > > + TypeImpl(compiler_type), current_flags}); > > } > > > > if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) { > > - entries.push_back({type_name, current_flags}); > > + entries.push_back({type_name, script_interpreter, > TypeImpl(compiler_type), > > + current_flags}); > > > > ConstString display_type_name(compiler_type.GetTypeName()); > > if (display_type_name != type_name) > > - entries.push_back({display_type_name, current_flags}); > > + entries.push_back({display_type_name, script_interpreter, > > + TypeImpl(compiler_type), current_flags}); > > } > > > > for (bool is_rvalue_ref = true, j = true; > > @@ -245,9 +251,9 @@ void FormatManager::GetPossibleMatches( > > for (lldb::LanguageType language_type : > > GetCandidateLanguages(valobj.GetObjectRuntimeLanguage())) { > > if (Language *language = Language::FindPlugin(language_type)) { > > - for (ConstString candidate : > > + for (const FormattersMatchCandidate& candidate : > > language->GetPossibleFormattersMatches(valobj, use_dynamic)) { > > - entries.push_back({candidate, current_flags}); > > + entries.push_back(candidate); > > } > > } > > } > > > > diff --git a/lldb/source/DataFormatters/TypeCategory.cpp > b/lldb/source/DataFormatters/TypeCategory.cpp > > index 1d5674968245..4d8663ea9c03 100644 > > --- a/lldb/source/DataFormatters/TypeCategory.cpp > > +++ b/lldb/source/DataFormatters/TypeCategory.cpp > > @@ -184,20 +184,15 @@ uint32_t > TypeCategoryImpl::GetCount(FormatCategoryItems items) { > > return count; > > } > > > > -bool TypeCategoryImpl::AnyMatches(ConstString type_name, > > - FormatCategoryItems items, bool > only_enabled, > > - const char **matching_category, > > - FormatCategoryItems *matching_type) { > > +bool TypeCategoryImpl::AnyMatches( > > + const FormattersMatchCandidate &candidate_type, FormatCategoryItems > items, > > + bool only_enabled, const char **matching_category, > > + FormatCategoryItems *matching_type) { > > if (!IsEnabled() && only_enabled) > > return false; > > > > - lldb::TypeFormatImplSP format_sp; > > - lldb::TypeSummaryImplSP summary_sp; > > - TypeFilterImpl::SharedPointer filter_sp; > > - ScriptedSyntheticChildren::SharedPointer synth_sp; > > - > > if (items & eFormatCategoryItemFormat) { > > - if (m_format_cont.AnyMatches(type_name)) { > > + if (m_format_cont.AnyMatches(candidate_type)) { > > if (matching_category) > > *matching_category = m_name.GetCString(); > > if (matching_type) > > @@ -207,7 +202,7 @@ bool TypeCategoryImpl::AnyMatches(ConstString > type_name, > > } > > > > if (items & eFormatCategoryItemSummary) { > > - if (m_summary_cont.AnyMatches(type_name)) { > > + if (m_summary_cont.AnyMatches(candidate_type)) { > > if (matching_category) > > *matching_category = m_name.GetCString(); > > if (matching_type) > > @@ -217,7 +212,7 @@ bool TypeCategoryImpl::AnyMatches(ConstString > type_name, > > } > > > > if (items & eFormatCategoryItemFilter) { > > - if (m_filter_cont.AnyMatches(type_name)) { > > + if (m_filter_cont.AnyMatches(candidate_type)) { > > if (matching_category) > > *matching_category = m_name.GetCString(); > > if (matching_type) > > @@ -227,7 +222,7 @@ bool TypeCategoryImpl::AnyMatches(ConstString > type_name, > > } > > > > if (items & eFormatCategoryItemSynth) { > > - if (m_synth_cont.AnyMatches(type_name)) { > > + if (m_synth_cont.AnyMatches(candidate_type)) { > > if (matching_category) > > *matching_category = m_name.GetCString(); > > if (matching_type) > > > > diff --git a/lldb/source/DataFormatters/TypeCategoryMap.cpp > b/lldb/source/DataFormatters/TypeCategoryMap.cpp > > index aa8387b4deec..55635173cc8c 100644 > > --- a/lldb/source/DataFormatters/TypeCategoryMap.cpp > > +++ b/lldb/source/DataFormatters/TypeCategoryMap.cpp > > @@ -154,14 +154,15 @@ bool TypeCategoryMap::Get(uint32_t pos, ValueSP > &entry) { > > } > > > > bool TypeCategoryMap::AnyMatches( > > - ConstString type_name, TypeCategoryImpl::FormatCategoryItems items, > > - bool only_enabled, const char **matching_category, > > + const FormattersMatchCandidate &candidate_type, > > + TypeCategoryImpl::FormatCategoryItems items, bool only_enabled, > > + const char **matching_category, > > TypeCategoryImpl::FormatCategoryItems *matching_type) { > > std::lock_guard<std::recursive_mutex> guard(m_map_mutex); > > > > MapIterator pos, end = m_map.end(); > > for (pos = m_map.begin(); pos != end; pos++) { > > - if (pos->second->AnyMatches(type_name, items, only_enabled, > > + if (pos->second->AnyMatches(candidate_type, items, only_enabled, > > matching_category, matching_type)) > > return true; > > } > > > > diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp > b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp > > index 11d5b0813b58..9cbb40419167 100644 > > --- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp > > +++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp > > @@ -12,6 +12,7 @@ > > > > #include "Plugins/ExpressionParser/Clang/ClangUtil.h" > > #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" > > +#include "lldb/Core/Debugger.h" > > #include "lldb/Core/PluginManager.h" > > #include "lldb/Core/ValueObject.h" > > #include "lldb/DataFormatters/DataVisualization.h" > > @@ -931,10 +932,10 @@ lldb::TypeCategoryImplSP > ObjCLanguage::GetFormatters() { > > return g_category; > > } > > > > -std::vector<ConstString> > > +std::vector<FormattersMatchCandidate> > > ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj, > > lldb::DynamicValueType > use_dynamic) { > > - std::vector<ConstString> result; > > + std::vector<FormattersMatchCandidate> result; > > > > if (use_dynamic == lldb::eNoDynamicValues) > > return result; > > @@ -959,7 +960,10 @@ > ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj, > > if (!objc_class_sp) > > break; > > if (ConstString name = objc_class_sp->GetClassName()) > > - result.push_back(name); > > + result.push_back( > > + {name, > valobj.GetTargetSP()->GetDebugger().GetScriptInterpreter(), > > + TypeImpl(objc_class_sp->GetType()), > > + FormattersMatchCandidate::Flags{}}); > > } while (false); > > } > > > > > > diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h > b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h > > index 914452086db7..b61348a3280e 100644 > > --- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h > > +++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h > > @@ -108,7 +108,7 @@ class ObjCLanguage : public Language { > > > > lldb::TypeCategoryImplSP GetFormatters() override; > > > > - std::vector<ConstString> > > + std::vector<FormattersMatchCandidate> > > GetPossibleFormattersMatches(ValueObject &valobj, > > lldb::DynamicValueType use_dynamic) > override; > > > > > > diff --git > a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h > b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h > > index 4df235356737..7e18b0ef0804 100644 > > --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h > > +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h > > @@ -75,6 +75,10 @@ bool LLDBSwigPythonWatchpointCallbackFunction( > > const char *python_function_name, const char > *session_dictionary_name, > > const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp); > > > > +bool LLDBSwigPythonFormatterCallbackFunction( > > + const char *python_function_name, const char > *session_dictionary_name, > > + lldb::TypeImplSP type_impl_sp); > > + > > bool LLDBSwigPythonCallTypeScript(const char *python_function_name, > > const void *session_dictionary, > > const lldb::ValueObjectSP &valobj_sp, > > > > diff --git > a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp > b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp > > index d0f67a5684c5..37e3c94df870 100644 > > --- > a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp > > +++ > b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp > > @@ -2154,6 +2154,14 @@ bool > ScriptInterpreterPythonImpl::GetScriptedSummary( > > return ret_val; > > } > > > > +bool ScriptInterpreterPythonImpl::FormatterCallbackFunction( > > + const char *python_function_name, TypeImplSP type_impl_sp) { > > + Locker py_lock(this, > > + Locker::AcquireLock | Locker::InitSession | > Locker::NoSTDIN); > > + return LLDBSwigPythonFormatterCallbackFunction( > > + python_function_name, m_dictionary_name.c_str(), type_impl_sp); > > +} > > + > > bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( > > void *baton, StoppointCallbackContext *context, user_id_t break_id, > > user_id_t break_loc_id) { > > > > diff --git > a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h > b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h > > index 3b80c67d201a..f4875bfb8d18 100644 > > --- > a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h > > +++ > b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h > > @@ -202,6 +202,9 @@ class ScriptInterpreterPythonImpl : public > ScriptInterpreterPython { > > const TypeSummaryOptions &options, > > std::string &retval) override; > > > > + bool FormatterCallbackFunction(const char *function_name, > > + lldb::TypeImplSP type_impl_sp) > override; > > + > > bool GetDocumentationForItem(const char *item, std::string &dest) > override; > > > > bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, > > > > diff --git a/lldb/source/Target/Language.cpp > b/lldb/source/Target/Language.cpp > > index 6df36aeeb7b7..92431005cba9 100644 > > --- a/lldb/source/Target/Language.cpp > > +++ b/lldb/source/Target/Language.cpp > > @@ -144,7 +144,7 @@ Language::GetHardcodedSynthetics() { > > return {}; > > } > > > > -std::vector<ConstString> > > +std::vector<FormattersMatchCandidate> > > Language::GetPossibleFormattersMatches(ValueObject &valobj, > > lldb::DynamicValueType > use_dynamic) { > > return {}; > > > > diff --git > a/lldb/test/API/functionalities/data-formatter/callback-matching/Makefile > b/lldb/test/API/functionalities/data-formatter/callback-matching/Makefile > > new file mode 100644 > > index 000000000000..99998b20bcb0 > > --- /dev/null > > +++ > b/lldb/test/API/functionalities/data-formatter/callback-matching/Makefile > > @@ -0,0 +1,3 @@ > > +CXX_SOURCES := main.cpp > > + > > +include Makefile.rules > > > > diff --git > a/lldb/test/API/functionalities/data-formatter/callback-matching/TestDataFormatterCallbackMatching.py > b/lldb/test/API/functionalities/data-formatter/callback-matching/TestDataFormatterCallbackMatching.py > > new file mode 100644 > > index 000000000000..91403d6d5f16 > > --- /dev/null > > +++ > b/lldb/test/API/functionalities/data-formatter/callback-matching/TestDataFormatterCallbackMatching.py > > @@ -0,0 +1,49 @@ > > +""" > > +Test lldb data formatter callback-based matching. > > +""" > > + > > +import lldb > > +from lldbsuite.test.decorators import * > > +from lldbsuite.test.lldbtest import * > > +from lldbsuite.test import lldbutil > > + > > + > > +class PythonSynthDataFormatterTestCase(TestBase): > > + > > + def setUp(self): > > + # Call super's setUp(). > > + TestBase.setUp(self) > > + # Find the line number to break at. > > + self.line = line_number('main.cpp', '// Set break point at this > line.') > > + > > + def test_callback_matchers(self): > > + """Test data formatter commands.""" > > + self.build() > > + > > + _, process, thread, _ = lldbutil.run_to_line_breakpoint( > > + self, lldb.SBFileSpec("main.cpp"), self.line) > > + > > + # Print derived without a formatter. > > + self.expect("frame variable derived", > > + substrs=['x = 2222', > > + 'y = 3333']) > > + > > + # now set up a summary function that uses a python callback to > match > > + # classes that derive from `Base`. > > + self.runCmd("command script import --allow-reload > ./formatters_with_callback.py") > > + > > + # Now `derived` should use our callback summary + synthetic > children. > > + self.expect("frame variable derived", > > + substrs=['hello from callback summary', > > + 'synthetic_child = 9999']) > > + > > + # But not other classes. > > + self.expect("frame variable base", matching=False, > > + substrs=['hello from callback summary']) > > + self.expect("frame variable base", > > + substrs=['x = 1111']) > > + > > + self.expect("frame variable nd", matching=False, > > + substrs=['hello from callback summary']) > > + self.expect("frame variable nd", > > + substrs=['z = 4444']) > > > > diff --git > a/lldb/test/API/functionalities/data-formatter/callback-matching/formatters_with_callback.py > b/lldb/test/API/functionalities/data-formatter/callback-matching/formatters_with_callback.py > > new file mode 100644 > > index 000000000000..60e919a94352 > > --- /dev/null > > +++ > b/lldb/test/API/functionalities/data-formatter/callback-matching/formatters_with_callback.py > > @@ -0,0 +1,39 @@ > > +import lldb > > + > > +def derives_from_base(sbtype, internal_dict): > > + for base in sbtype.get_bases_array(): > > + if base.GetName() == "Base": > > + return True > > + return False > > + > > + > > +class SynthProvider: > > + def __init__(self, valobj, dict): > > + self.valobj = valobj > > + > > + def num_children(self): > > + return 1 > > + > > + def get_child_index(self, name): > > + return 0 > > + > > + def get_child_at_index(self, index): > > + if index == 0: > > + return > self.valobj.CreateValueFromExpression("synthetic_child", > > + "9999") > > + return None > > + > > + > > +def __lldb_init_module(debugger, dict): > > + cat = debugger.CreateCategory("callback_formatters") > > + cat.AddTypeSummary( > > + > lldb.SBTypeNameSpecifier("formatters_with_callback.derives_from_base", > > + lldb.eFormatterMatchCallback), > > + lldb.SBTypeSummary.CreateWithScriptCode( > > + "return 'hello from callback summary'")) > > + cat.AddTypeSynthetic( > > + > lldb.SBTypeNameSpecifier('formatters_with_callback.derives_from_base', > > + lldb.eFormatterMatchCallback), > > + lldb.SBTypeSynthetic.CreateWithClassName( > > + 'formatters_with_callback.SynthProvider')) > > + cat.SetEnabled(True) > > > > diff --git > a/lldb/test/API/functionalities/data-formatter/callback-matching/main.cpp > b/lldb/test/API/functionalities/data-formatter/callback-matching/main.cpp > > new file mode 100644 > > index 000000000000..7732d87342a9 > > --- /dev/null > > +++ > b/lldb/test/API/functionalities/data-formatter/callback-matching/main.cpp > > @@ -0,0 +1,16 @@ > > +struct Base { int x; }; > > +struct Derived : public Base { int y; }; > > + > > +struct NonDerived { int z; }; > > + > > +int main() > > +{ > > + Base base = {1111}; > > + > > + Derived derived; > > + derived.x = 2222; > > + derived.y = 3333; > > + > > + NonDerived nd = {4444}; > > + return 0; // Set break point at this line. > > +} > > > > diff --git a/lldb/unittests/DataFormatter/FormattersContainerTest.cpp > b/lldb/unittests/DataFormatter/FormattersContainerTest.cpp > > index a28212391eae..41b01adfb9ec 100644 > > --- a/lldb/unittests/DataFormatter/FormattersContainerTest.cpp > > +++ b/lldb/unittests/DataFormatter/FormattersContainerTest.cpp > > @@ -7,12 +7,20 @@ > > > //===----------------------------------------------------------------------===// > > > > #include "lldb/DataFormatters/FormattersContainer.h" > > +#include "lldb/DataFormatters/FormatClasses.h" > > > > #include "gtest/gtest.h" > > > > using namespace lldb; > > using namespace lldb_private; > > > > +// Creates a dummy candidate with just a type name in order to test the > string > > +// matching (exact name match and regex match) paths. > > +FormattersMatchCandidate CandidateFromTypeName(const char *type_name) { > > + return FormattersMatchCandidate(ConstString(type_name), nullptr, > TypeImpl(), > > + FormattersMatchCandidate::Flags()); > > +} > > + > > // All the prefixes that the exact name matching will strip from the > type. > > static const std::vector<std::string> exact_name_prefixes = { > > "", // no prefix. > > @@ -25,63 +33,63 @@ TEST(TypeMatcherTests, ExactName) { > > SCOPED_TRACE("Prefix: " + prefix); > > > > TypeMatcher matcher(ConstString(prefix + "Name")); > > - EXPECT_TRUE(matcher.Matches(ConstString("class Name"))); > > - EXPECT_TRUE(matcher.Matches(ConstString("struct Name"))); > > - EXPECT_TRUE(matcher.Matches(ConstString("union Name"))); > > - EXPECT_TRUE(matcher.Matches(ConstString("enum Name"))); > > - EXPECT_TRUE(matcher.Matches(ConstString("Name"))); > > - > > - EXPECT_FALSE(matcher.Matches(ConstString("Name "))); > > - EXPECT_FALSE(matcher.Matches(ConstString("ame"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("Nam"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("am"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("a"))); > > - EXPECT_FALSE(matcher.Matches(ConstString(" "))); > > - EXPECT_FALSE(matcher.Matches(ConstString("class N"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("class "))); > > - EXPECT_FALSE(matcher.Matches(ConstString("class"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("class Name"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("struct Name"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("union Name"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("enum Name"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("Name"))); > > + > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("Name "))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("ame"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("Nam"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("am"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("a"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName(" "))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("class N"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("class "))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("class"))); > > } > > } > > > > // TypeMatcher that uses a regex to match a type name. > > TEST(TypeMatcherTests, RegexName) { > > TypeMatcher matcher(RegularExpression("^a[a-z]c$")); > > - EXPECT_TRUE(matcher.Matches(ConstString("abc"))); > > - EXPECT_TRUE(matcher.Matches(ConstString("azc"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("abc"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("azc"))); > > > > // FIXME: This isn't consistent with the 'exact' type name matches > above. > > - EXPECT_FALSE(matcher.Matches(ConstString("class abc"))); > > - > > - EXPECT_FALSE(matcher.Matches(ConstString("abbc"))); > > - EXPECT_FALSE(matcher.Matches(ConstString(" abc"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("abc "))); > > - EXPECT_FALSE(matcher.Matches(ConstString(" abc "))); > > - EXPECT_FALSE(matcher.Matches(ConstString("XabcX"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("ac"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("a[a-z]c"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("aAc"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("ABC"))); > > - EXPECT_FALSE(matcher.Matches(ConstString(""))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("class abc"))); > > + > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("abbc"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName(" abc"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("abc "))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName(" abc "))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("XabcX"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("ac"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("a[a-z]c"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("aAc"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("ABC"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName(""))); > > } > > > > // TypeMatcher that only searches the type name. > > TEST(TypeMatcherTests, RegexMatchPart) { > > TypeMatcher matcher(RegularExpression("a[a-z]c")); > > - EXPECT_TRUE(matcher.Matches(ConstString("class abc"))); > > - EXPECT_TRUE(matcher.Matches(ConstString("abc"))); > > - EXPECT_TRUE(matcher.Matches(ConstString(" abc "))); > > - EXPECT_TRUE(matcher.Matches(ConstString("azc"))); > > - EXPECT_TRUE(matcher.Matches(ConstString("abc "))); > > - EXPECT_TRUE(matcher.Matches(ConstString(" abc "))); > > - EXPECT_TRUE(matcher.Matches(ConstString(" abc"))); > > - EXPECT_TRUE(matcher.Matches(ConstString("XabcX"))); > > - > > - EXPECT_FALSE(matcher.Matches(ConstString("abbc"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("ac"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("a[a-z]c"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("aAc"))); > > - EXPECT_FALSE(matcher.Matches(ConstString("ABC"))); > > - EXPECT_FALSE(matcher.Matches(ConstString(""))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("class abc"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("abc"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName(" abc "))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("azc"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("abc "))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName(" abc "))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName(" abc"))); > > + EXPECT_TRUE(matcher.Matches(CandidateFromTypeName("XabcX"))); > > + > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("abbc"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("ac"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("a[a-z]c"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("aAc"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName("ABC"))); > > + EXPECT_FALSE(matcher.Matches(CandidateFromTypeName(""))); > > } > > > > // GetMatchString for exact type name matchers. > > > > diff --git > a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp > b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp > > index 6ac4606b5a84..87e4a03ee77b 100644 > > --- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp > > +++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp > > @@ -67,6 +67,12 @@ bool > lldb_private::LLDBSwigPythonWatchpointCallbackFunction( > > return false; > > } > > > > +bool lldb_private::LLDBSwigPythonFormatterCallbackFunction( > > + const char *python_function_name, const char > *session_dictionary_name, > > + lldb::TypeImplSP type_impl_sp) { > > + return false; > > +} > > + > > bool lldb_private::LLDBSwigPythonCallTypeScript( > > const char *python_function_name, const void *session_dictionary, > > const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper, > > > > > > > > _______________________________________________ > > lldb-commits mailing list > > lldb-commits@lists.llvm.org > > https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits > >
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits