Skip to content

Commit d26eb90

Browse files
author
Siva Chandra
committedJul 24, 2015
Add option eTypeOptionHideEmptyAggregates.
Summary: For certain data structures, when the synthetic child provider returns zero children, a summary like "Empty instance of <typename>" could be more appropriate than something like "size=0 {}". This new option helps hide the trailing "{}". This is also exposed with a -h option for the command "type summary add". Reviewers: granata.enrico Subscribers: lldb-commits Differential Revision: http://reviews.llvm.org/D11473 llvm-svn: 243166
1 parent fd4dfdc commit d26eb90

File tree

10 files changed

+113
-12
lines changed

10 files changed

+113
-12
lines changed
 

‎lldb/include/lldb/DataFormatters/TypeSummary.h

+22
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,22 @@ namespace lldb_private {
162162
m_flags &= ~lldb::eTypeOptionHideChildren;
163163
return *this;
164164
}
165+
166+
bool
167+
GetHideEmptyAggregates () const
168+
{
169+
return (m_flags & lldb::eTypeOptionHideEmptyAggregates) == lldb::eTypeOptionHideEmptyAggregates;
170+
}
171+
172+
Flags&
173+
SetHideEmptyAggregates (bool value = true)
174+
{
175+
if (value)
176+
m_flags |= lldb::eTypeOptionHideEmptyAggregates;
177+
else
178+
m_flags &= ~lldb::eTypeOptionHideEmptyAggregates;
179+
return *this;
180+
}
165181

166182
bool
167183
GetDontShowValue () const
@@ -279,6 +295,12 @@ namespace lldb_private {
279295
{
280296
return !m_flags.GetDontShowChildren();
281297
}
298+
299+
virtual bool
300+
DoesPrintEmptyAggregates () const
301+
{
302+
return !m_flags.GetHideEmptyAggregates();
303+
}
282304

283305
virtual bool
284306
DoesPrintValue (ValueObject* valobj) const

‎lldb/include/lldb/DataFormatters/ValueObjectPrinter.h

+3
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,9 @@ class ValueObjectPrinter
344344
bool
345345
ShouldPrintChildren (bool is_failed_description,
346346
uint32_t& curr_ptr_depth);
347+
348+
bool
349+
ShouldExpandEmptyAggregates ();
347350

348351
ValueObject*
349352
GetValueObjectForChildrenGeneration ();

‎lldb/include/lldb/lldb-enumerations.h

+10-9
Original file line numberDiff line numberDiff line change
@@ -729,15 +729,16 @@ namespace lldb {
729729
//----------------------------------------------------------------------
730730
FLAGS_ENUM(TypeOptions)
731731
{
732-
eTypeOptionNone = (0u),
733-
eTypeOptionCascade = (1u << 0),
734-
eTypeOptionSkipPointers = (1u << 1),
735-
eTypeOptionSkipReferences = (1u << 2),
736-
eTypeOptionHideChildren = (1u << 3),
737-
eTypeOptionHideValue = (1u << 4),
738-
eTypeOptionShowOneLiner = (1u << 5),
739-
eTypeOptionHideNames = (1u << 6),
740-
eTypeOptionNonCacheable = (1u << 7)
732+
eTypeOptionNone = (0u),
733+
eTypeOptionCascade = (1u << 0),
734+
eTypeOptionSkipPointers = (1u << 1),
735+
eTypeOptionSkipReferences = (1u << 2),
736+
eTypeOptionHideChildren = (1u << 3),
737+
eTypeOptionHideValue = (1u << 4),
738+
eTypeOptionShowOneLiner = (1u << 5),
739+
eTypeOptionHideNames = (1u << 6),
740+
eTypeOptionNonCacheable = (1u << 7),
741+
eTypeOptionHideEmptyAggregates = (1u << 8)
741742
};
742743

743744
//----------------------------------------------------------------------

‎lldb/source/Commands/CommandObjectType.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1438,6 +1438,9 @@ CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx
14381438
case 'e':
14391439
m_flags.SetDontShowChildren(false);
14401440
break;
1441+
case 'h':
1442+
m_flags.SetHideEmptyAggregates(true);
1443+
break;
14411444
case 'v':
14421445
m_flags.SetDontShowValue(true);
14431446
break;
@@ -1924,6 +1927,7 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
19241927
{ LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."},
19251928
{ LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."},
19261929
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."},
1930+
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Do not expand aggregate data types with no children."},
19271931
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "A name for this summary string."},
19281932
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
19291933
};

‎lldb/source/DataFormatters/ValueObjectPrinter.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,17 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
480480
return false;
481481
}
482482

483+
bool
484+
ValueObjectPrinter::ShouldExpandEmptyAggregates ()
485+
{
486+
TypeSummaryImpl* entry = GetSummaryFormatter();
487+
488+
if (!entry)
489+
return true;
490+
491+
return entry->DoesPrintEmptyAggregates();
492+
}
493+
483494
ValueObject*
484495
ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
485496
{
@@ -582,7 +593,7 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
582593
if (ShouldPrintValueObject())
583594
{
584595
// if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value
585-
if (m_valobj->DoesProvideSyntheticValue())
596+
if (m_valobj->DoesProvideSyntheticValue() || !ShouldExpandEmptyAggregates())
586597
m_stream->PutCString( "\n");
587598
else
588599
m_stream->PutCString(" {}\n");

‎lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py

+6
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ def cleanup():
208208
self.expect('frame variable bag_bag',
209209
substrs = ['x.z = 12'])
210210

211+
self.runCmd('type summary add -e -s "I am always empty but have" EmptyStruct')
212+
self.expect('frame variable es', substrs = ["I am always empty but have {}"])
213+
self.runCmd('type summary add -e -h -s "I am really empty" EmptyStruct')
214+
self.expect('frame variable es', substrs = ["I am really empty"])
215+
self.expect('frame variable es', substrs = ["I am really empty {}"], matching=False)
216+
211217

212218
if __name__ == '__main__':
213219
import atexit

‎lldb/test/functionalities/data-formatter/data-formatter-synth/main.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ struct BagOfBags
4646
q(20.11) {}
4747
};
4848

49+
struct EmptyStruct {};
50+
4951
struct Plenty
5052
{
5153
BagOfInts *some_values;
@@ -70,6 +72,7 @@ int main (int argc, const char * argv[])
7072
BagOfFloats float_bag(2.71);
7173

7274
BagOfBags bag_bag;
75+
EmptyStruct es;
7376

7477
Plenty plenty_of_stuff(5,true,false);
7578

‎lldb/test/python_api/formatters/TestFormattersSBAPI.py

+4
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ def cleanup():
302302
self.assertTrue(summary.IsValid(), "no summary found for foo* when one was in place")
303303
self.assertTrue(summary.GetData() == "hello static world", "wrong summary found for foo*")
304304

305+
self.expect("frame variable e1", substrs=["I am an empty Empty1 {}"])
306+
self.expect("frame variable e2", substrs=["I am an empty Empty2"])
307+
self.expect("frame variable e2", substrs=["I am an empty Empty2 {}"], matching=False)
308+
305309
def force_synth_off(self):
306310
"""Test that one can have the public API return non-synthetic SBValues if desired"""
307311
self.runCmd("file no_synth", CURRENT_EXECUTABLE_SET)

‎lldb/test/python_api/formatters/main.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ struct CCC
2626
int a, b, c;
2727
};
2828

29+
struct Empty1 { void *data; };
30+
struct Empty2 { void *data; };
31+
2932

3033
int main(int argc, char const *argv[]) {
3134
JustAStruct foo;
@@ -49,5 +52,8 @@ int main(int argc, char const *argv[]) {
4952

5053
CCC ccc = {111, 222, 333};
5154

55+
Empty1 e1;
56+
Empty2 e2;
57+
5258
return 0; // Set break point at this line.
5359
}

‎lldb/test/python_api/formatters/synth.py

+43-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,36 @@ def get_child_at_index(self, index):
4848
return self._sbvalue.GetChildMemberWithName("c")
4949

5050

51+
def empty1_summary(sbvalue, internal_dict):
52+
return "I am an empty Empty1"
53+
54+
55+
class Empty1SynthProvider(object):
56+
def __init__(self, sbvalue, internal_dict):
57+
self._sbvalue = sbvalue
58+
59+
def num_children(self):
60+
return 0
61+
62+
def get_child_at_index(self, index):
63+
return None
64+
65+
66+
def empty2_summary(sbvalue, internal_dict):
67+
return "I am an empty Empty2"
68+
69+
70+
class Empty2SynthProvider(object):
71+
def __init__(self, sbvalue, internal_dict):
72+
self._sbvalue = sbvalue
73+
74+
def num_children(self):
75+
return 0
76+
77+
def get_child_at_index(self, index):
78+
return None
79+
80+
5181
def __lldb_init_module(debugger,dict):
5282
debugger.CreateCategory("JASSynth").AddTypeSynthetic(lldb.SBTypeNameSpecifier("JustAStruct"),
5383
lldb.SBTypeSynthetic.CreateWithClassName("synth.jasSynthProvider"))
@@ -60,5 +90,16 @@ def __lldb_init_module(debugger,dict):
6090
lldb.SBTypeNameSpecifier("CCC"),
6191
lldb.SBTypeSummary.CreateWithFunctionName("synth.ccc_summary",
6292
lldb.eTypeOptionCascade))
63-
64-
93+
cat.AddTypeSynthetic(
94+
lldb.SBTypeNameSpecifier("Empty1"),
95+
lldb.SBTypeSynthetic.CreateWithClassName("synth.Empty1SynthProvider"))
96+
cat.AddTypeSummary(
97+
lldb.SBTypeNameSpecifier("Empty1"),
98+
lldb.SBTypeSummary.CreateWithFunctionName("synth.empty1_summary"))
99+
cat.AddTypeSynthetic(
100+
lldb.SBTypeNameSpecifier("Empty2"),
101+
lldb.SBTypeSynthetic.CreateWithClassName("synth.Empty2SynthProvider"))
102+
cat.AddTypeSummary(
103+
lldb.SBTypeNameSpecifier("Empty2"),
104+
lldb.SBTypeSummary.CreateWithFunctionName("synth.empty2_summary",
105+
lldb.eTypeOptionHideEmptyAggregates))

0 commit comments

Comments
 (0)
Please sign in to comment.