[Lldb-commits] [lldb] Make env and source map dictionaries #95137 (PR #106919)

via lldb-commits lldb-commits at lists.llvm.org
Mon Sep 2 15:57:09 PDT 2024


https://github.com/Da-Viper updated https://github.com/llvm/llvm-project/pull/106919

>From d2bddca1753b4c960895f51d7eb80b6efa7dc986 Mon Sep 17 00:00:00 2001
From: Ezike Ebuka <yerimyah1 at gmail.com>
Date: Sun, 1 Sep 2024 17:26:11 +0100
Subject: [PATCH 1/3] [lldb-dap] Make environment option an object

---
 .../tools/lldb-dap/launch/TestDAP_launch.py   |  4 +-
 lldb/tools/lldb-dap/JSONUtils.cpp             | 40 ++++++++++++++++---
 lldb/tools/lldb-dap/JSONUtils.h               | 22 ++++++++++
 lldb/tools/lldb-dap/README.md                 |  5 ++-
 lldb/tools/lldb-dap/lldb-dap.cpp              |  8 +++-
 lldb/tools/lldb-dap/package.json              | 11 +++--
 6 files changed, 77 insertions(+), 13 deletions(-)

diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
index a16f2da3c4df71..6b9993a2548b8d 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -229,7 +229,7 @@ def test_environment(self):
         Tests launch of a simple program with environment variables
         """
         program = self.getBuildArtifact("a.out")
-        env = ["NO_VALUE", "WITH_VALUE=BAR", "EMPTY_VALUE=", "SPACE=Hello World"]
+        env = {"NO_VALUE": "", "WITH_VALUE":"BAR", "EMPTY_VALUE": "", "SPACE": "Hello World"}
         self.build_and_launch(program, env=env)
         self.continue_to_exit()
 
@@ -242,7 +242,7 @@ def test_environment(self):
             lines.pop(0)
         # Make sure each environment variable in "env" is actually set in the
         # program environment that was printed to STDOUT
-        for var in env:
+        for var in env.keys():
             found = False
             for program_var in lines:
                 if var in program_var:
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 7338e7cf41eb03..29b3ad490af0b6 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -136,6 +136,31 @@ std::vector<std::string> GetStrings(const llvm::json::Object *obj,
   return strs;
 }
 
+std::unordered_map<std::string, std::string>
+GetStringMap(const llvm::json::Object &obj, llvm::StringRef key) {
+  std::unordered_map<std::string, std::string> strs;
+  const auto *const json_object = obj.getObject(key);
+  if (!json_object)
+    return strs;
+
+  for (const auto &[key, value] : *json_object) {
+    switch (value.kind()) {
+    case llvm::json::Value::String:
+      strs.emplace(key.str(), value.getAsString()->str());
+      break;
+    case llvm::json::Value::Number:
+    case llvm::json::Value::Boolean:
+      strs.emplace(key.str(), llvm::to_string(value));
+      break;
+    case llvm::json::Value::Null:
+    case llvm::json::Value::Object:
+    case llvm::json::Value::Array:
+      break;
+    }
+  }
+  return strs;
+}
+
 static bool IsClassStructOrUnionType(lldb::SBType t) {
   return (t.GetTypeClass() & (lldb::eTypeClassUnion | lldb::eTypeClassStruct |
                               lldb::eTypeClassArray)) != 0;
@@ -1370,13 +1395,16 @@ CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request,
   if (!cwd.empty())
     run_in_terminal_args.try_emplace("cwd", cwd);
 
-  // We need to convert the input list of environments variables into a
-  // dictionary
-  std::vector<std::string> envs = GetStrings(launch_request_arguments, "env");
+  std::unordered_map<std::string, std::string> envMap =
+      GetStringMap(*launch_request_arguments, "env");
   llvm::json::Object environment;
-  for (const std::string &env : envs) {
-    size_t index = env.find('=');
-    environment.try_emplace(env.substr(0, index), env.substr(index + 1));
+  for (const auto &[key, value] : envMap) {
+    if (key.empty())
+      g_dap.SendOutput(OutputType::Stderr,
+                       "empty environment variable for value: \"" + value +
+                           '\"');
+    else
+      environment.try_emplace(key, value);
   }
   run_in_terminal_args.try_emplace("env",
                                    llvm::json::Value(std::move(environment)));
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index b6356630b72682..60d5db06560657 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -16,6 +16,7 @@
 #include "llvm/Support/JSON.h"
 #include <cstdint>
 #include <optional>
+#include <unordered_map>
 
 namespace lldb_dap {
 
@@ -152,6 +153,27 @@ bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key);
 std::vector<std::string> GetStrings(const llvm::json::Object *obj,
                                     llvm::StringRef key);
 
+/// Extract an object of key value strings for the specified key from an object.
+///
+/// String values in the object will be extracted without any quotes
+/// around them. Numbers and Booleans will be converted into
+/// strings. Any NULL, array or objects values in the array will be
+/// ignored.
+///
+/// \param[in] obj
+///     A JSON object that we will attempt to extract the array from
+///
+/// \param[in] key
+///     The key to use when extracting the value
+///
+/// \return
+///     An object of key value strings for the specified \a key, or
+///     \a fail_value if there is no key that matches or if the
+///     value is not an object or key and values in the object are not
+///     strings, numbers or booleans.
+std::unordered_map<std::string, std::string>
+GetStringMap(const llvm::json::Object &obj, llvm::StringRef key);
+
 /// Fill a response object given the request object.
 ///
 /// The \a response object will get its "type" set to "response",
diff --git a/lldb/tools/lldb-dap/README.md b/lldb/tools/lldb-dap/README.md
index 11a14d29ab51e2..5b6fc5ef990e60 100644
--- a/lldb/tools/lldb-dap/README.md
+++ b/lldb/tools/lldb-dap/README.md
@@ -77,7 +77,10 @@ adds `FOO=1` and `bar` to the environment:
   "name": "Debug",
   "program": "/tmp/a.out",
   "args": [ "one", "two", "three" ],
-  "env": [ "FOO=1", "BAR" ],
+  "env": {
+    "FOO": "1"
+    "BAR": ""
+  }
 }
 ```
 
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index c5c4b09f15622b..da0935dff69878 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -1831,7 +1831,13 @@ lldb::SBError LaunchProcess(const llvm::json::Object &request) {
     launch_info.SetArguments(MakeArgv(args).data(), true);
 
   // Pass any environment variables along that the user specified.
-  auto envs = GetStrings(arguments, "env");
+  auto envMap = GetStringMap(*arguments, "env");
+  std::vector<std::string> envs;
+  envs.reserve(envMap.size());
+  for (const auto &[key, value] : envMap) {
+    envs.emplace_back(key + '=' + value);
+  }
+
   if (!envs.empty())
     launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
 
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index 4f4261d1718c01..3867302a841913 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -160,9 +160,14 @@
                 "default": "${workspaceRoot}"
               },
               "env": {
-                "type": "array",
-                "description": "Additional environment variables to set when launching the program. This is an array of strings that contains the variable name followed by an optional '=' character and the environment variable's value.",
-                "default": []
+                "type": "object",
+                "description": "Additional environment variables to set when launching the program. E.g. `{ \"FOO\": \"1\" }`",
+                "patternProperties": {
+                  ".*": {
+                    "type": "string"
+                  }
+                },
+                "default": {}
               },
               "stopOnEntry": {
                 "type": "boolean",

>From a3827ed57f655ab803fa28ea7f97e5274322bf0e Mon Sep 17 00:00:00 2001
From: Ezike Ebuka <yerimyah1 at gmail.com>
Date: Mon, 2 Sep 2024 14:25:07 +0100
Subject: [PATCH 2/3] [lldb-dap] format python test code

---
 lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
index 6b9993a2548b8d..a56ad032772cbb 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -229,7 +229,12 @@ def test_environment(self):
         Tests launch of a simple program with environment variables
         """
         program = self.getBuildArtifact("a.out")
-        env = {"NO_VALUE": "", "WITH_VALUE":"BAR", "EMPTY_VALUE": "", "SPACE": "Hello World"}
+        env = {
+            "NO_VALUE": "",
+            "WITH_VALUE": "BAR",
+            "EMPTY_VALUE": "",
+            "SPACE": "Hello World",
+        }
         self.build_and_launch(program, env=env)
         self.continue_to_exit()
 

>From b0dcf84e0b38dd69813f3aa0f827fb5a70d369f8 Mon Sep 17 00:00:00 2001
From: Ezike Ebuka <yerimyah1 at gmail.com>
Date: Mon, 2 Sep 2024 23:56:40 +0100
Subject: [PATCH 3/3] [lldb-dap] Clean: use Environment class instead of manual
 concatenation

---
 lldb/tools/lldb-dap/lldb-dap.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index da0935dff69878..7df84bd72794fd 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -51,6 +51,7 @@
 #include <thread>
 #include <vector>
 
+#include "lldb/API/SBEnvironment.h"
 #include "lldb/API/SBStream.h"
 #include "lldb/Host/Config.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -1832,14 +1833,13 @@ lldb::SBError LaunchProcess(const llvm::json::Object &request) {
 
   // Pass any environment variables along that the user specified.
   auto envMap = GetStringMap(*arguments, "env");
-  std::vector<std::string> envs;
-  envs.reserve(envMap.size());
+  lldb::SBEnvironment envs{};
   for (const auto &[key, value] : envMap) {
-    envs.emplace_back(key + '=' + value);
+    envs.Set(key.c_str(), value.c_str(), true);
   }
 
-  if (!envs.empty())
-    launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
+  if (envs.GetNumValues() != 0)
+    launch_info.SetEnvironment(envs, true);
 
   auto flags = launch_info.GetLaunchFlags();
 



More information about the lldb-commits mailing list