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

Reply via email to