llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) <details> <summary>Changes</summary> Add a `--changed`/`-c` flag to `settings show` that restricts the output to settings whose current value differs from the default. This makes it easy to inspect what has been customized in a session or config without scrolling through the full property tree. One thing worth calling out is that this works as expected with explicit property paths, for example you can show only the modified settings belonging to `target`: ``` (lldb) sett show --changed target target.load-script-from-symbol-file (enum) = true (lldb) ``` If nothing has been changed, the output is empty: ``` (lldb) sett show -c target.process (lldb) ``` rdar://176483441 --- Full diff: https://github.com/llvm/llvm-project/pull/196390.diff 18 Files Affected: - (modified) lldb/include/lldb/Interpreter/OptionValue.h (+8) - (modified) lldb/include/lldb/Interpreter/OptionValueArch.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueBoolean.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueChar.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueEnumeration.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueFileSpec.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueFormat.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueFormatEntity.h (+4) - (modified) lldb/include/lldb/Interpreter/OptionValueLanguage.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueProperties.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueRegex.h (+4) - (modified) lldb/include/lldb/Interpreter/OptionValueSInt64.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueString.h (+2) - (modified) lldb/include/lldb/Interpreter/OptionValueUInt64.h (+2) - (modified) lldb/source/Commands/CommandObjectSettings.cpp (+14) - (modified) lldb/source/Commands/Options.td (+3) - (modified) lldb/source/Interpreter/OptionValueProperties.cpp (+11) - (modified) lldb/test/API/commands/settings/TestSettings.py (+48) ``````````diff diff --git a/lldb/include/lldb/Interpreter/OptionValue.h b/lldb/include/lldb/Interpreter/OptionValue.h index 9c992821251cb..7e48a675e2b7f 100644 --- a/lldb/include/lldb/Interpreter/OptionValue.h +++ b/lldb/include/lldb/Interpreter/OptionValue.h @@ -63,6 +63,7 @@ class OptionValue { eDumpOptionRaw = (1u << 4), eDumpOptionCommand = (1u << 5), eDumpOptionDefaultValue = (1u << 6), + eDumpOptionOnlyChanged = (1u << 7), eDumpGroupValue = (eDumpOptionName | eDumpOptionType | eDumpOptionValue), eDumpGroupHelp = (eDumpOptionName | eDumpOptionType | eDumpOptionDescription), @@ -249,6 +250,13 @@ class OptionValue { void SetOptionWasSet() { m_value_was_set = true; } + /// Return true if the current value equals the default value. + /// + /// Subclasses that store a default value should override this to compare + /// against it. The base implementation falls back to `OptionWasSet()`, which + /// is a reasonable approximation for types without an explicit default. + virtual bool IsDefault() const { return !OptionWasSet(); } + void SetParent(const lldb::OptionValueSP &parent_sp) { m_parent_wp = parent_sp; } diff --git a/lldb/include/lldb/Interpreter/OptionValueArch.h b/lldb/include/lldb/Interpreter/OptionValueArch.h index 3ba07b65dd618..8b6954f03dd29 100644 --- a/lldb/include/lldb/Interpreter/OptionValueArch.h +++ b/lldb/include/lldb/Interpreter/OptionValueArch.h @@ -49,6 +49,8 @@ class OptionValueArch : public Cloneable<OptionValueArch, OptionValue> { m_value_was_set = false; } + bool IsDefault() const override { return m_current_value == m_default_value; } + void AutoComplete(CommandInterpreter &interpreter, lldb_private::CompletionRequest &request) override; diff --git a/lldb/include/lldb/Interpreter/OptionValueBoolean.h b/lldb/include/lldb/Interpreter/OptionValueBoolean.h index 6d15dcd2fca5d..72c1ce446b8a0 100644 --- a/lldb/include/lldb/Interpreter/OptionValueBoolean.h +++ b/lldb/include/lldb/Interpreter/OptionValueBoolean.h @@ -45,6 +45,8 @@ class OptionValueBoolean : public Cloneable<OptionValueBoolean, OptionValue> { void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) override; + bool IsDefault() const override { return m_current_value == m_default_value; } + // Subclass specific functions /// Convert to bool operator. diff --git a/lldb/include/lldb/Interpreter/OptionValueChar.h b/lldb/include/lldb/Interpreter/OptionValueChar.h index 2e2cf1ac1e08d..c1f83a3daf846 100644 --- a/lldb/include/lldb/Interpreter/OptionValueChar.h +++ b/lldb/include/lldb/Interpreter/OptionValueChar.h @@ -43,6 +43,8 @@ class OptionValueChar : public Cloneable<OptionValueChar, OptionValue> { m_value_was_set = false; } + bool IsDefault() const override { return m_current_value == m_default_value; } + // Subclass specific functions const char &operator=(char c) { diff --git a/lldb/include/lldb/Interpreter/OptionValueEnumeration.h b/lldb/include/lldb/Interpreter/OptionValueEnumeration.h index 91ab454b2065e..e8566934d9fc5 100644 --- a/lldb/include/lldb/Interpreter/OptionValueEnumeration.h +++ b/lldb/include/lldb/Interpreter/OptionValueEnumeration.h @@ -52,6 +52,8 @@ class OptionValueEnumeration m_value_was_set = false; } + bool IsDefault() const override { return m_current_value == m_default_value; } + void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) override; diff --git a/lldb/include/lldb/Interpreter/OptionValueFileSpec.h b/lldb/include/lldb/Interpreter/OptionValueFileSpec.h index 66c5e328180f5..66f2b2a04ff53 100644 --- a/lldb/include/lldb/Interpreter/OptionValueFileSpec.h +++ b/lldb/include/lldb/Interpreter/OptionValueFileSpec.h @@ -53,6 +53,8 @@ class OptionValueFileSpec : public Cloneable<OptionValueFileSpec, OptionValue> { void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) override; + bool IsDefault() const override { return m_current_value == m_default_value; } + // Subclass specific functions FileSpec &GetCurrentValue() { return m_current_value; } diff --git a/lldb/include/lldb/Interpreter/OptionValueFormat.h b/lldb/include/lldb/Interpreter/OptionValueFormat.h index 5fd3192304573..661e8b507d64f 100644 --- a/lldb/include/lldb/Interpreter/OptionValueFormat.h +++ b/lldb/include/lldb/Interpreter/OptionValueFormat.h @@ -42,6 +42,8 @@ class OptionValueFormat m_value_was_set = false; } + bool IsDefault() const override { return m_current_value == m_default_value; } + // Subclass specific functions lldb::Format GetCurrentValue() const { return m_current_value; } diff --git a/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h b/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h index c10d56cbeb70b..bbc1f8c1eec43 100644 --- a/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h +++ b/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h @@ -34,6 +34,10 @@ class OptionValueFormatEntity void Clear() override; + bool IsDefault() const override { + return m_current_format == m_default_format; + } + void AutoComplete(CommandInterpreter &interpreter, CompletionRequest &request) override; diff --git a/lldb/include/lldb/Interpreter/OptionValueLanguage.h b/lldb/include/lldb/Interpreter/OptionValueLanguage.h index e1c1f85493ad6..41ddb2a13f15e 100644 --- a/lldb/include/lldb/Interpreter/OptionValueLanguage.h +++ b/lldb/include/lldb/Interpreter/OptionValueLanguage.h @@ -44,6 +44,8 @@ class OptionValueLanguage : public Cloneable<OptionValueLanguage, OptionValue> { m_value_was_set = false; } + bool IsDefault() const override { return m_current_value == m_default_value; } + // Subclass specific functions lldb::LanguageType GetCurrentValue() const { return m_current_value; } diff --git a/lldb/include/lldb/Interpreter/OptionValueProperties.h b/lldb/include/lldb/Interpreter/OptionValueProperties.h index 21da8e584a7b4..d9b6c4764f4a4 100644 --- a/lldb/include/lldb/Interpreter/OptionValueProperties.h +++ b/lldb/include/lldb/Interpreter/OptionValueProperties.h @@ -46,6 +46,8 @@ class OptionValueProperties void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + bool IsDefault() const override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) const override; llvm::StringRef GetName() const override { return m_name; } diff --git a/lldb/include/lldb/Interpreter/OptionValueRegex.h b/lldb/include/lldb/Interpreter/OptionValueRegex.h index b952cb2476012..2799fea1538dc 100644 --- a/lldb/include/lldb/Interpreter/OptionValueRegex.h +++ b/lldb/include/lldb/Interpreter/OptionValueRegex.h @@ -41,6 +41,10 @@ class OptionValueRegex : public Cloneable<OptionValueRegex, OptionValue> { m_value_was_set = false; } + bool IsDefault() const override { + return m_regex.GetText() == m_default_regex_str; + } + // Subclass specific functions const RegularExpression *GetCurrentValue() const { return (m_regex.IsValid() ? &m_regex : nullptr); diff --git a/lldb/include/lldb/Interpreter/OptionValueSInt64.h b/lldb/include/lldb/Interpreter/OptionValueSInt64.h index c220ac29e461f..f19f3f8ab875e 100644 --- a/lldb/include/lldb/Interpreter/OptionValueSInt64.h +++ b/lldb/include/lldb/Interpreter/OptionValueSInt64.h @@ -48,6 +48,8 @@ class OptionValueSInt64 : public Cloneable<OptionValueSInt64, OptionValue> { m_value_was_set = false; } + bool IsDefault() const override { return m_current_value == m_default_value; } + // Subclass specific functions const int64_t &operator=(int64_t value) { diff --git a/lldb/include/lldb/Interpreter/OptionValueString.h b/lldb/include/lldb/Interpreter/OptionValueString.h index 4ec98176b6f8b..e199443fa8b49 100644 --- a/lldb/include/lldb/Interpreter/OptionValueString.h +++ b/lldb/include/lldb/Interpreter/OptionValueString.h @@ -82,6 +82,8 @@ class OptionValueString : public Cloneable<OptionValueString, OptionValue> { m_value_was_set = false; } + bool IsDefault() const override { return m_current_value == m_default_value; } + // Subclass specific functions Flags &GetOptions() { return m_options; } diff --git a/lldb/include/lldb/Interpreter/OptionValueUInt64.h b/lldb/include/lldb/Interpreter/OptionValueUInt64.h index 087c1d3ee321a..2a87c19c54bbf 100644 --- a/lldb/include/lldb/Interpreter/OptionValueUInt64.h +++ b/lldb/include/lldb/Interpreter/OptionValueUInt64.h @@ -51,6 +51,8 @@ class OptionValueUInt64 : public Cloneable<OptionValueUInt64, OptionValue> { m_value_was_set = false; } + bool IsDefault() const override { return m_current_value == m_default_value; } + // Subclass specific functions const uint64_t &operator=(uint64_t value) { diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp index 126f57c738115..2e7916431df10 100644 --- a/lldb/source/Commands/CommandObjectSettings.cpp +++ b/lldb/source/Commands/CommandObjectSettings.cpp @@ -264,6 +264,9 @@ class CommandObjectSettingsShow : public CommandObjectParsed { case 'd': m_include_defaults = true; break; + case 'c': + m_only_changed = true; + break; default: llvm_unreachable("Unimplemented option"); } @@ -272,6 +275,7 @@ class CommandObjectSettingsShow : public CommandObjectParsed { void OptionParsingStarting(ExecutionContext *execution_context) override { m_include_defaults = false; + m_only_changed = false; } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { @@ -279,6 +283,7 @@ class CommandObjectSettingsShow : public CommandObjectParsed { } bool m_include_defaults = false; + bool m_only_changed = false; }; protected: @@ -288,9 +293,18 @@ class CommandObjectSettingsShow : public CommandObjectParsed { uint32_t dump_mask = OptionValue::eDumpGroupValue; if (m_options.m_include_defaults) dump_mask |= OptionValue::eDumpOptionDefaultValue; + if (m_options.m_only_changed) + dump_mask |= OptionValue::eDumpOptionOnlyChanged; if (!args.empty()) { for (const auto &arg : args) { + if (m_options.m_only_changed) { + Status lookup_error; + lldb::OptionValueSP value_sp = GetDebugger().GetPropertyValue( + &m_exe_ctx, arg.ref(), lookup_error); + if (value_sp && value_sp->IsDefault()) + continue; + } Status error(GetDebugger().DumpPropertyValue( &m_exe_ctx, result.GetOutputStream(), arg.ref(), dump_mask)); if (error.Success()) { diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index ba6781dcab04e..123ba7bdb257e 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -71,6 +71,9 @@ let Command = "settings clear" in { let Command = "settings show" in { def setshow_defaults : Option<"defaults", "d">, Desc<"Include ${d}efault values if defined.">; + def setshow_changed : Option<"changed", "c">, + Desc<"Only show settings whose value differs from the " + "default.">; } let Command = "breakpoint list" in { diff --git a/lldb/source/Interpreter/OptionValueProperties.cpp b/lldb/source/Interpreter/OptionValueProperties.cpp index def6cc462f76a..0034e79018727 100644 --- a/lldb/source/Interpreter/OptionValueProperties.cpp +++ b/lldb/source/Interpreter/OptionValueProperties.cpp @@ -342,6 +342,8 @@ void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx, if (property) { OptionValue *option_value = property->GetValue().get(); assert(option_value); + if ((dump_mask & eDumpOptionOnlyChanged) && option_value->IsDefault()) + continue; const bool transparent_value = option_value->ValueIsTransparent(); property->Dump(exe_ctx, strm, dump_mask); if (!transparent_value) @@ -350,6 +352,15 @@ void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx, } } +bool OptionValueProperties::IsDefault() const { + for (const Property &property : m_properties) { + if (OptionValue *value = property.GetValue().get()) + if (!value->IsDefault()) + return false; + } + return true; +} + llvm::json::Value OptionValueProperties::ToJSON(const ExecutionContext *exe_ctx) const { llvm::json::Object json_properties; diff --git a/lldb/test/API/commands/settings/TestSettings.py b/lldb/test/API/commands/settings/TestSettings.py index 8410befe399a3..1cad6f8f2fa3f 100644 --- a/lldb/test/API/commands/settings/TestSettings.py +++ b/lldb/test/API/commands/settings/TestSettings.py @@ -237,6 +237,54 @@ def test_set_auto_confirm(self): startstr="auto-confirm (boolean) = false", ) + def test_settings_show_changed(self): + """Test `settings show --changed` filters the listing to non-default values.""" + setting = "target.max-children-count" + + def cleanup(): + self.runCmd("settings clear %s" % setting, check=False) + + self.addTearDownHook(cleanup) + + # Ensure a clean slate for this setting. + self.runCmd("settings clear %s" % setting) + + # With the setting at its default, it should not show up under --changed. + self.expect( + "settings show --changed", + matching=False, + substrs=[setting], + ) + + # After explicitly changing the setting, it should show up. + self.runCmd("settings set %s 42" % setting) + self.expect( + "settings show --changed", + substrs=["%s (unsigned) = 42" % setting], + ) + + # After clearing, it should no longer show up. + self.runCmd("settings clear %s" % setting) + self.expect( + "settings show --changed", + matching=False, + substrs=[setting], + ) + + # An explicit property path at its default prints nothing. + self.expect( + "settings show --changed %s" % setting, + matching=False, + substrs=[setting], + ) + + # When the value has been changed, the explicit path prints normally. + self.runCmd("settings set %s 42" % setting) + self.expect( + "settings show --changed %s" % setting, + substrs=["%s (unsigned) = 42" % setting], + ) + @skipIf(archs=no_match(["x86_64", "i386", "i686"])) def test_disassembler_settings(self): """Test that user options for the disassembler take effect.""" `````````` </details> https://github.com/llvm/llvm-project/pull/196390 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
