Skip to content

Commit 0cd2218

Browse files
committed
[lldb] Add JSON serialization for FileSpec and FileSpecList
Add a `ToJSON` method in FileSpec and OptionValueFileSpecList to enable JSON serialization. Fixes #110756
1 parent bdfcf3a commit 0cd2218

File tree

4 files changed

+71
-45
lines changed

4 files changed

+71
-45
lines changed

lldb/include/lldb/Interpreter/OptionValueFileSpecList.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class OptionValueFileSpecList
3333
void DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
3434
uint32_t dump_mask) override;
3535

36+
llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override;
37+
3638
Status
3739
SetValueFromString(llvm::StringRef value,
3840
VarSetOperationType op = eVarSetOperationAssign) override;

lldb/include/lldb/Utility/FileSpec.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/ADT/StringRef.h"
1919
#include "llvm/Support/FileSystem.h"
2020
#include "llvm/Support/FormatVariadic.h"
21+
#include "llvm/Support/JSON.h"
2122
#include "llvm/Support/Path.h"
2223

2324
#include <cstddef>
@@ -214,6 +215,17 @@ class FileSpec {
214215
/// The stream to which to dump the object description.
215216
void Dump(llvm::raw_ostream &s) const;
216217

218+
///
219+
/// Convert the filespec object to a json value.
220+
///
221+
/// Convert the filespec object to a json value. If the object contains a
222+
/// valid directory name, it will be displayed followed by a directory
223+
/// delimiter, and the filename.
224+
///
225+
/// \return
226+
/// A json value representation of a filespec.
227+
llvm::json::Value ToJSON() const;
228+
217229
Style GetPathStyle() const;
218230

219231
/// Directory string const get accessor.
@@ -232,7 +244,6 @@ class FileSpec {
232244
/// Clear the directory in this object.
233245
void ClearDirectory();
234246

235-
236247
/// Filename string const get accessor.
237248
///
238249
/// \return
@@ -413,11 +424,7 @@ class FileSpec {
413424
/// state in this object.
414425
void PathWasModified() { m_absolute = Absolute::Calculate; }
415426

416-
enum class Absolute : uint8_t {
417-
Calculate,
418-
Yes,
419-
No
420-
};
427+
enum class Absolute : uint8_t { Calculate, Yes, No };
421428

422429
/// The unique'd directory path.
423430
ConstString m_directory;

lldb/source/Interpreter/OptionValueFileSpecList.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
4141
}
4242
}
4343

44+
llvm::json::Value
45+
OptionValueFileSpecList::ToJSON(const ExecutionContext *exe_ctx) {
46+
std::lock_guard<std::recursive_mutex> lock(m_mutex);
47+
llvm::json::Array spec_list;
48+
for (const auto &file_spec : m_current_value) {
49+
spec_list.emplace_back(file_spec.ToJSON());
50+
}
51+
return spec_list;
52+
}
53+
4454
Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
4555
VarSetOperationType op) {
4656
std::lock_guard<std::recursive_mutex> lock(m_mutex);

lldb/source/Utility/FileSpec.cpp

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -118,53 +118,55 @@ bool needsNormalization(const llvm::StringRef &path) {
118118
return true;
119119
for (auto i = path.find_first_of("\\/"); i != llvm::StringRef::npos;
120120
i = path.find_first_of("\\/", i + 1)) {
121-
const auto next = safeCharAtIndex(path, i+1);
121+
const auto next = safeCharAtIndex(path, i + 1);
122122
switch (next) {
123+
case 0:
124+
// path separator char at the end of the string which should be
125+
// stripped unless it is the one and only character
126+
return i > 0;
127+
case '/':
128+
case '\\':
129+
// two path separator chars in the middle of a path needs to be
130+
// normalized
131+
if (i > 0)
132+
return true;
133+
++i;
134+
break;
135+
136+
case '.': {
137+
const auto next_next = safeCharAtIndex(path, i + 2);
138+
switch (next_next) {
139+
default:
140+
break;
123141
case 0:
124-
// path separator char at the end of the string which should be
125-
// stripped unless it is the one and only character
126-
return i > 0;
142+
return true; // ends with "/."
127143
case '/':
128144
case '\\':
129-
// two path separator chars in the middle of a path needs to be
130-
// normalized
131-
if (i > 0)
132-
return true;
133-
++i;
134-
break;
135-
145+
return true; // contains "/./"
136146
case '.': {
137-
const auto next_next = safeCharAtIndex(path, i+2);
138-
switch (next_next) {
139-
default: break;
140-
case 0: return true; // ends with "/."
141-
case '/':
142-
case '\\':
143-
return true; // contains "/./"
144-
case '.': {
145-
const auto next_next_next = safeCharAtIndex(path, i+3);
146-
switch (next_next_next) {
147-
default: break;
148-
case 0: return true; // ends with "/.."
149-
case '/':
150-
case '\\':
151-
return true; // contains "/../"
152-
}
153-
break;
154-
}
155-
}
147+
const auto next_next_next = safeCharAtIndex(path, i + 3);
148+
switch (next_next_next) {
149+
default:
150+
break;
151+
case 0:
152+
return true; // ends with "/.."
153+
case '/':
154+
case '\\':
155+
return true; // contains "/../"
156156
}
157157
break;
158+
}
159+
}
160+
} break;
158161

159-
default:
160-
break;
162+
default:
163+
break;
161164
}
162165
}
163166
return false;
164167
}
165168

166-
167-
}
169+
} // namespace
168170

169171
void FileSpec::SetFile(llvm::StringRef pathname) { SetFile(pathname, m_style); }
170172

@@ -199,11 +201,11 @@ void FileSpec::SetFile(llvm::StringRef pathname, Style style) {
199201
// Split path into filename and directory. We rely on the underlying char
200202
// pointer to be nullptr when the components are empty.
201203
llvm::StringRef filename = llvm::sys::path::filename(resolved, m_style);
202-
if(!filename.empty())
204+
if (!filename.empty())
203205
m_filename.SetString(filename);
204206

205207
llvm::StringRef directory = llvm::sys::path::parent_path(resolved, m_style);
206-
if(!directory.empty())
208+
if (!directory.empty())
207209
m_directory.SetString(directory);
208210
}
209211

@@ -330,6 +332,13 @@ void FileSpec::Dump(llvm::raw_ostream &s) const {
330332
s << path_separator;
331333
}
332334

335+
llvm::json::Value FileSpec::ToJSON() const {
336+
std::string file_spec{};
337+
llvm::raw_string_ostream stream(file_spec);
338+
this->Dump(stream);
339+
return llvm::json::Value(std::move(file_spec));
340+
}
341+
333342
FileSpec::Style FileSpec::GetPathStyle() const { return m_style; }
334343

335344
void FileSpec::SetDirectory(ConstString directory) {
@@ -504,9 +513,7 @@ bool FileSpec::IsSourceImplementationFile() const {
504513
return g_source_file_regex.Execute(extension);
505514
}
506515

507-
bool FileSpec::IsRelative() const {
508-
return !IsAbsolute();
509-
}
516+
bool FileSpec::IsRelative() const { return !IsAbsolute(); }
510517

511518
bool FileSpec::IsAbsolute() const {
512519
// Check if we have cached if this path is absolute to avoid recalculating.

0 commit comments

Comments
 (0)